├── .env
├── .env.example
├── .eslintignore
├── .eslintrc.json
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── .vscode
├── CharacterCreator.code-workspace
└── settings.json
├── LICENSE
├── README.md
├── cert.pem
├── index.html
├── key.pem
├── package.json
├── public
├── 3d
│ ├── Platform.glb
│ ├── animations
│ │ ├── idle_drophunter.fbx
│ │ ├── idle_drophunter2.fbx
│ │ ├── idle_neurohacker.fbx
│ │ ├── idle_neurohacker2.fbx
│ │ └── idle_sword.fbx
│ ├── icons-gradient
│ │ ├── accessories.svg
│ │ ├── chest.svg
│ │ ├── color.svg
│ │ ├── eyes.svg
│ │ ├── feet.svg
│ │ ├── gender.svg
│ │ ├── head.svg
│ │ ├── legs.svg
│ │ ├── outer.svg
│ │ ├── sampleColors.svg
│ │ └── skin.svg
│ ├── icons
│ │ ├── Rectangle.png
│ │ ├── accessories.png
│ │ ├── body.png
│ │ ├── color.png
│ │ ├── eye.png
│ │ ├── female-body-1.png
│ │ ├── hairStyle.png
│ │ ├── head.png
│ │ ├── jacket.png
│ │ ├── legs.png
│ │ ├── male-body-1.png
│ │ ├── shoes.png
│ │ ├── shuffle.png
│ │ ├── skin-color.png
│ │ ├── torso.png
│ │ ├── webaMark 1.png
│ │ └── webaMark.png
│ ├── models
│ │ ├── drophunter.vrm
│ │ ├── landing
│ │ │ ├── drop-noWeapon.vrm
│ │ │ └── neuro-noWeapon.vrm
│ │ └── neurohacker.vrm
│ └── ot.glb
├── DropHunter.svg
├── Neurohacker.svg
├── Rotation.json
├── assets
│ ├── backgrounds
│ │ ├── class-frame.svg
│ │ ├── class-mask.svg
│ │ ├── main-background.jpg
│ │ ├── main-background2.jpg
│ │ ├── profile-no-image.png
│ │ ├── token-box-common.svg
│ │ ├── token-box-epic.svg
│ │ ├── token-box-mythic.svg
│ │ ├── token-box-none.svg
│ │ ├── token-box-rare.svg
│ │ ├── token-box-uncommon.svg
│ │ └── token-frame-active.svg
│ ├── icons
│ │ ├── accessories.svg
│ │ ├── aqualith.png
│ │ ├── arrowBack.svg
│ │ ├── arrowLeft.svg
│ │ ├── arrowRight.svg
│ │ ├── backpack.svg
│ │ ├── chest.svg
│ │ ├── class-beast-painter.svg
│ │ ├── class-bruiser.svg
│ │ ├── class-custom.svg
│ │ ├── class-drop-hunter.svg
│ │ ├── class-engineer.svg
│ │ ├── class-lisk-witch.svg
│ │ ├── class-neural-hacker.svg
│ │ ├── class-the-degen.svg
│ │ ├── close.svg
│ │ ├── crown.svg
│ │ ├── discord.svg
│ │ ├── download.svg
│ │ ├── exclamation.svg
│ │ ├── exp.svg
│ │ ├── expandLeft.svg
│ │ ├── expandRight.svg
│ │ ├── eyes.svg
│ │ ├── feet.svg
│ │ ├── fyrite.png
│ │ ├── head.svg
│ │ ├── health.svg
│ │ ├── hide.svg
│ │ ├── legs.svg
│ │ ├── limit.svg
│ │ ├── locked.svg
│ │ ├── login.svg
│ │ ├── logout.svg
│ │ ├── mana.svg
│ │ ├── map.svg
│ │ ├── metamask.svg
│ │ ├── microphone.svg
│ │ ├── mint.svg
│ │ ├── minus.svg
│ │ ├── mobile.svg
│ │ ├── moonstone.png
│ │ ├── notClaimed.svg
│ │ ├── obsidian.png
│ │ ├── outer.svg
│ │ ├── phone.svg
│ │ ├── phoneActive.svg
│ │ ├── plus.svg
│ │ ├── rooms.svg
│ │ ├── scenes.svg
│ │ ├── settings.svg
│ │ ├── silk.png
│ │ ├── skin.svg
│ │ ├── slotBody.svg
│ │ ├── slotHead.svg
│ │ ├── slotLeftHand.svg
│ │ ├── slotLegs.svg
│ │ ├── slotMount.svg
│ │ ├── slotRightHand.svg
│ │ ├── soundoff.svg
│ │ ├── soundon.svg
│ │ ├── speechToText.svg
│ │ ├── tokens.svg
│ │ ├── venturine.png
│ │ ├── voice.svg
│ │ └── vr.svg
│ └── media
│ │ ├── DropHunter.png
│ │ ├── NeuralHacker.png
│ │ ├── btn_create_character.png
│ │ ├── btn_load_character.png
│ │ ├── degens.gif
│ │ └── disabled.png
├── city.hdr
├── fonts
│ └── tt-squares
│ │ ├── TT Squares Condensed Black Italic.otf
│ │ ├── TT Squares Condensed Black.otf
│ │ ├── TT Squares Condensed Bold Italic.otf
│ │ ├── TT Squares Condensed Bold.otf
│ │ ├── TT Squares Condensed Light Italic.otf
│ │ ├── TT Squares Condensed Light.otf
│ │ ├── TT Squares Condensed Regular Italic.otf
│ │ ├── TT Squares Condensed Regular.otf
│ │ ├── TT Squares Condensed Thin italic.otf
│ │ └── TT Squares Condensed Thin.otf
├── icons
│ ├── back.svg
│ ├── download.svg
│ └── webaverse.gif
├── main-background.jpg
├── scripts
│ └── compile-sounds.sh
├── sound
│ ├── background
│ │ ├── cc_bgm.wav
│ │ └── cc_bgm_balanced.wav
│ ├── effect
│ │ ├── character-load.wav
│ │ ├── class-select.wav
│ │ └── switchingItem.wav
│ ├── sound-files.json
│ ├── sounds.mp3
│ └── ui
│ │ ├── back-next-button.wav
│ │ ├── class-mouse-over.wav
│ │ ├── class_click.wav
│ │ ├── class_pass.wav
│ │ ├── option_click.wav
│ │ ├── randomize-button.wav
│ │ └── section_click.wav
├── style.css
├── textures
│ ├── beam2.png
│ ├── noise3.jpg
│ └── pixel9.png
└── ui
│ ├── ChatOff.svg
│ ├── ChatOn.svg
│ ├── DropHunter.svg
│ ├── Equip.svg
│ ├── MicChat.svg
│ ├── MicOff.svg
│ ├── MicOn.svg
│ ├── Neurohacker.svg
│ ├── aroff.svg
│ ├── aron.svg
│ ├── arrow.svg
│ ├── backButton_gray.png
│ ├── backButton_white.png
│ ├── background.png
│ ├── connectWallet.svg
│ ├── diconnectWallet.svg
│ ├── download.svg
│ ├── landing
│ └── logo.png
│ ├── loading.svg
│ ├── loading
│ └── webaMark.svg
│ ├── mainBackground.png
│ ├── mint.svg
│ ├── mint
│ ├── ethereum.png
│ ├── mintPopup.png
│ ├── polygon.png
│ └── walletError.png
│ ├── rotate-cancel.png
│ ├── rotate.png
│ ├── selector
│ ├── cancel.png
│ └── tick.svg
│ ├── skinSelector
│ └── Vector.png
│ ├── soundoff.svg
│ ├── soundon.svg
│ ├── traits
│ ├── Eye 2.png
│ ├── Layer_2.png
│ ├── Rectangle.png
│ ├── accessories.png
│ ├── body.png
│ ├── hairColor.png
│ ├── hairStyle.png
│ ├── head.png
│ ├── legs.png
│ ├── shoes.png
│ ├── shuffle.svg
│ ├── skin-color.png
│ ├── torso.png
│ └── webaMark.png
│ ├── weba.png
│ └── webadark.png
├── src
├── App.jsx
├── Main.jsx
├── components
│ ├── ARButton.jsx
│ ├── ARButton.module.css
│ ├── App.module.css
│ ├── AudioButton.jsx
│ ├── AudioButton.module.css
│ ├── BackButton.jsx
│ ├── BackButton.module.css
│ ├── Background.jsx
│ ├── Background.module.css
│ ├── Chat.jsx
│ ├── Chat.module.css
│ ├── ChatButton.jsx
│ ├── Contract.jsx
│ ├── Editor.jsx
│ ├── Editor.module.css
│ ├── ExportMenu.jsx
│ ├── ExportMenu.module.css
│ ├── LanguageSwitch.jsx
│ ├── LanguageSwitch.module.css
│ ├── LoadingOverlay.jsx
│ ├── LoadingOverlay.module.css
│ ├── Logo.css
│ ├── Logo.jsx
│ ├── Mint.jsx
│ ├── Mint.module.css
│ ├── Resizable.jsx
│ ├── Resizable.module.css
│ ├── Scene.jsx
│ ├── Scene.module.css
│ ├── Selector.jsx
│ ├── Selector.module.css
│ ├── custom-button
│ │ ├── CustomButton.module.css
│ │ ├── IconCollection.jsx
│ │ └── index.jsx
│ ├── message
│ │ ├── Message.module.css
│ │ └── index.jsx
│ └── token-box
│ │ ├── TokenBox.jsx
│ │ ├── TokenBox.module.css
│ │ └── index.jsx
├── constants
│ ├── favouriteColors.js
│ └── voices.js
├── context
│ ├── AccountContext.jsx
│ ├── AudioContext.jsx
│ ├── LanguageContext.jsx
│ ├── SceneContext.jsx
│ ├── SoundContext.jsx
│ └── ViewContext.jsx
├── favicon.ico
├── lib
│ ├── chat.js
│ └── localization
│ │ ├── i18n.js
│ │ └── translations.json
├── library
│ ├── VRMExporter.js
│ ├── VRMExporterv0.js
│ ├── animationManager.js
│ ├── ar.js
│ ├── blinkManager.js
│ ├── constants.js
│ ├── create-texture-atlas.js
│ ├── cull-mesh.js
│ ├── download-utils.js
│ ├── effectManager.js
│ ├── gltf-cubic-spline-interpolant.js
│ ├── lipsync.js
│ ├── lookatManager.js
│ ├── merge-geometry.js
│ ├── option-utils.js
│ ├── particle
│ │ ├── mesh.js
│ │ ├── particle.js
│ │ ├── shader.js
│ │ └── utils.js
│ └── utils.js
├── pages
│ ├── Appearance.jsx
│ ├── Appearance.module.css
│ ├── Bio.jsx
│ ├── Bio.module.css
│ ├── Create.jsx
│ ├── Create.module.css
│ ├── Landing.jsx
│ ├── Landing.module.css
│ ├── Load.jsx
│ ├── Load.module.css
│ ├── Mint.jsx
│ ├── Mint.module.css
│ ├── Save.jsx
│ ├── Save.module.css
│ ├── View.jsx
│ └── View.module.css
└── services
│ └── contract.jsx
├── vite.config.js
└── yarn.lock
/.env:
--------------------------------------------------------------------------------
1 | VITE_PINATA_API_KEY=bf7ebd9ad32c11abe43c
2 | VITE_PINATA_API_SECRET=c6fa7b8b056d0cf2e467e0ebbdc38ae889b96c59f06992ae831e2a25e52e5006
3 | VITE_ALCHEMY_API_KEY=OOWUrxHDTRyPmbYOSGyq7izHNQB1QYOv
4 | VITE_ASSET_PATH=https://webaverse-studios.github.io/character-assets
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | VITE_PINATA_API_KEY=05efa6dda750457f9c78
2 | VITE_PINATA_API_SECRET=f2b51a2d960d6c2ab02163cd57979fe4e47b6287f048ae47ff8967f27623308b
3 | VITE_ALCHEMY_API_KEY=OOWUrxHDTRyPmbYOSGyq7izHNQB1QYOv
4 | VITE_ASSET_PATH=https://webaverse-studios.github.io/character-assets
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 | .prettierrc.js
4 | .eslintrc.js
5 | env.d.ts
6 | *.png
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2021": true
5 | },
6 | "extends": [
7 | "eslint:recommended",
8 | "plugin:react/recommended"
9 | ],
10 | "parserOptions": {
11 | "ecmaFeatures": {
12 | "jsx": true
13 | },
14 | "sourceType": "module"
15 | },
16 | "plugins": [
17 | "react",
18 | "eslint-plugin-no-inline-styles"
19 | ],
20 | "rules": {
21 | "react/prop-types": "off"
22 | },
23 | "ignorePatterns": ["node_modules/*", "*.png", "character-assets/"]
24 | }
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | on:
2 | # When someone push or merge a pull request
3 | # inside the main branch
4 | push:
5 | # branches:
6 | # - main
7 | # When someone create a pull request from
8 | # the main branch
9 | pull_request:
10 | branches:
11 | - main
12 |
13 | jobs:
14 | check-quality:
15 | runs-on: ubuntu-latest
16 | name: Running Code Quality Analysis
17 | steps:
18 | - name: Configure GH Checkout
19 | # Ready-to-use action made by GH or third party
20 | # companies
21 | # We can recognize the GH actions from the third party
22 | # ones checking the name prefix.
23 | # `actions/` = GH
24 | # `something-else/` = third party
25 | # This is a GH ready-to-use action
26 | uses: actions/checkout@v2
27 |
28 | - name: Install Node Modules
29 | # Run the lint custom NPM command that triggers the
30 | # ESLint linter check
31 | run: npm install --force
32 |
33 | - name: Run ESLint
34 | # Run the lint custom NPM command that triggers the
35 | # ESLint linter check
36 | run: npm run lint:js
37 |
38 | - name: Check code meets quality standards
39 | id: code-inspector
40 | uses: codeinspectorio/github-action@master
41 | with:
42 | repo_token: ${{ secrets.GITHUB_TOKEN }}
43 | code_inspector_api_token: ${{ secrets.CODE_INSPECTOR_API_TOKEN }}
44 | force_ref: 'none'
45 | min_quality_grade: 'WARNING'
46 | min_quality_score: '50'
47 | max_defects_rate: '0.0001'
48 | max_complex_functions_rate: '0.0001'
49 | max_long_functions_rate: '0.0001'
50 | project_name: ''
51 | max_timeout_sec: '600'
52 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | build
2 | coverage
3 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": false,
3 | "trailingComma": "all",
4 | "semi": false
5 | }
6 |
--------------------------------------------------------------------------------
/.vscode/CharacterCreator.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": ".."
5 | }
6 | ],
7 | "settings": {
8 | "editor.formatOnSave": false
9 | }
10 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Atlas Foundation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Webaverse Character Studio
2 | An open, collaborative and evolving 3D avatar studio for the open metaverse.
3 |
4 | # Quick Start
5 | ```bash
6 | # Clone the repo and change directory into it
7 | git clone https://github.com/webaverse-studios/CharacterCreator
8 | cd CharacterCreator
9 |
10 | # Install dependencies with legacy peer deps flag to ignore React errors
11 | npm install --legacy-peer-deps
12 | npm run dev
13 |
14 | # Or use yarn
15 | yarn install
16 | yarn run dev
17 | ```
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Character Studio
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDE6IZDH3Rdf4R4
3 | 2yy+fGbNDDHmywUREBSHOSpS0a6kjDoiv6t9SKJ3su6M1g39GuJUhRBAGrW8bHDd
4 | SHrPcGyQzrg4ED04ZWl697/RIDZ9SLz/g+DsFPv6/TIdjHBt3e9+CRX/LH+8kTYc
5 | 4yu1kBqKM4QRWz0oWzsWJDTSZRwjJXk1p6G5jlsGbk9RuttufBn/N57iqxBDVOXV
6 | TmZIwgVj/GiSbrhyWjzt3PG3Ai6jdd24XUOzpXAPdv7p1WMNNyR1yiiw6INwn5Fh
7 | RN1L9aqFIJr2XDIuWcImvl02uSYt0jOrJuP/igjHlMn+oF4i9Kb2d7zSAAorSoaZ
8 | GhWRlzSlAgMBAAECggEAJqW4zG3dCgjgOFRUWOLTzoUJOlI4oVu1m8DVlMHA9Fzt
9 | gCp8fy+Fa9b7yTquLjJbn9kqElrrtprWICh8qkBXnqhkMeTGD06gQFlmFaar6zUe
10 | m0wIFm4b8uxFLNWGr5myytr/rUDPpXQe2dagmpc5Dk0EK9/rhgM5+qOKlozv09nL
11 | j30PREkvCkxCBpUAaPWc5mgRjgd4Er1oxjNbkDnPtCt9MsyBRF3LwttE4AX1UqpR
12 | M5jgtc68p9foVKzkOBEDqRz/C4uP1GRLUcyZ9xSfIw64EeZy89ixRynJriJjJIM/
13 | xnt2KNoDVU9k+uqq50WxPcwFeFxRy7Ye4rgDges4NQKBgQDNX4mtm6LxINbgERQP
14 | h71rIy2qDjfbWGUnLzbFLg2mIdbGp0H2WA5ADMJ8os//qBb+DyZJiKq8rfwI0Ogh
15 | 9qCy3bwb+Zl5C8aJsPUfbpc5Lk6et2PlcxLoHrGwLSOlFYPULe1W+O+yu5wurW/T
16 | cwGA3o7GVpFjOIhd1m9GWc5TewKBgQD1cssgSuOlNxq40E3Qig+CD0RzAcQ51FF0
17 | Gn8qGS8/rJllNjEJLOyD4b1XTLOFIB3vmq9HafrzQTpQ5hewAM9op8jJk1+cjjOm
18 | WJCgg/om6XEFIT7vXXxJRE/E0moIXwKj1o90ikBgDRI3ATC+jaB3KiKS7K3WiJAS
19 | 5CoUGaiOXwKBgQDGzhIH1d5wzxpSgxXJRtxNJxugP+1ATxx0Rxcc30zlImK3oNeQ
20 | sYLx66glYLI6yKuhOmcUzdCBn2aX3iqoHgdHvq/G4OL5MzX4ui0/RR3sg3Al4l84
21 | kSGfQ388jSWxO9eGgQL8qzPV8BjrcocKyIyPBGJviwNoaiRPujGzh2HcmwKBgQCW
22 | CEFZz+0vBGv1JH8sRfgMzEBO/Hlxz/KqQbgRh6t2BI8Pavy2WxuH0ejnAB+L9IHY
23 | AHm78XBQWULISJ2aHCSsGEOH0+nRzKqNt/1P4Nx8BJ3tQNEzh7V9I6CO8v+Vdl4q
24 | v/CYkBmhnNvRe4zMLc40iTDxFnN8e6V1prqB5t09iQKBgBuiPDlRcGoRlYmHrrbz
25 | 5VV/+xtvDGWENWBKDrZR7GWE/bpZa2YuE9FfQuXnwu1H3ZZOBBOEHc5PcND8qoE1
26 | NpaatdY7aP/9ivFuVrPbb6siRcqHpnjma5P+vRbg82Jr3l6M+vbneqhkNFY0CKMA
27 | iC3TdI5phnHXIb6QsujVdfOt
28 | -----END PRIVATE KEY-----
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@webaverse-studios/charactercreator",
3 | "version": "0.2.6",
4 | "scripts": {
5 | "dev": "vite --host",
6 | "build": "vite build",
7 | "serve": "vite preview",
8 | "lint": "npm run lint:js && npm run lint:prettier",
9 | "lint:js": "eslint --cache --ext .js,.jsx ./src",
10 | "lint:prettier": "prettier --check \"**/*\" --end-of-line auto"
11 | },
12 | "dependencies": {
13 | "@ethersproject/providers": "^5.5.1",
14 | "@pixiv/three-vrm": "^1.0.6",
15 | "@react-spring/three": "^9.2.4",
16 | "@use-gesture/react": "^10.0.0-beta.22",
17 | "@vitejs/plugin-basic-ssl": "^1.0.1",
18 | "@vitejs/plugin-react": "^3.0.0",
19 | "@web3-react/core": "^6.1.9",
20 | "@web3-react/injected-connector": "^6.0.7",
21 | "@web3-react/network-connector": "^6.1.9",
22 | "axios": "^0.27.2",
23 | "buffer": "^6.0.3",
24 | "classnames": "^2.3.2",
25 | "eslint-config-prettier": "^8.5.0",
26 | "eslint-plugin-import": "^2.26.0",
27 | "ethers": "^5.7.0",
28 | "events": "^3.3.0",
29 | "gsap": "^3.11.3",
30 | "html2canvas": "^1.4.1",
31 | "i18next": "^22.4.10",
32 | "i18next-browser-languagedetector": "^7.0.1",
33 | "load-script": "^1.0.0",
34 | "postprocessing": "^6.29.1",
35 | "react": "^18.2.0",
36 | "react-colorful": "^5.6.1",
37 | "react-dom": "^18.2.0",
38 | "react-i18next": "^12.1.5",
39 | "sepia-speechrecognition-polyfill": "^1.0.0",
40 | "short-uuid": "^4.2.0",
41 | "styled-components": "^5.3.1",
42 | "three": "^0.148.0",
43 | "three-mesh-bvh": "^0.5.21",
44 | "use-sound": "^4.0.1",
45 | "vite-plugin-mkcert": "^1.10.1",
46 | "vite-react-jsx": "1.1.2",
47 | "wrangler": "^2.6.2",
48 | "zustand": "^3.5.10"
49 | },
50 | "peerDependencies": {
51 | "three": "^0.146.0"
52 | },
53 | "devDependencies": {
54 | "@vitejs/plugin-react-swc": "^3.0.0",
55 | "eslint": "^8.30.0",
56 | "eslint-plugin-no-inline-styles": "^1.0.5",
57 | "eslint-plugin-react": "^7.31.11",
58 | "prettier": "^2.3.2",
59 | "vite": "^4.0.0"
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/public/3d/Platform.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/Platform.glb
--------------------------------------------------------------------------------
/public/3d/animations/idle_drophunter.fbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/animations/idle_drophunter.fbx
--------------------------------------------------------------------------------
/public/3d/animations/idle_drophunter2.fbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/animations/idle_drophunter2.fbx
--------------------------------------------------------------------------------
/public/3d/animations/idle_neurohacker.fbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/animations/idle_neurohacker.fbx
--------------------------------------------------------------------------------
/public/3d/animations/idle_neurohacker2.fbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/animations/idle_neurohacker2.fbx
--------------------------------------------------------------------------------
/public/3d/animations/idle_sword.fbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/animations/idle_sword.fbx
--------------------------------------------------------------------------------
/public/3d/icons-gradient/accessories.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/chest.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/color.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/eyes.svg:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/feet.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/gender.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/head.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
52 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/legs.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/outer.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/sampleColors.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
56 |
--------------------------------------------------------------------------------
/public/3d/icons-gradient/skin.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
55 |
--------------------------------------------------------------------------------
/public/3d/icons/Rectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/Rectangle.png
--------------------------------------------------------------------------------
/public/3d/icons/accessories.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/accessories.png
--------------------------------------------------------------------------------
/public/3d/icons/body.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/body.png
--------------------------------------------------------------------------------
/public/3d/icons/color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/color.png
--------------------------------------------------------------------------------
/public/3d/icons/eye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/eye.png
--------------------------------------------------------------------------------
/public/3d/icons/female-body-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/female-body-1.png
--------------------------------------------------------------------------------
/public/3d/icons/hairStyle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/hairStyle.png
--------------------------------------------------------------------------------
/public/3d/icons/head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/head.png
--------------------------------------------------------------------------------
/public/3d/icons/jacket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/jacket.png
--------------------------------------------------------------------------------
/public/3d/icons/legs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/legs.png
--------------------------------------------------------------------------------
/public/3d/icons/male-body-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/male-body-1.png
--------------------------------------------------------------------------------
/public/3d/icons/shoes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/shoes.png
--------------------------------------------------------------------------------
/public/3d/icons/shuffle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/shuffle.png
--------------------------------------------------------------------------------
/public/3d/icons/skin-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/skin-color.png
--------------------------------------------------------------------------------
/public/3d/icons/torso.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/torso.png
--------------------------------------------------------------------------------
/public/3d/icons/webaMark 1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/webaMark 1.png
--------------------------------------------------------------------------------
/public/3d/icons/webaMark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/icons/webaMark.png
--------------------------------------------------------------------------------
/public/3d/models/drophunter.vrm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/models/drophunter.vrm
--------------------------------------------------------------------------------
/public/3d/models/landing/drop-noWeapon.vrm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/models/landing/drop-noWeapon.vrm
--------------------------------------------------------------------------------
/public/3d/models/landing/neuro-noWeapon.vrm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/models/landing/neuro-noWeapon.vrm
--------------------------------------------------------------------------------
/public/3d/models/neurohacker.vrm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/models/neurohacker.vrm
--------------------------------------------------------------------------------
/public/3d/ot.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/3d/ot.glb
--------------------------------------------------------------------------------
/public/assets/backgrounds/class-frame.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/backgrounds/class-mask.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/backgrounds/main-background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/backgrounds/main-background.jpg
--------------------------------------------------------------------------------
/public/assets/backgrounds/main-background2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/backgrounds/main-background2.jpg
--------------------------------------------------------------------------------
/public/assets/backgrounds/profile-no-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/backgrounds/profile-no-image.png
--------------------------------------------------------------------------------
/public/assets/backgrounds/token-box-common.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/backgrounds/token-box-epic.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/backgrounds/token-box-mythic.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/backgrounds/token-box-none.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/public/assets/backgrounds/token-box-rare.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/backgrounds/token-box-uncommon.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/backgrounds/token-frame-active.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/accessories.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/aqualith.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/icons/aqualith.png
--------------------------------------------------------------------------------
/public/assets/icons/arrowBack.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/arrowLeft.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/arrowRight.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/backpack.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/chest.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/class-beast-painter.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/class-bruiser.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/class-custom.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/class-drop-hunter.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/class-engineer.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/class-lisk-witch.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/class-neural-hacker.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/class-the-degen.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/close.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/crown.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/discord.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/download.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/exclamation.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/exp.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/expandLeft.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/expandRight.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/eyes.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/feet.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/fyrite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/icons/fyrite.png
--------------------------------------------------------------------------------
/public/assets/icons/head.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/health.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/hide.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/legs.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/limit.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/locked.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/login.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/logout.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/mana.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/map.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/metamask.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/microphone.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/mint.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/assets/icons/minus.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/mobile.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/public/assets/icons/moonstone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/icons/moonstone.png
--------------------------------------------------------------------------------
/public/assets/icons/notClaimed.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/assets/icons/obsidian.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/icons/obsidian.png
--------------------------------------------------------------------------------
/public/assets/icons/outer.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/phone.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/public/assets/icons/phoneActive.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/public/assets/icons/plus.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/rooms.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/scenes.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/settings.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/silk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/icons/silk.png
--------------------------------------------------------------------------------
/public/assets/icons/skin.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/slotBody.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/slotHead.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/slotLeftHand.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/slotLegs.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/slotMount.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/slotRightHand.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/soundoff.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/assets/icons/soundon.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/speechToText.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/assets/icons/tokens.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/venturine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/icons/venturine.png
--------------------------------------------------------------------------------
/public/assets/icons/voice.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/icons/vr.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/assets/media/DropHunter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/media/DropHunter.png
--------------------------------------------------------------------------------
/public/assets/media/NeuralHacker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/media/NeuralHacker.png
--------------------------------------------------------------------------------
/public/assets/media/btn_create_character.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/media/btn_create_character.png
--------------------------------------------------------------------------------
/public/assets/media/btn_load_character.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/media/btn_load_character.png
--------------------------------------------------------------------------------
/public/assets/media/degens.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/media/degens.gif
--------------------------------------------------------------------------------
/public/assets/media/disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/assets/media/disabled.png
--------------------------------------------------------------------------------
/public/city.hdr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/city.hdr
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Black Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Black Italic.otf
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Black.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Black.otf
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Bold Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Bold Italic.otf
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Bold.otf
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Light Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Light Italic.otf
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Light.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Light.otf
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Regular Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Regular Italic.otf
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Regular.otf
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Thin italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Thin italic.otf
--------------------------------------------------------------------------------
/public/fonts/tt-squares/TT Squares Condensed Thin.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/fonts/tt-squares/TT Squares Condensed Thin.otf
--------------------------------------------------------------------------------
/public/icons/back.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/download.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/icons/webaverse.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/icons/webaverse.gif
--------------------------------------------------------------------------------
/public/main-background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/main-background.jpg
--------------------------------------------------------------------------------
/public/scripts/compile-sounds.sh:
--------------------------------------------------------------------------------
1 | # this script is used to compile sounds into an indexed mp3 file
2 | # input: directories containing wav files (48000 Hz)
3 | # output: mp3 data file and json metadata file
4 | # run this in the sounds directory
5 |
6 | find . -name '*-pad.wav' | xargs -d '\n' rm
7 | clean () {
8 | rm -f lol.txt
9 | rm -f sound-files.txt
10 | rm -f sounds.txt
11 | rm -f sounds.wav
12 | find . -name '*-pad.wav' | xargs -d '\n' rm
13 | }
14 | rm -f sounds.mp3
15 |
16 | clean
17 | ls {ui,effect,background}/*.wav | sort -n >sound-files.txt
18 |
19 | set --
20 | while IFS='' read -r item; do
21 | # pad files to avoid clipping at the edges
22 | sox -V "$item" "$item"-pad.wav pad 0 0.03
23 | set -- "$@" "$item"-pad.wav
24 | done &1 | tee lol.txt
26 | sox -V sounds.wav sounds.mp3 2>&1 | tee lol.txt
27 |
28 | cat sound-files.txt | while read f; do
29 | samples=$(soxi -s "$f"-pad.wav)
30 | samplerate=$(soxi -r "$f"-pad.wav)
31 | a=$(echo "scale=20; $samples / $samplerate" | bc)
32 | echo "$a $f" | tee -a sounds.txt
33 | done;
34 | node -e 'offset = 0; a = require("fs").readFileSync("./sounds.txt", "utf8").split("\n").filter(l => !!l).map(s => {m = s.match(/^([0-9\.]+) (.+)$/); duration = parseFloat(m[1] * 1000.); name = m[2]; r = {name,offset,duration}; offset += duration; return r;}); console.log(JSON.stringify(a, null, 2))' >sound-files.json
35 |
36 |
--------------------------------------------------------------------------------
/public/sound/background/cc_bgm.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/background/cc_bgm.wav
--------------------------------------------------------------------------------
/public/sound/background/cc_bgm_balanced.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/background/cc_bgm_balanced.wav
--------------------------------------------------------------------------------
/public/sound/effect/character-load.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/effect/character-load.wav
--------------------------------------------------------------------------------
/public/sound/effect/class-select.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/effect/class-select.wav
--------------------------------------------------------------------------------
/public/sound/effect/switchingItem.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/effect/switchingItem.wav
--------------------------------------------------------------------------------
/public/sound/sound-files.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "background/cc_bgm.wav",
4 | "offset": 0,
5 | "duration": 123458.58333333334
6 | },
7 | {
8 | "name": "background/cc_bgm_balanced.wav",
9 | "offset": 123458.58333333334,
10 | "duration": 123458.60416666666
11 | },
12 | {
13 | "name": "effect/character-load.wav",
14 | "offset": 246917.1875,
15 | "duration": 3030
16 | },
17 | {
18 | "name": "effect/class-select.wav",
19 | "offset": 249947.1875,
20 | "duration": 2780
21 | },
22 | {
23 | "name": "effect/switchingItem.wav",
24 | "offset": 252727.1875,
25 | "duration": 623.75
26 | },
27 | {
28 | "name": "ui/back-next-button.wav",
29 | "offset": 253350.9375,
30 | "duration": 155.02083333333334
31 | },
32 | {
33 | "name": "ui/class-mouse-over.wav",
34 | "offset": 253505.95833333334,
35 | "duration": 217.52083333333334
36 | },
37 | {
38 | "name": "ui/class_click.wav",
39 | "offset": 253723.4791666667,
40 | "duration": 3123.75
41 | },
42 | {
43 | "name": "ui/class_pass.wav",
44 | "offset": 256847.2291666667,
45 | "duration": 155
46 | },
47 | {
48 | "name": "ui/option_click.wav",
49 | "offset": 257002.2291666667,
50 | "duration": 155.02083333333334
51 | },
52 | {
53 | "name": "ui/randomize-button.wav",
54 | "offset": 257157.25000000003,
55 | "duration": 342.5208333333333
56 | },
57 | {
58 | "name": "ui/section_click.wav",
59 | "offset": 257499.77083333337,
60 | "duration": 155
61 | }
62 | ]
63 |
--------------------------------------------------------------------------------
/public/sound/sounds.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/sounds.mp3
--------------------------------------------------------------------------------
/public/sound/ui/back-next-button.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/ui/back-next-button.wav
--------------------------------------------------------------------------------
/public/sound/ui/class-mouse-over.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/ui/class-mouse-over.wav
--------------------------------------------------------------------------------
/public/sound/ui/class_click.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/ui/class_click.wav
--------------------------------------------------------------------------------
/public/sound/ui/class_pass.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/ui/class_pass.wav
--------------------------------------------------------------------------------
/public/sound/ui/option_click.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/ui/option_click.wav
--------------------------------------------------------------------------------
/public/sound/ui/randomize-button.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/ui/randomize-button.wav
--------------------------------------------------------------------------------
/public/sound/ui/section_click.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/sound/ui/section_click.wav
--------------------------------------------------------------------------------
/public/textures/beam2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/textures/beam2.png
--------------------------------------------------------------------------------
/public/textures/noise3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/textures/noise3.jpg
--------------------------------------------------------------------------------
/public/textures/pixel9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/textures/pixel9.png
--------------------------------------------------------------------------------
/public/ui/ChatOff.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/ui/ChatOn.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/ui/Equip.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/ui/MicChat.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/ui/MicOff.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/ui/MicOn.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/ui/aroff.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/ui/aron.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/ui/arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/ui/backButton_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/backButton_gray.png
--------------------------------------------------------------------------------
/public/ui/backButton_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/backButton_white.png
--------------------------------------------------------------------------------
/public/ui/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/background.png
--------------------------------------------------------------------------------
/public/ui/connectWallet.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/public/ui/diconnectWallet.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/public/ui/download.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/ui/landing/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/landing/logo.png
--------------------------------------------------------------------------------
/public/ui/loading.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/ui/mainBackground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/mainBackground.png
--------------------------------------------------------------------------------
/public/ui/mint.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/public/ui/mint/ethereum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/mint/ethereum.png
--------------------------------------------------------------------------------
/public/ui/mint/mintPopup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/mint/mintPopup.png
--------------------------------------------------------------------------------
/public/ui/mint/polygon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/mint/polygon.png
--------------------------------------------------------------------------------
/public/ui/mint/walletError.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/mint/walletError.png
--------------------------------------------------------------------------------
/public/ui/rotate-cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/rotate-cancel.png
--------------------------------------------------------------------------------
/public/ui/rotate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/rotate.png
--------------------------------------------------------------------------------
/public/ui/selector/cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/selector/cancel.png
--------------------------------------------------------------------------------
/public/ui/selector/tick.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/ui/skinSelector/Vector.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/skinSelector/Vector.png
--------------------------------------------------------------------------------
/public/ui/soundoff.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/ui/soundon.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/ui/traits/Eye 2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/Eye 2.png
--------------------------------------------------------------------------------
/public/ui/traits/Layer_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/Layer_2.png
--------------------------------------------------------------------------------
/public/ui/traits/Rectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/Rectangle.png
--------------------------------------------------------------------------------
/public/ui/traits/accessories.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/accessories.png
--------------------------------------------------------------------------------
/public/ui/traits/body.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/body.png
--------------------------------------------------------------------------------
/public/ui/traits/hairColor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/hairColor.png
--------------------------------------------------------------------------------
/public/ui/traits/hairStyle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/hairStyle.png
--------------------------------------------------------------------------------
/public/ui/traits/head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/head.png
--------------------------------------------------------------------------------
/public/ui/traits/legs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/legs.png
--------------------------------------------------------------------------------
/public/ui/traits/shoes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/shoes.png
--------------------------------------------------------------------------------
/public/ui/traits/shuffle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/ui/traits/skin-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/skin-color.png
--------------------------------------------------------------------------------
/public/ui/traits/torso.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/torso.png
--------------------------------------------------------------------------------
/public/ui/traits/webaMark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/traits/webaMark.png
--------------------------------------------------------------------------------
/public/ui/weba.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/weba.png
--------------------------------------------------------------------------------
/public/ui/webadark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/public/ui/webadark.png
--------------------------------------------------------------------------------
/src/Main.jsx:
--------------------------------------------------------------------------------
1 | import { Web3Provider } from "@ethersproject/providers"
2 | import { Web3ReactProvider } from "@web3-react/core"
3 | import React, { Suspense } from "react"
4 | import ReactDOM from "react-dom/client"
5 | import { AudioProvider } from "./context/AudioContext"
6 |
7 | import { AccountProvider } from "./context/AccountContext"
8 | import { SceneProvider } from "./context/SceneContext"
9 | import { ViewProvider } from "./context/ViewContext"
10 |
11 | import { SoundProvider } from "./context/SoundContext"
12 |
13 | // import i18n (needs to be bundled ;))
14 | import "./lib/localization/i18n"
15 |
16 | import App from "./App"
17 | import { LanguageProvider } from "./context/LanguageContext"
18 |
19 | const getLibrary = (provider) => {
20 | const library = new Web3Provider(provider)
21 | library.pollingInterval = 12000
22 | return library
23 | }
24 |
25 | ReactDOM.createRoot(document.getElementById("root")).render(
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | ,
45 | )
46 |
--------------------------------------------------------------------------------
/src/components/ARButton.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react"
2 | import { SceneContext } from "../context/SceneContext"
3 | import { CameraMode, ViewContext } from "../context/ViewContext"
4 | import { startAR } from "../library/ar"
5 | import styles from './ARButton.module.css'
6 |
7 | export default function ARButton() {
8 | const {currentCameraMode, setCurrentCameraMode} = useContext(ViewContext)
9 | const {scene} = useContext(SceneContext)
10 |
11 | return (
12 | {
14 | if (currentCameraMode === CameraMode.AR) {
15 | setCurrentCameraMode(CameraMode.NORMAL);
16 | // find a div called almostthereContainer and remove it from dom if it exists
17 | window.XR8?.stop()
18 | window.XR8?.clearCameraPipelineModules()
19 |
20 | const almostThereContainer = document.getElementById('almostthereContainer')
21 | if (almostThereContainer) {
22 | almostThereContainer.remove()
23 | }
24 | }
25 | else {
26 | startAR(scene)
27 | setCurrentCameraMode(CameraMode.AR);
28 | }
29 | }}
30 | />
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/src/components/ARButton.module.css:
--------------------------------------------------------------------------------
1 | .SquareButton {
2 | position: absolute;
3 | bottom: 2em;
4 | right: 6em;
5 | transition : .3s;
6 | background-size: 1.5em;
7 | background-repeat: no-repeat;
8 | background-position: center;
9 | color : rgba(255, 255, 255, 0.5);
10 | width: 3em;
11 | height: 3em;
12 | border: 1px solid #434B58;
13 | backdrop-filter: blur(22.5px);
14 | border-radius: 5px;
15 | opacity : 0.5;
16 | user-select : none;
17 | cursor:pointer;
18 | z-index:1000;
19 | }
20 |
21 | .SquareButton:hover {
22 | backdrop-filter: blur(1.5px);
23 | border-color : white;
24 | opacity : 1.0;
25 | color:white;
26 | }
27 |
28 | .StyledAudioButton {
29 | z-index: 1000;
30 | }
31 |
32 | .AROn {
33 | background-image: url('/ui/aron.svg');
34 | }
35 |
36 | .AROff {
37 | background-image: url('/ui/aroff.svg');
38 | }
--------------------------------------------------------------------------------
/src/components/App.module.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/src/components/App.module.css
--------------------------------------------------------------------------------
/src/components/AudioButton.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react"
2 | import { AudioContext } from "../context/AudioContext"
3 | import styles from './AudioButton.module.css'
4 |
5 | export default function AudioButton() {
6 | const {isMute, enableAudio, disableAudio} = useContext(AudioContext)
7 |
8 | return (
9 |
{
11 | if (isMute) enableAudio()
12 | else
13 | disableAudio()
14 | }}
15 | />
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/AudioButton.module.css:
--------------------------------------------------------------------------------
1 | .SquareButton {
2 | position: absolute;
3 | bottom: 2em;
4 | right: 2em;
5 | transition : .3s;
6 | background-size: 1.5em;
7 | background-repeat: no-repeat;
8 | background-position: center;
9 | color : rgba(255, 255, 255, 0.5);
10 | width: 3em;
11 | height: 3em;
12 | border: 1px solid #434B58;
13 | backdrop-filter: blur(22.5px);
14 | border-radius: 5px;
15 | opacity : 0.5;
16 | user-select : none;
17 | cursor:pointer;
18 | z-index:1000;
19 | }
20 |
21 | .SquareButton:hover {
22 | backdrop-filter: blur(1.5px);
23 | border-color : white;
24 | opacity : 1.0;
25 | color:white;
26 | }
27 |
28 | .StyledAudioButton {
29 | z-index: 1000;
30 | }
31 |
32 | .AudioOn {
33 | background-image: url('/ui/soundon.svg');
34 | }
35 |
36 | .AudioOff {
37 | background-image: url('/ui/soundoff.svg');
38 |
39 | }
--------------------------------------------------------------------------------
/src/components/BackButton.jsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import styles from './BackButton.module.css'
3 |
4 | export const BackButton = ({onClick}) =>{
5 | return (
6 |
7 |
8 | )
9 | }
--------------------------------------------------------------------------------
/src/components/BackButton.module.css:
--------------------------------------------------------------------------------
1 | .StyledBackButton {
2 | background: url('/ui/backButton_gray.png') center center no-repeat;
3 | background-size: 45% 55%;
4 | height: 4em;
5 | width: 4em;
6 | backdrop-filter: blur(22.5px);
7 | border-radius: 5px;
8 | box-sizing: border-box;
9 | opacity: 0.4;
10 | user-select: none;
11 | position: absolute;
12 | z-index: 100000;
13 | margin-left: 2em;
14 | margin-top: 2em;
15 | border: 1px solid #38404E;
16 |
17 | }
18 |
19 | .StyledBackButton:hover {
20 | opacity: 1.0;
21 | cursor: pointer;
22 | background: url('/ui/backButton_white.png') center center no-repeat;
23 | background-size: 45% 55%;
24 | }
--------------------------------------------------------------------------------
/src/components/Background.jsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | import logo from "../../public/ui/weba.png"
4 | import styles from "./Background.module.css"
5 |
6 | export default function Background() {
7 | return (
8 |
9 |
10 |
11 |
12 |

13 |
14 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/Background.module.css:
--------------------------------------------------------------------------------
1 | .backgroundImg {
2 | background-image: url('/assets/backgrounds/main-background2.jpg');
3 | background-attachment: fixed;
4 | background-repeat: no-repeat;
5 | background-position: center center;
6 | height: 100vh;
7 | width: 100vw;
8 | background-size: cover;
9 | display: fixed;
10 | flex-direction: column;
11 | align-items: center;
12 | overflow: hidden;
13 | position: absolute;
14 | z-index: -100;
15 | }
16 |
17 |
18 | .Background {
19 | background: url('/assets/backgrounds/main-background2.jpg');
20 | background-position: center;
21 | background-repeat: no-repeat;
22 | background-size: cover;
23 | overflow: hidden;
24 | }
25 |
26 | .webamark {
27 | position: absolute;
28 | left: 0;
29 | top: 0;
30 | width: 100vw;
31 | height: 100vh;
32 | }
33 |
34 | .logo {
35 | position: absolute;
36 | left: 50%;
37 | top: 50%;
38 | transform: translate(-50%, -50%);
39 | width: 100vh;
40 | height: 100vh;
41 | opacity: 0.05;
42 | }
--------------------------------------------------------------------------------
/src/components/Chat.module.css:
--------------------------------------------------------------------------------
1 | .chatBox {
2 | width: 100%;
3 | height: 100%;
4 | font-size: .875rem;
5 | color: #fff;
6 | text-align: left;
7 | box-sizing: border-box;
8 | padding: 24px;
9 | }
10 |
11 | .chatBox * {
12 | outline: none !important;
13 | }
14 |
15 |
16 | .chatBox > label, .chatBox > span > label {
17 | display: block;
18 | width: 100%;
19 | color: #99ABB2;
20 | margin-bottom: 8px;
21 | }
22 |
23 | .chatBox > input, .chatBox > span > input {
24 | background-color: #193234;
25 | color: #fff;
26 | border: 1px solid #C5DCD0;
27 | padding: .5em;
28 | display: block;
29 | }
30 |
31 | .chatBox > textarea {
32 | background-color: #193234;
33 | color: #fff;
34 | border: 1px solid #C5DCD0;
35 | padding: .5em;
36 | width: calc(100% - 1em);
37 | display: block;
38 | }
39 |
40 | .chatBox > select {
41 | background-color: #000;
42 | color: #fff;
43 | border-radius: 5px;
44 | border: 1px solid #fff;
45 | margin: .5em;
46 | padding: .5em;
47 | width: calc(100% - 1em);
48 | }
49 |
50 | .messages {
51 | display: flex;
52 | flex-direction: column;
53 | height: 100%;
54 | height: 180px;
55 | overflow: auto;
56 | margin-bottom: 20px;
57 | background-color: #193234;
58 | color: #fff;
59 | border: 1px solid #C5DCD0;
60 | padding: 16px 8px 16px 16px;
61 | box-sizing: border-box;
62 | width: 100%;
63 | height: calc(100% - 142px);
64 | height: -webkit-calc(100% - 142px);
65 | }
66 |
67 | .messages .scrollBox {
68 | overflow-y: scroll;
69 | overflow-x: hidden;
70 | height: 100%;
71 | width: 100%;
72 | padding-right: 8px;
73 | box-sizing: border-box;
74 | padding-top: 14px;
75 | }
76 |
77 | /* set the input0 text color to white */
78 | .send input {
79 | background-color: #193234;
80 | color: #fff;
81 | border: 1px solid #C5DCD0;
82 | padding: .5em;
83 | width: calc(100% - 214px);
84 | margin-left: 10px;
85 | margin-right: 8px;
86 | height: 18px;
87 | display: inline-block;
88 | }
89 |
90 | .mic {
91 | vertical-align: middle;
92 | }
93 |
94 | .sendButton {
95 | vertical-align: bottom;
96 | float: right;
97 | width: 140px;
98 | }
99 |
100 | .speaker {
101 | width: 100%;
102 | }
103 |
104 | .speaker > label {
105 | display: block;
106 | color: #99ABB2;
107 | margin-bottom: 8px;
108 | }
109 |
110 | .speaker input {
111 | background-color: #193234;
112 | color: #fff;
113 | border: 1px solid #C5DCD0;
114 | padding: .5em;
115 | width: 100%;
116 | height: 100%;
117 | box-sizing: border-box;
118 | margin-bottom: 8px;
119 | }
120 |
121 | .warning {
122 | display: inline-block;
123 | position: absolute;
124 | right: 24px;
125 | top: 9px;
126 | font-size: 14px;
127 | color: burlywood;
128 | }
129 |
130 | .isTyping {
131 | padding: 0;
132 | margin: 4px 0 0 45px;
133 | display: none;
134 | }
135 |
136 | .isTyping.show {
137 | display: inline-block;
138 | }
139 |
140 |
--------------------------------------------------------------------------------
/src/components/ChatButton.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react"
2 | import { ViewMode, ViewContext } from "../context/ViewContext"
3 | import styles from "./ChatButton.module.css"
4 | import { CustomButton } from "./custom-button"
5 |
6 | import { SoundContext } from "../context/SoundContext"
7 | import { AudioContext } from "../context/AudioContext"
8 |
9 | export default function ChatButton() {
10 | const { viewMode, setViewMode } = useContext(ViewContext)
11 | const { playSound } = useContext(SoundContext)
12 | const { isMute } = useContext(AudioContext)
13 | return (
14 |
{
20 | if (viewMode !== ViewMode.CHAT) {
21 | setViewMode(ViewMode.CHAT)
22 | !isMute && playSound('backNextButton');
23 | } else {
24 | setViewMode(ViewMode.APPEARANCE)
25 | !isMute && playSound('backNextButton');
26 | }
27 | }}
28 | />
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/ExportMenu.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react"
2 | import { SceneContext } from "../context/SceneContext"
3 | import CustomButton from "./custom-button"
4 |
5 | import { downloadGLB, downloadVRM } from "../library/download-utils"
6 |
7 | import styles from "./ExportMenu.module.css"
8 | import { LanguageContext } from "../context/LanguageContext"
9 |
10 | const defaultName = "Anon"
11 |
12 | export const ExportMenu = () => {
13 | // Translate hook
14 | const { t } = useContext(LanguageContext);
15 | const [name] = React.useState(localStorage.getItem("name") || defaultName)
16 | const { model, avatar } = useContext(SceneContext)
17 |
18 | return (
19 |
20 | {
27 | downloadGLB(model, true, name)
28 | }}
29 | />
30 | {
37 | downloadGLB(model, false, name)
38 | }}
39 | />
40 | {
47 | downloadVRM(model, avatar, name, 4096, true)
48 | }}
49 | />
50 |
51 | )
52 | }
53 |
--------------------------------------------------------------------------------
/src/components/ExportMenu.module.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin: 0 8px;
3 | }
--------------------------------------------------------------------------------
/src/components/LanguageSwitch.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react"
2 | import { useTranslation, Trans } from "react-i18next"
3 | import styles from "./LanguageSwitch.module.css"
4 |
5 | const lngs = {
6 | // English
7 | en: { nativeName: "English" },
8 | // Russian
9 | ru: { nativeName: "Русский" },
10 | // Chinese
11 | zh: { nativeName: "中文" },
12 | }
13 |
14 | export default function LanguageSwitch() {
15 | const { t, i18n } = useTranslation()
16 | return (
17 |
18 |
28 |
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/LanguageSwitch.module.css:
--------------------------------------------------------------------------------
1 | .languageSwitchWrap {
2 | position: absolute;
3 | z-index: 10000000;
4 | top: 26px;
5 | right: 32px;
6 | color: white;
7 | }
8 |
9 | .languageSwitchWrap select {
10 | background: none !important;
11 | color: white;
12 | border: none;
13 | font-size: 16px;
14 | padding-right: 8px;
15 | box-shadow: 0 5px 25px rgba(0, 0, 0, 0.2);
16 | -webkit-appearance: button;
17 | appearance: button;
18 | outline: none;
19 | text-align: right;
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/components/LoadingOverlay.jsx:
--------------------------------------------------------------------------------
1 | import React, {useContext} from "react"
2 | // import webaMark from "../../public/ui/loading/webaMark.svg"
3 |
4 | import styles from './LoadingOverlay.module.css'
5 |
6 | import {ViewContext} from "../context/ViewContext"
7 | export default function LoadingOverlayCircularStatic({
8 | title = "LOADING"
9 | }) {
10 | const {isLoading} = useContext(ViewContext)
11 | // return isLoading ? (
12 | //
13 | //
14 | //
{title}
15 | //
16 | //

17 | //
18 | //
19 | // ) : null
20 | return isLoading ? (
21 |
22 |
23 | {title}
24 |
25 | ) : null
26 | }
--------------------------------------------------------------------------------
/src/components/LoadingOverlay.module.css:
--------------------------------------------------------------------------------
1 | /* TASK: rewrite the above styled component to use CSS modules. instead of nesting classes, format them with CSS to be individual classes. use the default values instead of props */
2 |
3 | .LoadingStyleBox {
4 | z-index: 10000000;
5 | width: 100vw;
6 | height: 100vh;
7 | top: 0;
8 | left: 0;
9 | position: fixed;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | user-select: none;
15 | overflow: hidden;
16 | background: #000000;
17 | }
18 |
19 | .loading-text {
20 | font-family: Proxima;
21 | font-style: normal;
22 | font-weight: 400;
23 | font-size: 18px;
24 | position: relative;
25 | top: 1em;
26 | line-height: 32px;
27 | text-align: center;
28 | color: #FFFFFF;
29 | display: inline-block;
30 | }
31 |
32 | @keyframes spinner {
33 | 0% {
34 | transform: rotate(0deg);
35 | }
36 | 100% {
37 | transform: rotate(360deg);
38 | }
39 | }
40 | .loading-spinner {
41 | width: 5em;
42 | height: 5em;
43 |
44 | border: 5px solid #860080; /* Light grey */
45 | border-top: 5px solid #2c0026; /* Black */
46 | border-radius: 50%;
47 | animation: spinner 1.5s linear infinite;
48 | display: inline-block;
49 | float: right;
50 | }
51 |
52 |
53 | .logo-container {
54 | bottom: 0;
55 | position: absolute;
56 | }
57 |
58 | .webamark {
59 | position: absolute;
60 | left: 50%;
61 | transform: translate(-50%, 0);
62 | width: 100px;
63 | bottom: 10vh;
64 | }
65 |
66 | .logo-gradient {
67 | height: 20vh;
68 | width: 100vw;
69 | background: radial-gradient(49.5% 173.11% at 50.84% -79.89%, #95414E 30.36%, rgba(137, 61, 73, 0) 100%);
70 | display: flex;
71 | flex-direction: column;
72 | transform: rotate(-180deg);
73 | bottom: 0;
74 | }
--------------------------------------------------------------------------------
/src/components/Logo.css:
--------------------------------------------------------------------------------
1 | .logo {
2 | position: absolute;
3 | left: 1.5em;
4 | top: 1.5em;
5 | }
6 |
7 | .logo img {
8 | width: 5em;
9 |
10 | }
--------------------------------------------------------------------------------
/src/components/Logo.jsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import "./Logo.css"
3 | export default function Logo () {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/src/components/Resizable.module.css:
--------------------------------------------------------------------------------
1 | .Block{
2 | display: flex;
3 | align-items: flex-end;
4 | position: absolute;
5 | overflow: hidden;
6 |
7 | }
8 | .Draggable{
9 | background: rgb(230, 230, 230);
10 | cursor: pointer;
11 | height: 20px;
12 | width: 20px;
13 | }
14 | .FullScreen{
15 | display: flex;
16 | overflow: hidden;
17 | position: absolute;
18 | width: 100%;
19 | height: 100%;
20 | }
21 | .BlockScreen{
22 | position:relative;
23 | width: 100%;
24 | height: 100%;
25 | }
26 |
27 | .leftBlock{
28 | animation: fadein 1s;
29 | position:absolute;
30 | background-color: rgba(0, 0, 0, 0.6);
31 | height: 100%;
32 | }
33 | .rightBlock{
34 | animation: fadein 1s;
35 | position:absolute;
36 | right: 0;
37 | background-color: rgba(0, 0, 0, 0.6);
38 | height: 100%;
39 | }
40 | .topBlock{
41 | animation: fadein 1s;
42 | position:absolute;
43 | top: 0;
44 | background-color: rgba(0, 0, 0, 0.6);
45 | height: 25px;
46 | }
47 | .lowerBlock{
48 | animation: fadein 1s;
49 | position:absolute;
50 | bottom: 0;
51 | background-color: rgba(0, 0, 0, 0.6);
52 | }
53 |
54 | body {
55 | animation: fadeInAnimation ease 3s;
56 | animation-iteration-count: 1;
57 | animation-fill-mode: forwards;
58 | }
59 | @keyframes fadein {
60 | from { opacity: 0; }
61 | to { opacity: 1; }
62 | }
--------------------------------------------------------------------------------
/src/components/Scene.module.css:
--------------------------------------------------------------------------------
1 | .FitParentContainer {
2 | width: 100vw;
3 | height: 100vh;
4 | position: relative;
5 | overflow: hidden;
6 | z-index: -1;
7 | }
8 |
9 | .ScreenSizeContainer {
10 | height: 100vh;
11 | width: 100vw;
12 | position: absolute;
13 | top: 0;
14 | }
15 |
16 | .Background {
17 | background: url('/ui/mainBackground.png');
18 | background-position: center;
19 | background-repeat: no-repeat;
20 | background-size: cover;
21 | overflow: hidden;
22 | }
23 |
24 | .webamark {
25 | position: absolute;
26 | left: 0;
27 | top: 0;
28 | width: 100vw;
29 | height: 100vh;
30 | }
31 |
32 | .logo {
33 | position: absolute;
34 | left: 50%;
35 | top: 50%;
36 | transform: translate(-50%, -50%);
37 | width: 100vh;
38 | height: 100vh;
39 | opacity: 0.05;
40 | }
--------------------------------------------------------------------------------
/src/components/Selector.module.css:
--------------------------------------------------------------------------------
1 | .SelectorContainerPos {
2 | position: absolute;
3 | top: 98px;
4 | right: 32px;
5 | height: -webkit-calc(100vh - 176px);
6 | height: calc(100vh - 176px);
7 | backdrop-filter: blur(22.5px);
8 | background: rgba(5, 11, 14, 0.8);
9 | z-index: 1000;
10 | cursor: pointer;
11 | }
12 |
13 | .scrollContainer {
14 | height: 100%;
15 | width: 80%;
16 | overflow-y: scroll;
17 | position: relative;
18 | overflow-x: hidden !important;
19 | margin: 16px;
20 | margin-right: 10px;
21 | padding-right: 6px;
22 | height: -webkit-calc(100% - 40px);
23 | height: calc(100% - 40px);
24 | }
25 |
26 | .selector-container {
27 | user-select: none;
28 | flex: 1;
29 | width: 140px;
30 | position: relative;
31 | }
32 |
33 | .traitTitleWrap {
34 | background: rgba(5, 11, 14, 0.8);
35 | position: absolute;
36 | top: -28px;
37 | padding: 8px 0 6px 0;
38 | font-size: 12px !important;
39 | width: 132px;
40 | text-align: center;
41 | left: 20px;
42 | color: #5eb086;
43 | }
44 |
45 | .topLine {
46 | background: rgb(0, 149, 100);
47 | background: -moz-linear-gradient(
48 | 90deg,
49 | rgba(0, 149, 100, 0) 0%,
50 | rgba(8, 234, 160, 1) 50%,
51 | rgba(0, 149, 100, 0) 100%
52 | );
53 | background: -webkit-linear-gradient(
54 | 90deg,
55 | rgba(0, 149, 100, 0) 0%,
56 | rgba(8, 234, 160, 1) 50%,
57 | rgba(0, 149, 100, 0) 100%
58 | );
59 | background: linear-gradient(
60 | 90deg,
61 | rgba(0, 149, 100, 0) 0%,
62 | rgba(8, 234, 160, 1) 50%,
63 | rgba(0, 149, 100, 0) 100%
64 | );
65 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1);
66 | position: absolute;
67 | top: 0;
68 | left: 0;
69 | width: 100%;
70 | height: 1px;
71 | }
72 |
73 | .bottomLine {
74 | background: rgb(0, 149, 100);
75 | background: -moz-linear-gradient(
76 | 90deg,
77 | rgba(0, 149, 100, 0) 0%,
78 | rgba(8, 234, 160, 1) 50%,
79 | rgba(0, 149, 100, 0) 100%
80 | );
81 | background: -webkit-linear-gradient(
82 | 90deg,
83 | rgba(0, 149, 100, 0) 0%,
84 | rgba(8, 234, 160, 1) 50%,
85 | rgba(0, 149, 100, 0) 100%
86 | );
87 | background: linear-gradient(
88 | 90deg,
89 | rgba(0, 149, 100, 0) 0%,
90 | rgba(8, 234, 160, 1) 50%,
91 | rgba(0, 149, 100, 0) 100%
92 | );
93 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1);
94 | position: absolute;
95 | bottom: 0;
96 | left: 0;
97 | width: 100%;
98 | height: 1px;
99 | }
100 |
101 | .traitTitleWrap .traitTitle {
102 | font-size: 12px;
103 | text-transform: uppercase;
104 | }
105 |
106 | .selector-container::after {
107 | content: " ";
108 | display: block;
109 | clear: both;
110 | }
111 |
112 | .selector-button {
113 | opacity: 1;
114 | float: left;
115 | width: 62px;
116 | text-align: center;
117 | }
118 |
119 | .selector-button:hover {
120 | opacity: 1;
121 | }
122 |
123 | .active {
124 | opacity: 1;
125 | }
126 |
127 | .selectorButton {
128 | padding: 0.25em;
129 | display: block;
130 | position: relative;
131 | }
132 |
133 | .trait-icon {
134 | height: 4em;
135 | margin: auto;
136 | user-select: none;
137 | position: relative;
138 | }
139 |
140 | .tickStyle {
141 | width: 20%;
142 | position: absolute;
143 | right: -15px;
144 | top: -15px;
145 | }
146 |
147 | .tickStyleInActive {
148 | display: none;
149 | }
150 |
151 | .icon-hidden {
152 | visibility: hidden;
153 | }
--------------------------------------------------------------------------------
/src/components/custom-button/IconCollection.jsx:
--------------------------------------------------------------------------------
1 | export const IconCollection = [
2 | {
3 | name: 'backpack',
4 | file: '/assets/icons/backpack.svg',
5 | },
6 | {
7 | name: 'microphone',
8 | file: '/assets/icons/microphone.svg',
9 | },
10 | {
11 | name: 'speechToText',
12 | file: '/assets/icons/speechToText.svg',
13 | },
14 | {
15 | name: 'arrowRight',
16 | file: '/assets/icons/arrowRight.svg',
17 | },
18 | {
19 | name: 'arrowLeft',
20 | file: '/assets/icons/arrowLeft.svg',
21 | },
22 | {
23 | name: 'rooms',
24 | file: '/assets/icons/rooms.svg',
25 | },
26 | {
27 | name: 'scenes',
28 | file: '/assets/icons/scenes.svg',
29 | },
30 | {
31 | name: 'settings',
32 | file: '/assets/icons/settings.svg',
33 | },
34 | {
35 | name: 'tokens',
36 | file: '/assets/icons/tokens.svg',
37 | },
38 | {
39 | name: 'voice',
40 | file: '/assets/icons/voice.svg',
41 | },
42 | {
43 | name: 'vr',
44 | file: '/assets/icons/vr.svg',
45 | },
46 | {
47 | name: 'discord',
48 | file: '/assets/icons/discord.svg',
49 | },
50 | {
51 | name: 'metamask',
52 | file: '/assets/icons/metamask.svg',
53 | },
54 | {
55 | name: 'close',
56 | file: '/assets/icons/close.svg',
57 | },
58 | {
59 | name: 'hide',
60 | file: '/assets/icons/hide.svg',
61 | },
62 | {
63 | name: 'map',
64 | file: '/assets/icons/map.svg',
65 | },
66 | {
67 | name: 'login',
68 | file: '/assets/icons/login.svg',
69 | },
70 | {
71 | name: 'logout',
72 | file: '/assets/icons/logout.svg',
73 | },
74 | {
75 | name: 'plus',
76 | file: '/assets/icons/plus.svg',
77 | },
78 | {
79 | name: 'minus',
80 | file: '/assets/icons/minus.svg',
81 | },
82 | {
83 | name: 'mint',
84 | file: '/assets/icons/mint.svg',
85 | },
86 | {
87 | name: 'download',
88 | file: '/assets/icons/download.svg',
89 | },
90 | {
91 | name: 'classDropHunter',
92 | file: '/assets/icons/class-drop-hunter.svg',
93 | },
94 | {
95 | name: 'classEndineer',
96 | file: '/assets/icons/class-engineer.svg',
97 | },
98 | {
99 | name: 'classCustom',
100 | file: '/assets/icons/class-custom.svg',
101 | },
102 | {
103 | name: 'classNeuralHacker',
104 | file: '/assets/icons/class-neural-hacker.svg',
105 | },
106 | {
107 | name: 'classLiskWitch',
108 | file: '/assets/icons/class-lisk-witch.svg',
109 | },
110 | {
111 | name: 'classBruiser',
112 | file: '/assets/icons/class-bruiser.svg',
113 | },
114 | {
115 | name: 'classBeastPainter',
116 | file: '/assets/icons/class-beast-painter.svg',
117 | },
118 | {
119 | name: 'soundon',
120 | file: '/assets/icons/soundon.svg',
121 | },
122 | {
123 | name: 'soundoff',
124 | file: '/assets/icons/soundoff.svg',
125 | },
126 | ];
--------------------------------------------------------------------------------
/src/components/message/Message.module.css:
--------------------------------------------------------------------------------
1 | .message .chat-bubble {
2 | display: inline-block;
3 | padding: 8px 12px;
4 | max-width: 60%;
5 | border-radius: 4px;
6 | background:rgba(255,255,255,0.05);
7 | box-shadow: 0 1px 1px rgba(0,0,0,0.4);
8 | position: relative;
9 | margin-bottom: 8px;
10 | font-size: 16px;
11 | }
12 |
13 | .message .chat-bubble .colorBg {
14 | background: #aaa;
15 | position: absolute;
16 | left: 0;
17 | top: 0;
18 | width: 100%;
19 | height: 100%;
20 | opacity: 0.2;
21 | border-radius: 4px;
22 | }
23 |
24 | .message .name {
25 | margin-bottom: 8px;
26 | padding-left: 4px;
27 | margin-top: -16px;
28 | font-size: 14px;
29 | }
30 |
31 | .message span {
32 | font-size: 10px;
33 | margin-left: 4px;
34 | margin-right: 4px;
35 | display: inline-block;
36 | color: rgba(255,255,255,0.4);
37 | }
38 |
39 | .speaker {
40 | text-align: right;
41 | }
--------------------------------------------------------------------------------
/src/components/message/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react"
2 | import styles from "./Message.module.css"
3 |
4 | export const Message = (props) => {
5 | const { timestamp, name, message, type, color } = props
6 | let date = new Date(timestamp)
7 | const hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
8 | const minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
9 | const time = `${hours}:${minutes}`
10 | return (
11 |
12 |
13 | {name}, {time}
14 |
15 |
22 |
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/token-box/TokenBox.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import classnames from "classnames";
3 | import styles from "./TokenBox.module.css";
4 |
5 | export const TokenBox = (props) => {
6 | const {
7 | size,
8 | active,
9 | onClick,
10 | level,
11 | icon,
12 | rarity,
13 | style
14 | } = props;
15 | return (
16 |
21 | {active && (
22 |
23 | )}
24 |
27 |

28 | {level && (
29 |
35 | Lv.{level}
36 |
37 | )}
38 |
39 | );
40 | };
--------------------------------------------------------------------------------
/src/components/token-box/index.jsx:
--------------------------------------------------------------------------------
1 | import {TokenBox} from './TokenBox';
2 | export {TokenBox};
--------------------------------------------------------------------------------
/src/constants/favouriteColors.js:
--------------------------------------------------------------------------------
1 | export const favouriteColors = {
2 | red:{
3 | color:"#FF0000",
4 | fontColor:"#FF9494"
5 | },
6 | orange:{
7 | color:"#FF7300",
8 | fontColor:"#FF9A47"
9 | },
10 | yellow:{
11 | color:"#FFC800",
12 | fontColor:"#FFC800"
13 | },
14 | green:{
15 | color:"#99FF00",
16 | fontColor:"#99FF00"
17 | },
18 | blue:{
19 | color:"#00AAFF",
20 | fontColor:"#38BDFF"
21 | },
22 | indigo:{
23 | color:"#0062FF",
24 | fontColor:"#80B0FF"
25 | },
26 | violet:{
27 | color:"#C800FF",
28 | fontColor:"#EDADFF"
29 | },
30 | purple:{
31 | color:"#6600FF",
32 | fontColor:"#C59EFF"
33 | },
34 | pink:{
35 | color:"#FF94D2",
36 | fontColor:"#FF94D2"
37 | },
38 | black:{
39 | color:"#000000",
40 | fontColor:"#BFBFBF"
41 | },
42 | white:{
43 | color:"#FFFFFF",
44 | fontColor:"#FFFFFF"
45 | }
46 | }
--------------------------------------------------------------------------------
/src/constants/voices.js:
--------------------------------------------------------------------------------
1 | export const voices = {
2 | 'Female 1': '1QnOliOAmerMUNuo2wXoH-YoainoSjZen',
3 | 'Female 2': '132G6oD0HHPPn4t1H6IkYv18_F0UVLWgi',
4 | 'Female 3': '1CdYZ2r52mtgJsFs88U0ZViMSnzpQ_HRp',
5 | 'Male 1': '17MQWS6m6VKkiU9KWRNGbTemZ0fIBKm0O',
6 | 'Male 2': '1AwNZizuEmCgmnpAlqGLXWh_mvTm6OLbM',
7 | 'Male 3': '1TKFdmFLttjjzByj2fZW8J70ZHjR-RTwc',
8 | 'Robot': '1NwpxG6kQ5lxwjPyuZTR0M9qc_7bMqPUH',
9 | }
--------------------------------------------------------------------------------
/src/context/AccountContext.jsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useState } from "react"
2 | export const AccountContext = createContext()
3 |
4 | export const AccountProvider = (props) => {
5 | const [walletAddress, setWalletAddress] = useState(null)
6 | const [ensName, setEnsName] = useState(null)
7 | const [connected, setConnected] = useState(false)
8 | const [OTTokens, setOTTokens] = useState([])
9 |
10 | return (
11 |
23 | {props.children}
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/src/context/AudioContext.jsx:
--------------------------------------------------------------------------------
1 | import React, {useState, createContext} from 'react';
2 | export const AudioContext = createContext();
3 | import bgm from "../../public/sound/background/cc_bgm_balanced.wav"
4 |
5 | export const AudioProvider = ({ children }) => {
6 | const [isMute, setMute] = useState(false);
7 | const audioRef = React.useRef(null);
8 |
9 | const enableAudio = () => {
10 | setMute(false)
11 | // append the background music to the body and play, using html
12 | // audio element
13 | const audio = audioRef.current;
14 | audio.src = bgm
15 | audio.loop = true
16 | audio.volume = 0.0
17 | audio.play()
18 | // fade audio in over 5 seconds in 1/60th of a second intervals
19 | let volume = 0.0
20 | const seconds = 5.0
21 | const interval = setInterval(() => {
22 | volume = Math.max(volume + 1.0 / (10 * seconds * 60.0), 1.0)
23 | if (volume >= 1.0) {
24 | clearInterval(interval)
25 | }
26 | audio.volume = volume
27 |
28 | }, 1000 / 60)
29 | }
30 |
31 | const disableAudio = () => {
32 | setMute(true)
33 | const audio = audioRef.current;
34 | // pause audio
35 | audio.pause()
36 | }
37 |
38 |
39 | return (
40 |
44 |
45 | {children}
46 |
47 | )
48 | }
--------------------------------------------------------------------------------
/src/context/LanguageContext.jsx:
--------------------------------------------------------------------------------
1 | import React, { createContext } from "react"
2 | import { useTranslation } from "react-i18next"
3 |
4 | export const LanguageContext = createContext()
5 |
6 | export const LanguageProvider = (props) => {
7 | const { t } = useTranslation()
8 |
9 | return (
10 |
15 | {props.children}
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/context/SoundContext.jsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useEffect, useState } from "react"
2 | import * as THREE from "three"
3 | import useSound from "use-sound"
4 | import soundFileSpecs from '../../public/sound/sound-files.json';
5 | import soundUrl from '../../public/sound/sounds.mp3';
6 |
7 | export const SoundContext = createContext()
8 |
9 | export const SoundProvider = (props) => {
10 | const _getSoundFiles = regex => soundFileSpecs.find(f => regex.test(f.name));
11 |
12 | const [play] = useSound(soundUrl, {
13 | sprite: {
14 | switchItem: [_getSoundFiles(/switchingItem/).offset, _getSoundFiles(/switchingItem/).duration],
15 | classSelect: [_getSoundFiles(/class-select/).offset, _getSoundFiles(/class-select/).duration],
16 | characterLoad: [_getSoundFiles(/character-load/).offset, _getSoundFiles(/character-load/).duration],
17 | randomizeButton: [_getSoundFiles(/randomize-button/).offset, _getSoundFiles(/randomize-button/).duration],
18 | classMouseOver: [_getSoundFiles(/class-mouse-over/).offset, _getSoundFiles(/class-mouse-over/).duration],
19 | backNextButton: [_getSoundFiles(/back-next-button/).offset, _getSoundFiles(/back-next-button/).duration],
20 | }
21 | });
22 |
23 | const playSound = (name, delay = 0) => {
24 | delay === 0 ? play({ id: name }) : setTimeout(() => {
25 | play({ id: name });
26 | },delay);
27 | }
28 |
29 | return (
30 |
35 | {props.children}
36 |
37 | )
38 | }
39 |
--------------------------------------------------------------------------------
/src/context/ViewContext.jsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | export const CameraMode = {
4 | NORMAL: "NORMAL",
5 | AR: "AR",
6 | AR_FRONT: "AR_FRONT",
7 | VR: "VR",
8 | }
9 |
10 | export const ViewMode = {
11 | LANDING: "LANDING",
12 | CREATE: "CREATE",
13 | LOAD: "LOAD",
14 | APPEARANCE: "APPEARANCE",
15 | BIO: "BIO",
16 | SAVE: "SAVE",
17 | MINT: "MINT",
18 | CHAT: "CHAT",
19 | }
20 |
21 | export const ViewContext = React.createContext()
22 |
23 | export const ViewProvider = (props) => {
24 | const [currentCameraMode, setCurrentCameraMode] = React.useState(CameraMode.NORMAL)
25 | const [viewMode, setViewMode] = React.useState(ViewMode.CREATE)
26 | const [isLoading, setIsLoading] = React.useState(false)
27 | const [mouseIsOverUI, setMouseIsOverUI] = React.useState(false)
28 |
29 | return (
30 |
36 | {props.children}
37 |
38 | )
39 | }
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/src/favicon.ico
--------------------------------------------------------------------------------
/src/lib/chat.js:
--------------------------------------------------------------------------------
1 | // Constants
2 |
3 | const messagesMaxCharacters = 20000
4 |
5 | // Prune Messages Function
6 |
7 | export async function pruneMessages(messages) {
8 | let currentSize = 0
9 | const newMessages = [];
10 |
11 | for (let i = messages.length - 1; i >= 0; i--) {
12 | const messageItem = messages[i];
13 | const message = `${messageItem?.name}: ${messageItem?.message}`;
14 |
15 | currentSize += message.length
16 |
17 | // Add up to N characters.
18 | if (currentSize < messagesMaxCharacters) newMessages.push(message)
19 | else break
20 | }
21 |
22 | // Reverse the array so that the newest messages are first.
23 | newMessages.reverse()
24 |
25 | return newMessages
26 | }
27 |
--------------------------------------------------------------------------------
/src/lib/localization/i18n.js:
--------------------------------------------------------------------------------
1 | import i18n from 'i18next';
2 | import { initReactI18next } from 'react-i18next';
3 | import LanguageDetector from 'i18next-browser-languagedetector';
4 | import translations from './translations.json';
5 |
6 | i18n
7 | // detect user language
8 | .use(LanguageDetector)
9 | // pass the i18n instance to react-i18next.
10 | .use(initReactI18next)
11 | // init i18next
12 | .init({
13 | debug: true,
14 | fallbackLng: 'en',
15 | interpolation: {
16 | escapeValue: false,
17 | },
18 | resources: translations
19 | });
20 |
21 | export default i18n;
--------------------------------------------------------------------------------
/src/library/blinkManager.js:
--------------------------------------------------------------------------------
1 | import { VRMExpressionPresetName } from "@pixiv/three-vrm";
2 | import { Clock } from "three";
3 |
4 |
5 | export class BlinkManager {
6 | constructor(closeTime = 0.5, openTime = 0.5, continuity = 1, randomness = 5) {
7 | this.vrmBlinkers = [];
8 | this.mode = 'ready';
9 |
10 | this.clock = new Clock();
11 |
12 | this.closeTime = closeTime
13 | this.openTime = openTime
14 | this.continuity = continuity;
15 | this.randomness = randomness
16 |
17 | this._eyeOpen = 1
18 | this._blinkCounter = 0;
19 |
20 | this.update()
21 | }
22 |
23 | addBlinker(vrm){
24 | this.vrmBlinkers.push(vrm)
25 | }
26 |
27 | update(){
28 | setInterval(() => {
29 | const deltaTime = this.clock.getDelta()
30 | switch (this.mode){
31 |
32 | case 'closing':
33 | if ( this._eyeOpen > 0)
34 | this._eyeOpen -= deltaTime / this.closeTime;
35 | else{
36 | this._eyeOpen =0
37 | this.mode = 'open'
38 | }
39 | this._updateBlinkers();
40 | break;
41 | case 'open':
42 | if ( this._eyeOpen < 1)
43 | this._eyeOpen += deltaTime / this.openTime;
44 | else{
45 | this._eyeOpen =1
46 | this.mode = 'ready'
47 | }
48 | this._updateBlinkers();
49 | break;
50 | case 'ready':
51 | this._blinkCounter += deltaTime;
52 | if (this._blinkCounter >= this.continuity){
53 | if (Math.floor(Math.random() * this.randomness) === 0)
54 | this.mode = 'closing'
55 | this._blinkCounter = 0;
56 | }
57 |
58 | break;
59 | }
60 | }, 1000/30);
61 | }
62 |
63 | _updateBlinkers(){
64 | this.vrmBlinkers.forEach(vrm => {
65 | vrm.expressionManager.setValue(VRMExpressionPresetName.Blink, 1 - this._eyeOpen)
66 | vrm.expressionManager.update()
67 | });
68 | }
69 | }
--------------------------------------------------------------------------------
/src/library/constants.js:
--------------------------------------------------------------------------------
1 | export const TRANSITION_TIME_OF_SWITCH_ITEM = 100;
2 | export const TRANSITION_TIME_OF_LOADING_AVATAR = 100;
3 |
4 | export const SWITCH_ITEM_EFFECT_INITIAL_TIME = 0.0;
5 | export const SWITCH_ITEM_EFFECT_DURATION = 1.5;
6 | export const SWITCH_ITEM_EFFECT_SPEED = 0.1;
7 |
8 | export const FADE_OUT_AVATAR_INITIAL_TIME = 0.0;
9 | export const FADE_OUT_AVATAR_DURATION = 1;
10 | export const FADE_OUT_AVATAR_SPEED = 0.05;
11 |
12 | export const FADE_IN_AVATAR_INITIAL_TIME = 0.0;
13 | export const FADE_IN_AVATAR_DURATION = 1;
14 | export const FADE_IN_AVATAR_SPEED = 0.015;
15 |
16 | export const transitionEffectTypeNumber = {
17 | normal: 0,
18 | switchItem: 1,
19 | fadeOutAvatar: 2,
20 | loadingAvatar: 3,
21 | fadeInAvatar: 4,
22 | }
23 |
--------------------------------------------------------------------------------
/src/library/gltf-cubic-spline-interpolant.js:
--------------------------------------------------------------------------------
1 | import * as THREE from "three";
2 | /*********************************/
3 | /********** INTERPOLATION ********/
4 | /*********************************/
5 | // Spline Interpolation
6 | // Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation
7 | export function GLTFCubicSplineInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) {
8 | THREE.Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
9 | }
10 | GLTFCubicSplineInterpolant.prototype = Object.create(THREE.Interpolant.prototype);
11 | GLTFCubicSplineInterpolant.prototype.constructor = GLTFCubicSplineInterpolant;
12 | GLTFCubicSplineInterpolant.prototype.copySampleValue_ = function (index) {
13 | // Copies a sample value to the result buffer. See description of glTF
14 | // CUBICSPLINE values layout in interpolate_() function below.
15 | var result = this.resultBuffer, values = this.sampleValues, valueSize = this.valueSize, offset = index * valueSize * 3 + valueSize;
16 | for (var i = 0; i !== valueSize; i++) {
17 | result[i] = values[offset + i];
18 | }
19 | return result;
20 | };
21 | GLTFCubicSplineInterpolant.prototype.beforeStart_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;
22 | GLTFCubicSplineInterpolant.prototype.afterEnd_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;
23 | GLTFCubicSplineInterpolant.prototype.interpolate_ = function (i1, t0, t, t1) {
24 | var result = this.resultBuffer;
25 | var values = this.sampleValues;
26 | var stride = this.valueSize;
27 | var stride2 = stride * 2;
28 | var stride3 = stride * 3;
29 | var td = t1 - t0;
30 | var p = (t - t0) / td;
31 | var pp = p * p;
32 | var ppp = pp * p;
33 | var offset1 = i1 * stride3;
34 | var offset0 = offset1 - stride3;
35 | var s2 = -2 * ppp + 3 * pp;
36 | var s3 = ppp - pp;
37 | var s0 = 1 - s2;
38 | var s1 = s3 - pp + p;
39 | // Layout of keyframe output values for CUBICSPLINE animations:
40 | // [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]
41 | for (var i = 0; i !== stride; i++) {
42 | var p0 = values[offset0 + i + stride]; // splineVertex_k
43 | var m0 = values[offset0 + i + stride2] * td; // outTangent_k * (t_k+1 - t_k)
44 | var p1 = values[offset1 + i + stride]; // splineVertex_k+1
45 | var m1 = values[offset1 + i] * td; // inTangent_k+1 * (t_k+1 - t_k)
46 | result[i] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;
47 | }
48 | return result;
49 | };
50 |
--------------------------------------------------------------------------------
/src/library/particle/utils.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three';
2 |
3 | export const _getGeometry = (geometry, attributeSpecs, particleCount) => {
4 | const geometry2 = new THREE.BufferGeometry();
5 | ['position', 'normal', 'uv'].forEach(k => {
6 | geometry2.setAttribute(k, geometry.attributes[k]);
7 | });
8 | geometry2.setIndex(geometry.index);
9 |
10 | const positions = new Float32Array(particleCount * 3);
11 | const positionsAttribute = new THREE.InstancedBufferAttribute(positions, 3);
12 | geometry2.setAttribute('positions', positionsAttribute);
13 |
14 | for(const attributeSpec of attributeSpecs){
15 | const {
16 | name,
17 | itemSize,
18 | } = attributeSpec;
19 | const array = new Float32Array(particleCount * itemSize);
20 | geometry2.setAttribute(name, new THREE.InstancedBufferAttribute(array, itemSize));
21 | }
22 |
23 | return geometry2;
24 | };
--------------------------------------------------------------------------------
/src/pages/Appearance.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect } from "react"
2 | import styles from "./Appearance.module.css"
3 | import { ViewMode, ViewContext } from "../context/ViewContext"
4 | import { SceneContext } from "../context/SceneContext"
5 | import Editor from "../components/Editor"
6 | import CustomButton from "../components/custom-button"
7 | import { LanguageContext } from "../context/LanguageContext"
8 | import { SoundContext } from "../context/SoundContext"
9 | import { AudioContext } from "../context/AudioContext"
10 |
11 | function Appearance({
12 | animationManager,
13 | blinkManager,
14 | lookatManager,
15 | effectManager,
16 | fetchNewModel,
17 | }) {
18 | const { isLoading, setViewMode } = React.useContext(ViewContext)
19 | const {
20 | resetAvatar,
21 | getRandomCharacter,
22 | isChangingWholeAvatar,
23 | setIsChangingWholeAvatar,
24 | } = React.useContext(SceneContext)
25 |
26 | const { playSound } = React.useContext(SoundContext)
27 | const { isMute } = React.useContext(AudioContext)
28 | const back = () => {
29 | !isMute && playSound('backNextButton');
30 | resetAvatar()
31 | setViewMode(ViewMode.CREATE)
32 | }
33 |
34 | const next = () => {
35 | !isMute && playSound('backNextButton');
36 | setViewMode(ViewMode.BIO)
37 | }
38 |
39 | const randomize = () => {
40 | if (!isChangingWholeAvatar) {
41 | !isMute && playSound('randomizeButton');
42 | getRandomCharacter()
43 | }
44 | }
45 |
46 | useEffect(() => {
47 | const setIsChangingWholeAvatarFalse = () => setIsChangingWholeAvatar(false)
48 |
49 | effectManager.addEventListener(
50 | "fadeintraitend",
51 | setIsChangingWholeAvatarFalse,
52 | )
53 | effectManager.addEventListener(
54 | "fadeinavatarend",
55 | setIsChangingWholeAvatarFalse,
56 | )
57 | return () => {
58 | effectManager.removeEventListener(
59 | "fadeintraitend",
60 | setIsChangingWholeAvatarFalse,
61 | )
62 | effectManager.removeEventListener(
63 | "fadeinavatarend",
64 | setIsChangingWholeAvatarFalse,
65 | )
66 | }
67 | }, [])
68 |
69 | // Translate hook
70 | const { t } = useContext(LanguageContext)
71 |
72 | return (
73 |
74 |
75 |

76 |
77 |
{t("pageTitles.chooseAppearance")}
78 |
85 |
86 |
93 |
100 |
107 |
108 |
109 | )
110 | }
111 |
112 | export default Appearance
113 |
--------------------------------------------------------------------------------
/src/pages/Appearance.module.css:
--------------------------------------------------------------------------------
1 | .buttonContainer {
2 | position: absolute;
3 | bottom: 20px;
4 | left: 32px;
5 | width: calc(100% - 64px);
6 | width: -webkit-calc(100% - 64px);
7 | text-align: center;
8 | }
9 |
10 | .buttonContainer .buttonLeft {
11 | float: left;
12 | }
13 |
14 | .buttonContainer .buttonRight {
15 | float: Right;
16 | }
17 |
18 | .buttonContainer .buttonCenter {
19 | margin: 0 8px;
20 | }
21 |
22 | .buttonContainer::after {
23 | content: ' ';
24 | display: block;
25 | clear: both;
26 | }
27 |
28 | .buttonContainer button {
29 | min-width: 120px;
30 | }
--------------------------------------------------------------------------------
/src/pages/Landing.jsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import styles from "./Landing.module.css"
3 | import { ViewMode, ViewContext } from "../context/ViewContext"
4 |
5 | import { SoundContext } from "../context/SoundContext"
6 | import { AudioContext } from "../context/AudioContext"
7 |
8 | function Landing() {
9 | const { setViewMode } = React.useContext(ViewContext)
10 | const { playSound } = React.useContext(SoundContext)
11 | const { isMute } = React.useContext(AudioContext)
12 |
13 | const createCharacter = () => {
14 | setViewMode(ViewMode.CREATE)
15 | !isMute && playSound('backNextButton');
16 | }
17 |
18 | const loadCharacter = () => {
19 | setViewMode(ViewMode.LOAD)
20 | !isMute && playSound('backNextButton');
21 | }
22 |
23 | return (
24 |
25 |
26 |
29 | {/*
30 |
34 | */}
35 |
36 |
37 | )
38 | }
39 |
40 | export default Landing
41 |
--------------------------------------------------------------------------------
/src/pages/Landing.module.css:
--------------------------------------------------------------------------------
1 | .buttonContainer {
2 | position: absolute;
3 | left: 0;
4 | width: calc(100% - 64px);
5 | width: -webkit-calc(100% - 64px);
6 | top: 50%;
7 | transform: translateY(-50%);
8 | -webkit-transform: translateY(-50%);
9 | text-align: center;
10 | height: 320px;
11 | }
12 | .buttonContainer .button {
13 | background: none !important;
14 | border: none !important;
15 | cursor: pointer;
16 | margin: 0 32px;
17 | height: 320px;
18 | width: 126px;
19 | position: relative;
20 | }
21 | .buttonContainer .button img {
22 | height: 100%;
23 | transition: all 0.3s ease-in-out;
24 | position: absolute;
25 | left: 0;
26 | top: 0;
27 | }
28 | .buttonContainer .button:hover img {
29 | top: -8px;
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/src/pages/Load.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import styles from './Load.module.css';
3 | import { ethers } from 'ethers';
4 | import { useWeb3React } from '@web3-react/core';
5 | import { InjectedConnector } from "@web3-react/injected-connector"
6 | import { ViewContext, ViewMode } from '../context/ViewContext';
7 |
8 | import { SoundContext } from "../context/SoundContext"
9 | import { AudioContext } from "../context/AudioContext"
10 |
11 | function Load() {
12 | const { account, library, activate } = useWeb3React();
13 | const [characters, setCharacters] = useState([]);
14 | const { setViewMode } = React.useContext(ViewContext);
15 | const { playSound } = React.useContext(SoundContext)
16 | const { isMute } = React.useContext(AudioContext)
17 |
18 | const injectedConnector = new InjectedConnector({
19 | supportedChainIds: [137, 1, 3, 4, 5, 42, 97],
20 | })
21 |
22 | useEffect(() => {
23 | if (account && library) {
24 | const contractAddress = '0x69341F01C2113E2d09Cd4837bbF1786dfbBc41d7';
25 | const abi = [
26 | 'function balanceOf(address owner) external view returns (uint256)',
27 | 'function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256)',
28 | 'function tokenURI(uint256 tokenId) external view returns (string)',
29 | ];
30 | const contract = new ethers.Contract(contractAddress, abi, library);
31 | contract.balanceOf(account).then((balance) => {
32 | const promises = [];
33 | for (let i = 0; i < balance; i++) {
34 | promises.push(contract.tokenOfOwnerByIndex(account, i));
35 | }
36 | Promise.all(promises).then((tokenIds) => {
37 | const tokenURIs = tokenIds.map((tokenId) => {
38 | return contract.tokenURI(tokenId);
39 | });
40 | Promise.all(tokenURIs).then((values) => {
41 | setCharacters(values);
42 | });
43 | });
44 | });
45 | }
46 | }, [account, library]);
47 |
48 | const connectWallet = () => {
49 | activate(injectedConnector)
50 | }
51 |
52 | const loadCharacter = (character) => {
53 | !isMute && playSound('backNextButton');
54 | setViewMode(ViewMode.APPEARANCE)
55 | }
56 |
57 | const back = () => {
58 | setViewMode(ViewMode.LANDING)
59 | !isMute && playSound('backNextButton');
60 | }
61 |
62 | return (
63 |
64 | {/* if the user has not logged in, display a message */}
65 | {!account && (
66 |
67 | Please connect your wallet to load your characters
68 | {/* show connect button */}
69 |
70 |
71 | )}
72 |
73 |
Load Character
74 | {characters.map((character, i) => {
75 | return (
76 |
{loadCharacter(character)}}
80 | >
81 | {JSON.stringify(character)}
82 |
83 | );
84 | })}
85 |
86 | {/* show back button to return to landing page */}
87 |
88 |
89 | );
90 | }
91 |
92 | export default Load;
--------------------------------------------------------------------------------
/src/pages/Load.module.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webaverse-studios/CharacterCreator/5ba01d5eab6bd750b5b41fba46b652417a573036/src/pages/Load.module.css
--------------------------------------------------------------------------------
/src/pages/Mint.jsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import styles from "./Mint.module.css"
3 | import { ViewMode, ViewContext } from "../context/ViewContext"
4 |
5 | import Mint from "../components/Mint"
6 | import ResizableDiv from "../components/Resizable"
7 | import CustomButton from "../components/custom-button"
8 |
9 | import { SoundContext } from "../context/SoundContext"
10 | import { AudioContext } from "../context/AudioContext"
11 |
12 | function MintComponent() {
13 | const { setViewMode } = React.useContext(ViewContext)
14 | const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256});
15 | const { playSound } = React.useContext(SoundContext)
16 | const { isMute } = React.useContext(AudioContext)
17 |
18 | const back = () => {
19 | setViewMode(ViewMode.SAVE)
20 | !isMute && playSound('backNextButton');
21 | }
22 |
23 | const next = () => {
24 | setViewMode(ViewMode.CHAT)
25 | !isMute && playSound('backNextButton');
26 | }
27 |
28 | return (
29 |
30 |
Mint Your Character
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
48 |
55 |
56 |
57 | )
58 | }
59 |
60 | export default MintComponent
61 |
--------------------------------------------------------------------------------
/src/pages/Mint.module.css:
--------------------------------------------------------------------------------
1 | .mintContainer {
2 | position: absolute;
3 | width: 100%;
4 | max-width: 50%;
5 | top: 50%;
6 | right: 32px;
7 | transform: translateY(-50%);
8 | -webkit-transform: translateY(-50%);
9 | text-align: center;
10 | height: -webkit-calc(100vh - 266px);
11 | height: calc(100vh - 266px);
12 | background: rgba(5, 11, 14, 0.8);
13 | color: aliceblue;
14 | user-select: none;
15 | }
16 |
17 | .scrollContainer {
18 | height: 98%;
19 | width: 99%;
20 | position: absolute;
21 | left: 0;
22 | top: 2px;
23 | overflow-x: hidden;
24 | overflow-y: scroll;
25 | }
26 |
27 | .topLine {
28 | background: rgb(0, 149, 100);
29 | background: -moz-linear-gradient(
30 | 90deg,
31 | rgba(0, 149, 100, 0) 0%,
32 | rgba(8, 234, 160, 1) 50%,
33 | rgba(0, 149, 100, 0) 100%
34 | );
35 | background: -webkit-linear-gradient(
36 | 90deg,
37 | rgba(0, 149, 100, 0) 0%,
38 | rgba(8, 234, 160, 1) 50%,
39 | rgba(0, 149, 100, 0) 100%
40 | );
41 | background: linear-gradient(
42 | 90deg,
43 | rgba(0, 149, 100, 0) 0%,
44 | rgba(8, 234, 160, 1) 50%,
45 | rgba(0, 149, 100, 0) 100%
46 | );
47 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1);
48 | position: absolute;
49 | top: 0;
50 | left: 0;
51 | width: 100%;
52 | height: 1px;
53 | }
54 |
55 | .bottomLine {
56 | background: rgb(0, 149, 100);
57 | background: -moz-linear-gradient(
58 | 90deg,
59 | rgba(0, 149, 100, 0) 0%,
60 | rgba(8, 234, 160, 1) 50%,
61 | rgba(0, 149, 100, 0) 100%
62 | );
63 | background: -webkit-linear-gradient(
64 | 90deg,
65 | rgba(0, 149, 100, 0) 0%,
66 | rgba(8, 234, 160, 1) 50%,
67 | rgba(0, 149, 100, 0) 100%
68 | );
69 | background: linear-gradient(
70 | 90deg,
71 | rgba(0, 149, 100, 0) 0%,
72 | rgba(8, 234, 160, 1) 50%,
73 | rgba(0, 149, 100, 0) 100%
74 | );
75 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1);
76 | position: absolute;
77 | bottom: 0;
78 | left: 0;
79 | width: 100%;
80 | height: 1px;
81 | }
82 |
83 | .buttonContainer {
84 | position: absolute;
85 | bottom: 20px;
86 | left: 32px;
87 | width: calc(100% - 64px);
88 | width: -webkit-calc(100% - 64px);
89 | text-align: center;
90 | }
91 |
92 | .buttonContainer .buttonLeft {
93 | float: left;
94 | }
95 |
96 | .buttonContainer .buttonRight {
97 | float: Right;
98 | }
99 |
100 | .buttonContainer .buttonCenter {
101 | margin: 0 8px;
102 | }
103 |
104 | .buttonContainer::after {
105 | content: " ";
106 | display: block;
107 | clear: both;
108 | }
109 |
110 | .buttonContainer button {
111 | min-width: 120px;
112 | }
113 |
--------------------------------------------------------------------------------
/src/pages/Save.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react"
2 | import styles from "./Save.module.css"
3 | import { ExportMenu } from "../components/ExportMenu"
4 |
5 | import { ViewMode, ViewContext } from "../context/ViewContext"
6 | import CustomButton from "../components/custom-button"
7 | import { LanguageContext } from "../context/LanguageContext"
8 | import { SoundContext } from "../context/SoundContext"
9 | import { AudioContext } from "../context/AudioContext"
10 |
11 | function Save() {
12 | const { setViewMode } = React.useContext(ViewContext);
13 | const { playSound } = React.useContext(SoundContext)
14 | const { isMute } = React.useContext(AudioContext)
15 |
16 | const back = () => {
17 | setViewMode(ViewMode.BIO)
18 | !isMute && playSound('backNextButton');
19 | }
20 | const mint = () => {
21 | setViewMode(ViewMode.CHAT)
22 | }
23 | const next = () => {
24 | setViewMode(ViewMode.CHAT)
25 | !isMute && playSound('backNextButton');
26 | }
27 |
28 | // Translate hook
29 | const { t } = useContext(LanguageContext);
30 |
31 | return (
32 |
33 |
{t("pageTitles.saveCharacter")}
34 |
35 |
42 |
43 | {/*
44 |
51 | */}
52 |
59 |
60 |
61 | )
62 | }
63 |
64 | export default Save
65 |
--------------------------------------------------------------------------------
/src/pages/Save.module.css:
--------------------------------------------------------------------------------
1 | .buttonContainer {
2 | position: absolute;
3 | bottom: 20px;
4 | left: 32px;
5 | width: calc(100% - 64px);
6 | width: -webkit-calc(100% - 64px);
7 | text-align: center;
8 | }
9 |
10 | .buttonContainer .buttonLeft {
11 | float: left;
12 | }
13 |
14 | .buttonContainer .buttonRight {
15 | float: Right;
16 | }
17 |
18 | .buttonContainer .buttonCenter {
19 | margin: 0 8px;
20 | }
21 |
22 | .buttonContainer::after {
23 | content: ' ';
24 | display: block;
25 | clear: both;
26 | }
27 |
28 | .buttonContainer button {
29 | min-width: 120px;
30 | }
--------------------------------------------------------------------------------
/src/pages/View.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react"
2 | import styles from "./View.module.css"
3 | import { ViewMode, ViewContext } from "../context/ViewContext"
4 | import Chat from "../components/Chat"
5 | import CustomButton from "../components/custom-button"
6 | import { LanguageContext } from "../context/LanguageContext"
7 |
8 | import { SoundContext } from "../context/SoundContext"
9 | import { AudioContext } from "../context/AudioContext"
10 |
11 | function View({templateInfo}) {
12 | const { setViewMode } = React.useContext(ViewContext)
13 |
14 | const [micEnabled, setMicEnabled] = React.useState(false)
15 | const [speechRecognition, setSpeechRecognition] = React.useState(false)
16 |
17 | const { playSound } = React.useContext(SoundContext)
18 | const { isMute } = React.useContext(AudioContext)
19 |
20 | const back = () => {
21 | setViewMode(ViewMode.SAVE)
22 | !isMute && playSound('backNextButton');
23 | if (speechRecognition)
24 | speechRecognition.stop()
25 | setMicEnabled(false)
26 | }
27 |
28 | // Translate hook
29 | const { t } = useContext(LanguageContext);
30 |
31 | return (
32 |
33 |
{t("pageTitles.chat")}
34 |
35 |
36 |
37 |
38 |
45 |
46 |
47 |
48 |
55 |
56 |
57 | )
58 | }
59 |
60 | export default View
61 |
--------------------------------------------------------------------------------
/src/pages/View.module.css:
--------------------------------------------------------------------------------
1 | .chatContainer {
2 | position: absolute;
3 | width: 100%;
4 | max-width: 50%;
5 | top: 50%;
6 | right: 32px;
7 | transform: translateY(-50%);
8 | -webkit-transform: translateY(-50%);
9 | text-align: center;
10 | height: -webkit-calc(100vh - 266px);
11 | height: calc(100vh - 266px);
12 | background: rgba(5, 11, 14, 0.8);
13 | color: aliceblue;
14 | }
15 |
16 | .scrollContainer {
17 | height: 98%;
18 | width: 99%;
19 | position: absolute;
20 | left: 0;
21 | top: 2px;
22 | overflow-x: hidden;
23 | overflow-y: scroll;
24 | }
25 |
26 | .topLine {
27 | background: rgb(0, 149, 100);
28 | background: -moz-linear-gradient(
29 | 90deg,
30 | rgba(0, 149, 100, 0) 0%,
31 | rgba(8, 234, 160, 1) 50%,
32 | rgba(0, 149, 100, 0) 100%
33 | );
34 | background: -webkit-linear-gradient(
35 | 90deg,
36 | rgba(0, 149, 100, 0) 0%,
37 | rgba(8, 234, 160, 1) 50%,
38 | rgba(0, 149, 100, 0) 100%
39 | );
40 | background: linear-gradient(
41 | 90deg,
42 | rgba(0, 149, 100, 0) 0%,
43 | rgba(8, 234, 160, 1) 50%,
44 | rgba(0, 149, 100, 0) 100%
45 | );
46 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1);
47 | position: absolute;
48 | top: 0;
49 | left: 0;
50 | width: 100%;
51 | height: 1px;
52 | }
53 |
54 | .bottomLine {
55 | background: rgb(0, 149, 100);
56 | background: -moz-linear-gradient(
57 | 90deg,
58 | rgba(0, 149, 100, 0) 0%,
59 | rgba(8, 234, 160, 1) 50%,
60 | rgba(0, 149, 100, 0) 100%
61 | );
62 | background: -webkit-linear-gradient(
63 | 90deg,
64 | rgba(0, 149, 100, 0) 0%,
65 | rgba(8, 234, 160, 1) 50%,
66 | rgba(0, 149, 100, 0) 100%
67 | );
68 | background: linear-gradient(
69 | 90deg,
70 | rgba(0, 149, 100, 0) 0%,
71 | rgba(8, 234, 160, 1) 50%,
72 | rgba(0, 149, 100, 0) 100%
73 | );
74 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1);
75 | position: absolute;
76 | bottom: 0;
77 | left: 0;
78 | width: 100%;
79 | height: 1px;
80 | }
81 |
82 | .buttonContainer {
83 | position: absolute;
84 | bottom: 20px;
85 | left: 32px;
86 | width: calc(100% - 64px);
87 | width: -webkit-calc(100% - 64px);
88 | text-align: center;
89 | }
90 |
91 | .buttonContainer .buttonLeft {
92 | float: left;
93 | }
94 |
95 | .buttonContainer .buttonRight {
96 | float: Right;
97 | }
98 |
99 | .buttonContainer .buttonCenter {
100 | margin: 0 8px;
101 | }
102 |
103 | .buttonContainer::after {
104 | content: " ";
105 | display: block;
106 | clear: both;
107 | }
108 |
109 | .buttonContainer button {
110 | min-width: 120px;
111 | }
112 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react-swc'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------