From 1862468d9eb33669325e805bcafd9dff5b8087e3 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Fri, 10 Feb 2023 17:09:39 -0500 Subject: [PATCH 01/79] re write screenshot --- src/App.jsx | 11 +- src/components/Mint.jsx | 173 +++++++++++++++------------- src/components/Resizable.jsx | 158 ------------------------- src/components/Resizable.module.css | 62 ---------- src/library/screenshotManager.js | 77 +++++++++++++ src/pages/Mint.jsx | 6 +- src/pages/View.jsx | 10 ++ 7 files changed, 189 insertions(+), 308 deletions(-) delete mode 100644 src/components/Resizable.jsx delete mode 100644 src/components/Resizable.module.css create mode 100644 src/library/screenshotManager.js diff --git a/src/App.jsx b/src/App.jsx index 1d569376..565a5461 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -11,6 +11,7 @@ import { BlinkManager } from "./library/blinkManager" import { LookAtManager } from "./library/lookatManager" import { EffectManager } from "./library/effectManager" import { AnimationManager } from "./library/animationManager" +import { ScreenshotManager } from "./library/screenshotManager" import Scene from "./components/Scene" import Background from "./components/Background" @@ -22,6 +23,7 @@ import BioPage from "./pages/Bio" import Create from "./pages/Create" import Landing from "./pages/Landing" import Appearance from "./pages/Appearance" +import Mint from "./pages/Mint" // dynamically import the manifest const assetImportPath = import.meta.env.VITE_ASSET_PATH + "/manifest.json" @@ -107,6 +109,7 @@ async function fetchAll() { const blinkManager = new BlinkManager(0.1, 0.1, 0.5, 5) const lookatManager = new LookAtManager(80, "editor-scene") const effectManager = new EffectManager() + const screenshotManager = new ScreenshotManager() return { initialManifest, @@ -115,6 +118,7 @@ async function fetchAll() { blinkManager, lookatManager, effectManager, + screenshotManager, } } @@ -156,6 +160,7 @@ export default function App() { blinkManager, lookatManager, effectManager, + screenshotManager, } = resource.read() const [hideUi, setHideUi] = useState(false) @@ -178,6 +183,8 @@ export default function App() { effectManager.camera = camera effectManager.scene = scene + screenshotManager.scene = scene + const updateCameraPosition = () => { if (!effectManager.camera) return @@ -237,7 +244,7 @@ export default function App() { if (controls) { if ( - [ViewMode.APPEARANCE, ViewMode.SAVE, ViewMode.MINT].includes(viewMode) + [ViewMode.APPEARANCE, ViewMode.SAVE].includes(viewMode) ) { controls.enabled = true } else { @@ -292,7 +299,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - // [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 7f494fc0..188c3ec1 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -15,7 +15,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotPosition}) { +export default function MintPopup({screenshotPosition, screenshotManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -90,94 +90,103 @@ export default function MintPopup({screenshotPosition}) { } const mintAsset = async (avatar) => { - let walletAddress = await connectWallet() + console.log(templateInfo) + // let walletAddress = await connectWallet() - const pass = await checkOT(walletAddress); + // const pass = await checkOT(walletAddress); + const pass = true; if(pass) { setMintStatus("Uploading...") let imageHash, glbHash; - const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - if (screenshot) { - let imageName = "AvatarImage_" + Date.now() + ".png"; - imageHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const img_hash = await saveFileToPinata( - screenshot, - imageName - ).catch((reason) => { - console.error(i, "---", reason) - }) - return img_hash - } catch(err) { - console.warn(err); - } - } - throw new Error('failed to upload screenshot'); - setMintStatus("Couldn't save screenshot to pinata") - })(); - } else { - throw new Error("Unable to get screenshot") - } + + const headPosition = templateInfo.traits[0].cameraTarget.height; + const cameraFov = 1.0; + screenshotManager.setCamera(headPosition, cameraFov); + + screenshotManager.saveAsImage(); - const glb = await getGLBBlobData(model) - if (glb) { - let glbName = "AvatarGlb_" + Date.now() + ".glb"; - glbHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const glb_hash = await saveFileToPinata( - glb, - glbName - ).catch((reason) => { - console.error(i, "---", reason) - setMintStatus("Couldn't save glb to pinata") - }) - return glb_hash - } catch(err) { - console.warn(err); - } - } - throw new Error('failed to upload glb'); - setMintStatus("Couldn't save glb to pinata") - })(); - } else { - throw new Error("Unable to get glb") - } + // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) + // if (screenshot) { + // let imageName = "AvatarImage_" + Date.now() + ".png"; + // imageHash = await (async() => { + // for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + // try { + // const img_hash = await saveFileToPinata( + // screenshot, + // imageName + // ).catch((reason) => { + // console.error(i, "---", reason) + // }) + // return img_hash + // } catch(err) { + // console.warn(err); + // } + // } + // throw new Error('failed to upload screenshot'); + // setMintStatus("Couldn't save screenshot to pinata") + // })(); + // } else { + // throw new Error("Unable to get screenshot") + // } - const attributes = getAvatarTraits() - const metadata = { - name: "Avatars", - description: "Character Studio Avatars.", - image: `ipfs://${imageHash.IpfsHash}`, - animation_url: `ipfs://${glbHash.IpfsHash}`, - attributes: attributes - } - const str = JSON.stringify(metadata) - const metaDataHash = await saveFileToPinata( - new Blob([str]), - "AvatarMetadata_" + Date.now() + ".json", - ) - const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` + // const glb = await getGLBBlobData(model) + // if (glb) { + // let glbName = "AvatarGlb_" + Date.now() + ".glb"; + // glbHash = await (async() => { + // for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + // try { + // const glb_hash = await saveFileToPinata( + // glb, + // glbName + // ).catch((reason) => { + // console.error(i, "---", reason) + // setMintStatus("Couldn't save glb to pinata") + // }) + // return glb_hash + // } catch(err) { + // console.warn(err); + // } + // } + // throw new Error('failed to upload glb'); + // setMintStatus("Couldn't save glb to pinata") + // })(); + // } else { + // throw new Error("Unable to get glb") + // } - setMintStatus("Minting...") - const signer = new ethers.providers.Web3Provider( - window.ethereum, - ).getSigner() - const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) - try { - const options = { - value: tokenPrice, - from: walletAddress - } - const tx = await contract.mintToken(1, metadataIpfs, options) - let res = await tx.wait() - if (res.transactionHash) { - setMintStatus("Mint success!") - } - } catch (err) { - setMintStatus("Public Mint failed! Please check your wallet.") - } + // const attributes = getAvatarTraits() + // const metadata = { + // name: "Avatars", + // description: "Character Studio Avatars.", + // image: `ipfs://${imageHash.IpfsHash}`, + // animation_url: `ipfs://${glbHash.IpfsHash}`, + // attributes: attributes + // } + // const str = JSON.stringify(metadata) + // const metaDataHash = await saveFileToPinata( + // new Blob([str]), + // "AvatarMetadata_" + Date.now() + ".json", + // ) + // const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` + + // setMintStatus("Minting...") + // const signer = new ethers.providers.Web3Provider( + // window.ethereum, + // ).getSigner() + // const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) + // try { + // const options = { + // value: tokenPrice, + // from: walletAddress + // } + // const tx = await contract.mintToken(1, metadataIpfs, options) + // let res = await tx.wait() + // if (res.transactionHash) { + // setMintStatus("Mint success!") + // } + // } catch (err) { + // setMintStatus("Public Mint failed! Please check your wallet.") + // } } else { return; } diff --git a/src/components/Resizable.jsx b/src/components/Resizable.jsx deleted file mode 100644 index 08ad41c3..00000000 --- a/src/components/Resizable.jsx +++ /dev/null @@ -1,158 +0,0 @@ -import React, { useState } from 'react'; -import styles from "./Resizable.module.css" - -const ResizableDiv = ({setScreenshotPosition, screenshotPosition}) => { - - const [initialPos, setInitialPos] = useState(null); - const [initialSize, setInitialSize] = useState(null); - - const [moving, setMoving] = useState(false) - const [scaling, setScaling] = useState(false) - - - const windowResize = () => { - updateMask() - } - - - - React.useEffect (() => { - let resizable = document.getElementById('screenshots'); - let draggable = document.getElementById('Screenshot-block'); - - resizable.style.width = `${screenshotPosition.width}px`; - resizable.style.height = `${screenshotPosition.height}px`; - - draggable.style.paddingTop = `${screenshotPosition.y+20}px` - draggable.style.paddingLeft = `${screenshotPosition.x}px` - - - updateMask() - window.addEventListener('resize', windowResize); - return () => { - window.removeEventListener('resize', windowResize) - } - },[]) - - - - const handleMouseMove = (e) => { - //console.log(moving) - if (moving){ - let draggable = document.getElementById('Screenshot-block'); - let resizable = document.getElementById('screenshots'); - - const posX = (e.clientX - resizable.offsetWidth/2)// + initialPos.x - const posY = (e.clientY - resizable.offsetHeight/2)// + initialPos.y - - draggable.style.paddingTop = `${posY+20}px` - - draggable.style.paddingLeft = `${posX}px` - - //moveMask(posX, posY, resizable.offsetWidth, resizable.offsetHeight); - updateMask(); - setScreenshotPosition({...screenshotPosition, ...{x:posX, y:posY}}); - - } - - if (scaling){ - let resizable = document.getElementById('screenshots'); - - const newWidth = parseInt(initialSize.width) + parseInt(e.clientX - initialPos.x) - const newHeight = parseInt(initialSize.height) + parseInt(e.clientY - initialPos.y) - - const sameRatio = newWidth >= newHeight ? newWidth : newHeight - if (newWidth > 50 && newHeight > 50){ - resizable.style.width = `${sameRatio}px`; - resizable.style.height = `${sameRatio}px`; - - //resizeMask() - updateMask(); - - setScreenshotPosition({...screenshotPosition,...{width:sameRatio, height:sameRatio}}); - } - } - } - const updateMask = () =>{ - const fscreen = document.getElementById('fscreen-div'); - - const maskLeft = document.getElementById('maskLeft'); - const maskTop = document.getElementById('maskTop'); - const maskRight = document.getElementById('maskRight'); - const maskBottom = document.getElementById('maskBottom'); - - const clientHeight = fscreen.clientHeight; - const clientWidth = fscreen.clientWidth; - - maskLeft.style.width = `${screenshotPosition.x}px` - - maskTop.style.left = `${screenshotPosition.x}px` - maskTop.style.height = `${screenshotPosition.y}px` - maskTop.style.width = `${screenshotPosition.width}px` - - maskRight.style.width = `${clientWidth - screenshotPosition.x - screenshotPosition.width}px` - - maskBottom.style.left = `${screenshotPosition.x}px` - maskBottom.style.height = `${clientHeight - screenshotPosition.y - screenshotPosition.height}px` - maskBottom.style.width = `${screenshotPosition.width}px` - } - - const initialFrame = (e) => { - setMoving(true) - let draggable = document.getElementById('Screenshot-block'); - let resizable = document.getElementById('screenshots'); - - const leftPos = e.clientX - draggable.style.paddingLeft; - - draggable.style.paddingTop = e.clientY - resizable.offsetHeight/2; - - - setInitialPos({x:leftPos, y:e.clientY}); - - } - - const initial = (e) => { - setScaling(true) - let resizable = document.getElementById('screenshots'); - - setInitialPos({x:e.clientX, y:e.clientY}); - setInitialSize({width:resizable.offsetWidth, height:resizable.offsetHeight}); - - } - - const endInteraction = () => { - setScaling(false) - setMoving(false) - } - - return( -
handleMouseMove(ev)} - onMouseLeave = {endInteraction} - onMouseUp = {endInteraction} - onTouchEnd = {endInteraction} - onTouchCancel = {endInteraction}> -
-
-
-
- -
-
-
-
-
- ); - -} - -export default ResizableDiv; \ No newline at end of file diff --git a/src/components/Resizable.module.css b/src/components/Resizable.module.css deleted file mode 100644 index 4754b7cf..00000000 --- a/src/components/Resizable.module.css +++ /dev/null @@ -1,62 +0,0 @@ -.Block{ - display: flex; - align-items: flex-end; - position: absolute; - overflow: hidden; - -} -.Draggable{ - background: rgb(230, 230, 230); - cursor: pointer; - height: 20px; - width: 20px; -} -.FullScreen{ - display: flex; - overflow: hidden; - position: absolute; - width: 100%; - height: 100%; -} -.BlockScreen{ - position:relative; - width: 100%; - height: 100%; -} - -.leftBlock{ - animation: fadein 1s; - position:absolute; - background-color: rgba(0, 0, 0, 0.6); - height: 100%; -} -.rightBlock{ - animation: fadein 1s; - position:absolute; - right: 0; - background-color: rgba(0, 0, 0, 0.6); - height: 100%; -} -.topBlock{ - animation: fadein 1s; - position:absolute; - top: 0; - background-color: rgba(0, 0, 0, 0.6); - height: 25px; -} -.lowerBlock{ - animation: fadein 1s; - position:absolute; - bottom: 0; - background-color: rgba(0, 0, 0, 0.6); -} - -body { - animation: fadeInAnimation ease 3s; - animation-iteration-count: 1; - animation-fill-mode: forwards; -} -@keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} \ No newline at end of file diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js new file mode 100644 index 00000000..57a6d7de --- /dev/null +++ b/src/library/screenshotManager.js @@ -0,0 +1,77 @@ +import * as THREE from "three" + +const localVector = new THREE.Vector3(); + +export class ScreenshotManager { + constructor() { + this.frameRate = 1000 / 30; + + this.renderer = new THREE.WebGLRenderer({ + preserveDrawingBuffer: true + }); + + this.renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight); + this.renderTarget.texture.encoding = THREE.sRGBEncoding; + + this.renderer.setSize(window.innerWidth, window.innerHeight); + + this.camera = new THREE.PerspectiveCamera( + 30, + window.innerWidth / window.innerHeight, + 0.1, + 1000, + ) + // this.setUpCamera(); + this.update(); + } + + setCamera(height, playerCameraDistance) { + this.camera.position.y = height; + + localVector.set(0, 0, -1); + this.cameraDir = localVector.applyQuaternion(this.camera.quaternion); + this.cameraDir.normalize(); + this.camera.position.x = -this.cameraDir.x * playerCameraDistance; + this.camera.position.z = -this.cameraDir.z * playerCameraDistance; + + } + + saveAsImage() { + let imgData; + try { + this.renderer.render(this.scene, this.camera); + const strDownloadMime = "image/octet-stream"; + const strMime = "image/jpeg"; + imgData = this.renderer.domElement.toDataURL(strMime); + this.saveFile(imgData.replace(strMime, strDownloadMime), "test.jpg"); + } catch (e) { + console.log(e); + return; + } + + } + + saveFile (strData, filename) { + const link = document.createElement('a'); + if (typeof link.download === 'string') { + document.body.appendChild(link); //Firefox requires the link to be in the body + link.download = filename; + link.href = strData; + link.click(); + document.body.removeChild(link); //remove the link when done + } else { + location.replace(uri); + } + } + + update() { + setInterval(() => { + + // this.renderer.render(this.scene, this.camera); + + }, this.frameRate); + } + + + +} \ No newline at end of file diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index fd7f4a5b..5a6a6b45 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -3,10 +3,9 @@ import styles from "./Mint.module.css" import { ViewMode, ViewContext } from "../context/ViewContext" import Mint from "../components/Mint" -import ResizableDiv from "../components/Resizable" import CustomButton from "../components/custom-button" -function MintComponent() { +function MintComponent({screenshotManager}) { const { setViewMode } = React.useContext(ViewContext) const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); @@ -21,13 +20,12 @@ function MintComponent() { return (
Mint Your Character
-
- +
diff --git a/src/pages/View.jsx b/src/pages/View.jsx index 1c557b6b..aa8ff1c5 100644 --- a/src/pages/View.jsx +++ b/src/pages/View.jsx @@ -16,6 +16,9 @@ function View({templateInfo}) { speechRecognition.stop() setMicEnabled(false) } + const next = () =>{ + setViewMode(ViewMode.MINT) + } return (
@@ -41,6 +44,13 @@ function View({templateInfo}) { className={styles.buttonLeft} onClick={back} /> +
) From 5241346a25dba069a91d814570f1a39159105b21 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Fri, 10 Feb 2023 17:37:20 -0500 Subject: [PATCH 02/79] clean code --- src/components/Mint.jsx | 8 +++++--- src/library/screenshotManager.js | 21 +++++---------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 188c3ec1..9895c615 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -90,7 +90,6 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { } const mintAsset = async (avatar) => { - console.log(templateInfo) // let walletAddress = await connectWallet() // const pass = await checkOT(walletAddress); @@ -99,11 +98,14 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { setMintStatus("Uploading...") let imageHash, glbHash; - const headPosition = templateInfo.traits[0].cameraTarget.height; + const female = templateInfo.name === 'Drophunter' ? true : false; + const headPosition = female ? 1.35 : 1.45; const cameraFov = 1.0; + screenshotManager.setCamera(headPosition, cameraFov); + let imageName = "AvatarImage_" + Date.now() + ".png"; + screenshotManager.saveAsImage(imageName); - screenshotManager.saveAsImage(); // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) // if (screenshot) { diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 57a6d7de..9001c27c 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -21,8 +21,6 @@ export class ScreenshotManager { 0.1, 1000, ) - // this.setUpCamera(); - this.update(); } setCamera(height, playerCameraDistance) { @@ -36,17 +34,18 @@ export class ScreenshotManager { } - saveAsImage() { + saveAsImage(imageName) { let imgData; try { this.renderer.render(this.scene, this.camera); const strDownloadMime = "image/octet-stream"; - const strMime = "image/jpeg"; + const strMime = "image/png"; imgData = this.renderer.domElement.toDataURL(strMime); - this.saveFile(imgData.replace(strMime, strDownloadMime), "test.jpg"); + this.saveFile(imgData.replace(strMime, strDownloadMime), imageName); + return true; } catch (e) { console.log(e); - return; + return false; } } @@ -64,14 +63,4 @@ export class ScreenshotManager { } } - update() { - setInterval(() => { - - // this.renderer.render(this.scene, this.camera); - - }, this.frameRate); - } - - - } \ No newline at end of file From 994de2e9a23f4b3eee2e1b86ae12adca4fc34f9e Mon Sep 17 00:00:00 2001 From: Jacob LeCoq Date: Fri, 10 Feb 2023 16:48:06 -0600 Subject: [PATCH 03/79] adjust mint page to match figma mockups --- .gitignore | 3 +- package.json | 1 + public/assets/icons/polygon.svg | 18 ++ src/App.jsx | 25 +-- .../custom-button/IconCollection.jsx | 8 + src/pages/Mint.jsx | 51 ++++-- src/pages/Mint.module.css | 113 ------------- src/pages/Mint.module.scss | 154 ++++++++++++++++++ src/pages/Save.jsx | 54 +++--- src/pages/Save.module.css | 28 ++-- 10 files changed, 284 insertions(+), 171 deletions(-) create mode 100644 public/assets/icons/polygon.svg delete mode 100644 src/pages/Mint.module.css create mode 100644 src/pages/Mint.module.scss diff --git a/.gitignore b/.gitignore index 27cf4f0a..e91b9927 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ character-assets .eslint-cache .env .eslintcache -lerna-debug.log \ No newline at end of file +lerna-debug.log +.vscode \ No newline at end of file diff --git a/package.json b/package.json index 56762747..9b968ff0 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "eslint-plugin-no-inline-styles": "^1.0.5", "eslint-plugin-react": "^7.31.11", "prettier": "^2.3.2", + "sass": "^1.58.0", "vite": "^4.0.0" } } diff --git a/public/assets/icons/polygon.svg b/public/assets/icons/polygon.svg new file mode 100644 index 00000000..2ee2e72a --- /dev/null +++ b/public/assets/icons/polygon.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/src/App.jsx b/src/App.jsx index 200c31d5..3b1bd5fb 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -12,16 +12,17 @@ import { LookAtManager } from "./library/lookatManager" import { EffectManager } from "./library/effectManager" import { AnimationManager } from "./library/animationManager" -const Scene = React.lazy(() => import("./components/Scene")) -const Background = React.lazy(() => import("./components/Background")) - -const View = React.lazy(() => import("./pages/View")) -const Save = React.lazy(() => import("./pages/Save")) -const Load = React.lazy(() => import("./pages/Load")) -const BioPage = React.lazy(() => import("./pages/Bio")) -const Create = React.lazy(() => import("./pages/Create")) -const Landing = React.lazy(() => import("./pages/Landing")) -const Appearance = React.lazy(() => import("./pages/Appearance")) +import Scene from "./components/Scene" +import Background from "./components/Background" + +import View from "./pages/View" +import Mint from "./pages/Mint" +import Save from "./pages/Save" +import Load from "./pages/Load" +import BioPage from "./pages/Bio" +import Create from "./pages/Create" +import Landing from "./pages/Landing" +import Appearance from "./pages/Appearance" // dynamically import the manifest const assetImportPath = import.meta.env.VITE_ASSET_PATH + "/manifest.json" @@ -181,7 +182,7 @@ export default function App() { const updateCameraPosition = () => { if (!effectManager.camera) return - if ([ViewMode.BIO, ViewMode.MINT, ViewMode.CHAT].includes(viewMode)) { + if ([ViewMode.BIO, ViewMode.CHAT].includes(viewMode)) { // auto move camera if (viewMode === ViewMode.CHAT) { cameraDistance = cameraDistanceChat @@ -292,7 +293,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - // [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/custom-button/IconCollection.jsx b/src/components/custom-button/IconCollection.jsx index 5918c6fa..68363aef 100644 --- a/src/components/custom-button/IconCollection.jsx +++ b/src/components/custom-button/IconCollection.jsx @@ -123,4 +123,12 @@ export const IconCollection = [ name: 'soundoff', file: '/assets/icons/soundoff.svg', }, + { + name: 'soundoff', + file: '/assets/icons/soundoff.svg', + }, + { + name: 'polygon', + file: '/assets/icons/polygon.svg', + }, ]; \ No newline at end of file diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index fd7f4a5b..0e2fd357 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -1,14 +1,14 @@ import React from "react" -import styles from "./Mint.module.css" +import styles from "./Mint.module.scss" import { ViewMode, ViewContext } from "../context/ViewContext" -import Mint from "../components/Mint" -import ResizableDiv from "../components/Resizable" +// import Mint from "../components/Mint" +// import ResizableDiv from "../components/Resizable" import CustomButton from "../components/custom-button" function MintComponent() { const { setViewMode } = React.useContext(ViewContext) - const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); + // const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); const back = () => { setViewMode(ViewMode.SAVE) @@ -18,19 +18,48 @@ function MintComponent() { setViewMode(ViewMode.CHAT) } + function MenuTitle() { + return ( +
+
+
Mint
+
+ ) + } + return (
Mint Your Character
- + + {/* */} +
-
-
-
- - + + +
+ + +
+ + + + (Genesis pass holders only)
-
+ +
div { + padding: 16px !important; + } + + .genesisText { + opacity: 0.4; + + .required:after { + content: "*"; + color: red; + } + } + + .divider { + width: 80%; + height: 1px; + margin: 8px 0; + opacity: 0.2; + background: #e0e6e5; + } + } + } + + .bottomContainer { + z-index: 0; + display: flex; + padding: 20px 32px; + justify-content: space-between; + + button { + min-width: 120px; + } + } +} + +.topLine { + background: rgb(0, 149, 100); + background: -moz-linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + + background: -webkit-linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + + background: linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + + top: 0; + left: 0; + width: 100%; + height: 1px; + position: absolute; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1); +} + +.bottomLine { + background: rgb(0, 149, 100); + background: -moz-linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + background: -webkit-linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + background: linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1); + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 1px; +} diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index 51b0048b..6dec30a6 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -13,7 +13,7 @@ function Save() { } const mint = () => { - setViewMode(ViewMode.CHAT) + setViewMode(ViewMode.MINT) } @@ -25,30 +25,36 @@ function Save() {
Save Your Character
- +
+ +
+ + - {/* - - */} - + +
+ + + +
); diff --git a/src/pages/Save.module.css b/src/pages/Save.module.css index fa9073a0..416fb1d7 100644 --- a/src/pages/Save.module.css +++ b/src/pages/Save.module.css @@ -1,18 +1,26 @@ +.container{ + height: 100%; + display: flex; + align-items: flex-end; + justify-content: center; +} + .buttonContainer { - position: absolute; - bottom: 20px; - left: 32px; - width: calc(100% - 64px); - width: -webkit-calc(100% - 64px); - text-align: center; + z-index: 0; + width: 100%; + padding: 20px 32px; + display: flex; } -.buttonContainer .buttonLeft { - float: left; +.buttonContainer .leftButtonContainer{ + margin-right: auto; + display: inline-flex; + } -.buttonContainer .buttonRight { - float: Right; +.buttonContainer .rightButtonContainer{ + margin-left: auto; + display: inline-flex; } .buttonContainer .buttonCenter { From 95b65f6979701c0973663994199d6e607322a3b2 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Fri, 10 Feb 2023 18:03:53 -0500 Subject: [PATCH 04/79] convert image to blob --- src/components/Mint.jsx | 158 +++++++++++++++---------------- src/library/screenshotManager.js | 12 ++- 2 files changed, 88 insertions(+), 82 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 9895c615..fe79812f 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -104,91 +104,91 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; - screenshotManager.saveAsImage(imageName); + const screenshot = screenshotManager.saveAsImage(imageName); // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - // if (screenshot) { - // let imageName = "AvatarImage_" + Date.now() + ".png"; - // imageHash = await (async() => { - // for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - // try { - // const img_hash = await saveFileToPinata( - // screenshot, - // imageName - // ).catch((reason) => { - // console.error(i, "---", reason) - // }) - // return img_hash - // } catch(err) { - // console.warn(err); - // } - // } - // throw new Error('failed to upload screenshot'); - // setMintStatus("Couldn't save screenshot to pinata") - // })(); - // } else { - // throw new Error("Unable to get screenshot") - // } + if (screenshot) { + let imageName = "AvatarImage_" + Date.now() + ".png"; + imageHash = await (async() => { + for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + try { + const img_hash = await saveFileToPinata( + screenshot, + imageName + ).catch((reason) => { + console.error(i, "---", reason) + }) + return img_hash + } catch(err) { + console.warn(err); + } + } + throw new Error('failed to upload screenshot'); + setMintStatus("Couldn't save screenshot to pinata") + })(); + } else { + throw new Error("Unable to get screenshot") + } - // const glb = await getGLBBlobData(model) - // if (glb) { - // let glbName = "AvatarGlb_" + Date.now() + ".glb"; - // glbHash = await (async() => { - // for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - // try { - // const glb_hash = await saveFileToPinata( - // glb, - // glbName - // ).catch((reason) => { - // console.error(i, "---", reason) - // setMintStatus("Couldn't save glb to pinata") - // }) - // return glb_hash - // } catch(err) { - // console.warn(err); - // } - // } - // throw new Error('failed to upload glb'); - // setMintStatus("Couldn't save glb to pinata") - // })(); - // } else { - // throw new Error("Unable to get glb") - // } + const glb = await getGLBBlobData(model) + if (glb) { + let glbName = "AvatarGlb_" + Date.now() + ".glb"; + glbHash = await (async() => { + for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + try { + const glb_hash = await saveFileToPinata( + glb, + glbName + ).catch((reason) => { + console.error(i, "---", reason) + setMintStatus("Couldn't save glb to pinata") + }) + return glb_hash + } catch(err) { + console.warn(err); + } + } + throw new Error('failed to upload glb'); + setMintStatus("Couldn't save glb to pinata") + })(); + } else { + throw new Error("Unable to get glb") + } - // const attributes = getAvatarTraits() - // const metadata = { - // name: "Avatars", - // description: "Character Studio Avatars.", - // image: `ipfs://${imageHash.IpfsHash}`, - // animation_url: `ipfs://${glbHash.IpfsHash}`, - // attributes: attributes - // } - // const str = JSON.stringify(metadata) - // const metaDataHash = await saveFileToPinata( - // new Blob([str]), - // "AvatarMetadata_" + Date.now() + ".json", - // ) - // const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` + const attributes = getAvatarTraits() + const metadata = { + name: "Avatars", + description: "Character Studio Avatars.", + image: `ipfs://${imageHash.IpfsHash}`, + animation_url: `ipfs://${glbHash.IpfsHash}`, + attributes: attributes + } + const str = JSON.stringify(metadata) + const metaDataHash = await saveFileToPinata( + new Blob([str]), + "AvatarMetadata_" + Date.now() + ".json", + ) + const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` - // setMintStatus("Minting...") - // const signer = new ethers.providers.Web3Provider( - // window.ethereum, - // ).getSigner() - // const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) - // try { - // const options = { - // value: tokenPrice, - // from: walletAddress - // } - // const tx = await contract.mintToken(1, metadataIpfs, options) - // let res = await tx.wait() - // if (res.transactionHash) { - // setMintStatus("Mint success!") - // } - // } catch (err) { - // setMintStatus("Public Mint failed! Please check your wallet.") - // } + setMintStatus("Minting...") + const signer = new ethers.providers.Web3Provider( + window.ethereum, + ).getSigner() + const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) + try { + const options = { + value: tokenPrice, + from: walletAddress + } + const tx = await contract.mintToken(1, metadataIpfs, options) + let res = await tx.wait() + if (res.transactionHash) { + setMintStatus("Mint success!") + } + } catch (err) { + setMintStatus("Public Mint failed! Please check your wallet.") + } } else { return; } diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 9001c27c..4106da32 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -1,11 +1,10 @@ import * as THREE from "three" +import { Buffer } from "buffer"; const localVector = new THREE.Vector3(); export class ScreenshotManager { constructor() { - this.frameRate = 1000 / 30; - this.renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true }); @@ -41,8 +40,15 @@ export class ScreenshotManager { const strDownloadMime = "image/octet-stream"; const strMime = "image/png"; imgData = this.renderer.domElement.toDataURL(strMime); + + const base64Data = Buffer.from( + imgData.replace(/^data:image\/\w+;base64,/, ""), + "base64" + ); + const blob = new Blob([base64Data], { type: "image/jpeg" }); + this.saveFile(imgData.replace(strMime, strDownloadMime), imageName); - return true; + return blob; } catch (e) { console.log(e); return false; From 2d62017281ba628c79d2196587778a3e533c42dd Mon Sep 17 00:00:00 2001 From: Jacob LeCoq Date: Fri, 10 Feb 2023 17:13:11 -0600 Subject: [PATCH 05/79] disable mint button on save page --- src/pages/Save.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index 6dec30a6..19d01ecb 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -12,9 +12,9 @@ function Save() { setViewMode(ViewMode.BIO) } - const mint = () => { - setViewMode(ViewMode.MINT) - } + // const mint = () => { + // setViewMode(ViewMode.MINT) + // } const next = () => { @@ -39,13 +39,13 @@ function Save() {
- + /> */} Date: Fri, 10 Feb 2023 18:39:34 -0500 Subject: [PATCH 06/79] open eyes when screenshot --- src/App.jsx | 1 + src/library/blinkManager.js | 4 ++++ src/library/screenshotManager.js | 9 ++++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 565a5461..b3768bc4 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -184,6 +184,7 @@ export default function App() { effectManager.scene = scene screenshotManager.scene = scene + screenshotManager.blinkManager = blinkManager const updateCameraPosition = () => { if (!effectManager.camera) return diff --git a/src/library/blinkManager.js b/src/library/blinkManager.js index 1650e8ae..3a59757d 100644 --- a/src/library/blinkManager.js +++ b/src/library/blinkManager.js @@ -24,6 +24,10 @@ export class BlinkManager { this.vrmBlinkers.push(vrm) } + setEyeOpen() { + this._eyeOpen = 2; + } + update(){ setInterval(() => { const deltaTime = this.clock.getDelta() diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 4106da32..b69fc88b 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -9,14 +9,16 @@ export class ScreenshotManager { preserveDrawingBuffer: true }); - this.renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight); + const width = 500; + const height = 750; + this.renderTarget = new THREE.WebGLRenderTarget(width, height); this.renderTarget.texture.encoding = THREE.sRGBEncoding; - this.renderer.setSize(window.innerWidth, window.innerHeight); + this.renderer.setSize(width, height); this.camera = new THREE.PerspectiveCamera( 30, - window.innerWidth / window.innerHeight, + width / height, 0.1, 1000, ) @@ -36,6 +38,7 @@ export class ScreenshotManager { saveAsImage(imageName) { let imgData; try { + this.blinkManager.setEyeOpen(); this.renderer.render(this.scene, this.camera); const strDownloadMime = "image/octet-stream"; const strMime = "image/png"; From b71f24875b8b93bef32cafae299e483eb3ed2cea Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 10 Feb 2023 18:01:03 -0600 Subject: [PATCH 07/79] screenshot encoding --- src/library/screenshotManager.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index b69fc88b..bc5305e2 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -8,11 +8,10 @@ export class ScreenshotManager { this.renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true }); + this.renderer.outputEncoding = THREE.sRGBEncoding const width = 500; const height = 750; - this.renderTarget = new THREE.WebGLRenderTarget(width, height); - this.renderTarget.texture.encoding = THREE.sRGBEncoding; this.renderer.setSize(width, height); From 643b6f56f96f65d8138323e5f9b1035c5447927a Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 10 Feb 2023 18:07:48 -0600 Subject: [PATCH 08/79] add pause to animation manager --- src/library/animationManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/animationManager.js b/src/library/animationManager.js index 31201aaf..52a89474 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -76,7 +76,7 @@ export class AnimationManager{ ); } setInterval(() => { - this.update(); + //this.update(); }, 1000/30); } async loadAnimations(path){ From 9f6944881f7a5fc37cd886eee4e98803637f180e Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 10 Feb 2023 18:09:06 -0600 Subject: [PATCH 09/79] fix paused var --- src/library/animationManager.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/library/animationManager.js b/src/library/animationManager.js index 52a89474..fa0d9474 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -75,10 +75,18 @@ export class AnimationManager{ offset[2] ); } + this.paused = false; setInterval(() => { - //this.update(); + if (!this.paused) + this.update(); }, 1000/30); } + pause(){ + this.paused = true; + } + resume(){ + this.paused = false; + } async loadAnimations(path){ const loader = path.endsWith('.fbx') ? fbxLoader : gltfLoader; const anim = await loader.loadAsync(path); From e5430aa10125111d9fd0556c24d1d0eee885fee6 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 10 Feb 2023 18:32:13 -0600 Subject: [PATCH 10/79] reset camera for screenshot --- src/App.jsx | 2 +- src/components/Mint.jsx | 6 +++--- src/library/animationManager.js | 10 ++++++++++ src/pages/Mint.jsx | 4 ++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index b3768bc4..9b0429d5 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -300,7 +300,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index fe79812f..85e3eb31 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -15,12 +15,12 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotPosition, screenshotManager}) { +export default function MintPopup({screenshotPosition, screenshotManager, animationManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); const chainId = "0x89"; - + useEffect(() => { ( async () => { const defaultProvider = new ethers.providers.StaticJsonRpcProvider('https://polygon-rpc.com/') @@ -101,7 +101,7 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { const female = templateInfo.name === 'Drophunter' ? true : false; const headPosition = female ? 1.35 : 1.45; const cameraFov = 1.0; - + animationManager.reset(); screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; const screenshot = screenshotManager.saveAsImage(imageName); diff --git a/src/library/animationManager.js b/src/library/animationManager.js index fa0d9474..cc8d6dc5 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -48,6 +48,11 @@ class AnimationControl { this.actions[curIdx].play(); } + reset(){ + this.to.reset(); + this.to.play(); + } + dispose(){ this.animationManager.disposeAnimation(this); //console.log("todo dispose animation control") @@ -87,6 +92,11 @@ export class AnimationManager{ resume(){ this.paused = false; } + reset(){ + this.animationControls.forEach(control => { + control.reset() + }); + } async loadAnimations(path){ const loader = path.endsWith('.fbx') ? fbxLoader : gltfLoader; const anim = await loader.loadAsync(path); diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 5a6a6b45..6f92ec29 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -5,7 +5,7 @@ import { ViewMode, ViewContext } from "../context/ViewContext" import Mint from "../components/Mint" import CustomButton from "../components/custom-button" -function MintComponent({screenshotManager}) { +function MintComponent({screenshotManager, animationManager}) { const { setViewMode } = React.useContext(ViewContext) const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); @@ -25,7 +25,7 @@ function MintComponent({screenshotManager}) {
- +
From d1a3866fc84400ffd7ef803bb9fb47ead14edfcc Mon Sep 17 00:00:00 2001 From: tcm390 Date: Fri, 10 Feb 2023 22:35:59 -0500 Subject: [PATCH 11/79] revert blink manager and animation manager --- src/App.jsx | 3 +-- src/components/Mint.jsx | 3 +-- src/library/animationManager.js | 22 ++-------------------- src/library/blinkManager.js | 4 ---- src/library/screenshotManager.js | 1 - src/pages/Mint.jsx | 4 ++-- 6 files changed, 6 insertions(+), 31 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 9b0429d5..565a5461 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -184,7 +184,6 @@ export default function App() { effectManager.scene = scene screenshotManager.scene = scene - screenshotManager.blinkManager = blinkManager const updateCameraPosition = () => { if (!effectManager.camera) return @@ -300,7 +299,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 85e3eb31..65c2871b 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -15,7 +15,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotPosition, screenshotManager, animationManager}) { +export default function MintPopup({screenshotPosition, screenshotManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -101,7 +101,6 @@ export default function MintPopup({screenshotPosition, screenshotManager, animat const female = templateInfo.name === 'Drophunter' ? true : false; const headPosition = female ? 1.35 : 1.45; const cameraFov = 1.0; - animationManager.reset(); screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; const screenshot = screenshotManager.saveAsImage(imageName); diff --git a/src/library/animationManager.js b/src/library/animationManager.js index cc8d6dc5..9db19464 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -48,11 +48,6 @@ class AnimationControl { this.actions[curIdx].play(); } - reset(){ - this.to.reset(); - this.to.play(); - } - dispose(){ this.animationManager.disposeAnimation(this); //console.log("todo dispose animation control") @@ -80,23 +75,10 @@ export class AnimationManager{ offset[2] ); } - this.paused = false; setInterval(() => { - if (!this.paused) - this.update(); + this.update(); }, 1000/30); } - pause(){ - this.paused = true; - } - resume(){ - this.paused = false; - } - reset(){ - this.animationControls.forEach(control => { - control.reset() - }); - } async loadAnimations(path){ const loader = path.endsWith('.fbx') ? fbxLoader : gltfLoader; const anim = await loader.loadAsync(path); @@ -219,4 +201,4 @@ export class AnimationManager{ else this.weightOut = 0; } } -} +} \ No newline at end of file diff --git a/src/library/blinkManager.js b/src/library/blinkManager.js index 3a59757d..1650e8ae 100644 --- a/src/library/blinkManager.js +++ b/src/library/blinkManager.js @@ -24,10 +24,6 @@ export class BlinkManager { this.vrmBlinkers.push(vrm) } - setEyeOpen() { - this._eyeOpen = 2; - } - update(){ setInterval(() => { const deltaTime = this.clock.getDelta() diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index bc5305e2..0e407da7 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -37,7 +37,6 @@ export class ScreenshotManager { saveAsImage(imageName) { let imgData; try { - this.blinkManager.setEyeOpen(); this.renderer.render(this.scene, this.camera); const strDownloadMime = "image/octet-stream"; const strMime = "image/png"; diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 6f92ec29..5a6a6b45 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -5,7 +5,7 @@ import { ViewMode, ViewContext } from "../context/ViewContext" import Mint from "../components/Mint" import CustomButton from "../components/custom-button" -function MintComponent({screenshotManager, animationManager}) { +function MintComponent({screenshotManager}) { const { setViewMode } = React.useContext(ViewContext) const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); @@ -25,7 +25,7 @@ function MintComponent({screenshotManager, animationManager}) {
- +
From 9e7e90392df66f899709d9f93755258f27d47874 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Mon, 13 Feb 2023 11:10:36 -0500 Subject: [PATCH 12/79] use head world position for screenshot instead of harded code --- src/components/Mint.jsx | 14 ++++++++++---- src/library/screenshotManager.js | 8 ++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 65c2871b..ba4d4099 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -1,3 +1,5 @@ +import * as THREE from 'three'; + import axios from "axios" import { BigNumber, ethers } from "ethers" import React, { Fragment, useContext, useState, useEffect } from "react" @@ -88,8 +90,15 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { }) return metadataTraits } - + const headPosition = new THREE.Vector3(); const mintAsset = async (avatar) => { + console.log(avatar) + avatar.traverse(o => { + if (o.isSkinnedMesh) { + const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] + headBone.getWorldPosition(headPosition) + } + }); // let walletAddress = await connectWallet() // const pass = await checkOT(walletAddress); @@ -97,9 +106,6 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { if(pass) { setMintStatus("Uploading...") let imageHash, glbHash; - - const female = templateInfo.name === 'Drophunter' ? true : false; - const headPosition = female ? 1.35 : 1.45; const cameraFov = 1.0; screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 0e407da7..5e772ae3 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -23,14 +23,14 @@ export class ScreenshotManager { ) } - setCamera(height, playerCameraDistance) { - this.camera.position.y = height; + setCamera(headPosition, playerCameraDistance) { + this.camera.position.copy(headPosition); localVector.set(0, 0, -1); this.cameraDir = localVector.applyQuaternion(this.camera.quaternion); this.cameraDir.normalize(); - this.camera.position.x = -this.cameraDir.x * playerCameraDistance; - this.camera.position.z = -this.cameraDir.z * playerCameraDistance; + this.camera.position.x -= this.cameraDir.x * playerCameraDistance; + this.camera.position.z -= this.cameraDir.z * playerCameraDistance; } From f23958784029103151c1c341aafea543166dfa3c Mon Sep 17 00:00:00 2001 From: tcm390 Date: Mon, 13 Feb 2023 11:11:20 -0500 Subject: [PATCH 13/79] clean code --- src/components/Mint.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index ba4d4099..4e78ceb8 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -92,7 +92,6 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { } const headPosition = new THREE.Vector3(); const mintAsset = async (avatar) => { - console.log(avatar) avatar.traverse(o => { if (o.isSkinnedMesh) { const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] From b82e12f07ef0c9a88248c55a8df0331188bb8504 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Mon, 13 Feb 2023 11:23:07 -0500 Subject: [PATCH 14/79] clean code --- src/components/Mint.jsx | 10 +++++----- src/pages/Mint.jsx | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 4e78ceb8..a1a27ca1 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -17,7 +17,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotPosition, screenshotManager}) { +export default function MintPopup({screenshotManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -198,10 +198,10 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { } } - const takeScreenshot = async () => { - const img = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - const glb = await getGLBBlobData(model) - } + // const takeScreenshot = async () => { + // const img = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) + // const glb = await getGLBBlobData(model) + // } const checkOT = async (address) => { if(address) { diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 5a6a6b45..fb53258a 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -7,7 +7,7 @@ import CustomButton from "../components/custom-button" function MintComponent({screenshotManager}) { const { setViewMode } = React.useContext(ViewContext) - const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); + // const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); const back = () => { setViewMode(ViewMode.SAVE) @@ -25,7 +25,7 @@ function MintComponent({screenshotManager}) {
- +
From 8d04bc1e6620d0a204f4aea88b427678fceb09f5 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Mon, 13 Feb 2023 11:27:38 -0500 Subject: [PATCH 15/79] clean code --- src/components/Mint.jsx | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index a1a27ca1..ccd2aacf 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -12,6 +12,8 @@ import { CharacterContract, EternalProxyContract, webaverseGenesisAddress } from import { getGLBBlobData } from "../library/download-utils" import styles from "./Mint.module.css" +const localVector = new THREE.Vector3(); + const pinataApiKey = import.meta.env.VITE_PINATA_API_KEY const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET @@ -90,21 +92,25 @@ export default function MintPopup({screenshotManager}) { }) return metadataTraits } - const headPosition = new THREE.Vector3(); + + const mintAsset = async (avatar) => { - avatar.traverse(o => { - if (o.isSkinnedMesh) { - const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] - headBone.getWorldPosition(headPosition) - } - }); // let walletAddress = await connectWallet() // const pass = await checkOT(walletAddress); const pass = true; + if(pass) { setMintStatus("Uploading...") let imageHash, glbHash; + + avatar.traverse(o => { + if (o.isSkinnedMesh) { + const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] + headBone.getWorldPosition(localVector) + } + }); + const headPosition = localVector; const cameraFov = 1.0; screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; From 47b0865601fe9f717b7018ca39722fb8925f34db Mon Sep 17 00:00:00 2001 From: tcm390 Date: Mon, 13 Feb 2023 11:31:52 -0500 Subject: [PATCH 16/79] spacing --- src/components/Mint.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index ccd2aacf..6dc66683 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -106,8 +106,8 @@ export default function MintPopup({screenshotManager}) { avatar.traverse(o => { if (o.isSkinnedMesh) { - const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] - headBone.getWorldPosition(localVector) + const headBone = o.skeleton.bones.filter(bone => bone.name === 'head')[0]; + headBone.getWorldPosition(localVector); } }); const headPosition = localVector; From ebf8a9893db8825b3cd53b9c00c149753b47bfef Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 11:28:05 -0500 Subject: [PATCH 17/79] change screen shot ratio and camera fov --- src/components/Mint.jsx | 3 ++- src/library/screenshotManager.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 6dc66683..eab968f5 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -111,7 +111,8 @@ export default function MintPopup({screenshotManager}) { } }); const headPosition = localVector; - const cameraFov = 1.0; + const female = templateInfo.name === "Drophunter"; + const cameraFov = female ? 0.78 : 0.85; screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; const screenshot = screenshotManager.saveAsImage(imageName); diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 5e772ae3..635a3183 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -10,8 +10,8 @@ export class ScreenshotManager { }); this.renderer.outputEncoding = THREE.sRGBEncoding - const width = 500; - const height = 750; + const width = 512; + const height = 512; this.renderer.setSize(width, height); From 18b4c362affcd7ab8cc7472de34089f1cf5777d8 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 11:49:16 -0500 Subject: [PATCH 18/79] add screenshot background --- src/library/screenshotManager.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 635a3183..3d36d7b7 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -3,6 +3,10 @@ import { Buffer } from "buffer"; const localVector = new THREE.Vector3(); +const textureLoader = new THREE.TextureLoader(); +const backgroundTexture = textureLoader.load(`/assets/backgrounds/main-background2.jpg`); +backgroundTexture.wrapS = backgroundTexture.wrapT = THREE.RepeatWrapping; + export class ScreenshotManager { constructor() { this.renderer = new THREE.WebGLRenderer({ @@ -37,6 +41,7 @@ export class ScreenshotManager { saveAsImage(imageName) { let imgData; try { + this.scene.background = backgroundTexture; this.renderer.render(this.scene, this.camera); const strDownloadMime = "image/octet-stream"; const strMime = "image/png"; @@ -49,6 +54,7 @@ export class ScreenshotManager { const blob = new Blob([base64Data], { type: "image/jpeg" }); this.saveFile(imgData.replace(strMime, strDownloadMime), imageName); + this.scene.background = null; return blob; } catch (e) { console.log(e); From 64115bffa7a447d7ddee71afdbfcd2f82e4f0297 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 13:09:57 -0500 Subject: [PATCH 19/79] add antialias to screenshot renderer --- src/library/screenshotManager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 3d36d7b7..720ea81b 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -10,7 +10,8 @@ backgroundTexture.wrapS = backgroundTexture.wrapT = THREE.RepeatWrapping; export class ScreenshotManager { constructor() { this.renderer = new THREE.WebGLRenderer({ - preserveDrawingBuffer: true + preserveDrawingBuffer: true, + antialias: true }); this.renderer.outputEncoding = THREE.sRGBEncoding From 46423a9a14e736aed905413821adb65b80ae9d91 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 16:10:32 -0500 Subject: [PATCH 20/79] prevent eyes closing when taking the screen shot --- src/App.jsx | 2 +- src/components/Mint.jsx | 5 +++-- src/library/blinkManager.js | 20 ++++++++++++++++++-- src/library/screenshotManager.js | 2 +- src/pages/Mint.jsx | 4 ++-- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 565a5461..06bc5676 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -299,7 +299,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index eab968f5..b69a6d48 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -19,7 +19,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotManager}) { +export default function MintPopup({screenshotManager, blinkManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -101,6 +101,7 @@ export default function MintPopup({screenshotManager}) { const pass = true; if(pass) { + blinkManager.enableScreenshot(); setMintStatus("Uploading...") let imageHash, glbHash; @@ -116,7 +117,7 @@ export default function MintPopup({screenshotManager}) { screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; const screenshot = screenshotManager.saveAsImage(imageName); - + blinkManager.disableScreenshot(); // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) if (screenshot) { diff --git a/src/library/blinkManager.js b/src/library/blinkManager.js index 1650e8ae..ae744e6d 100644 --- a/src/library/blinkManager.js +++ b/src/library/blinkManager.js @@ -1,6 +1,7 @@ import { VRMExpressionPresetName } from "@pixiv/three-vrm"; import { Clock } from "three"; +const SCREENSHOT_EYES_OPEN_THRESHOLD = 2; export class BlinkManager { constructor(closeTime = 0.5, openTime = 0.5, continuity = 1, randomness = 5) { @@ -17,6 +18,8 @@ export class BlinkManager { this._eyeOpen = 1 this._blinkCounter = 0; + this.isTakingScreenShot = false; + this.update() } @@ -24,8 +27,21 @@ export class BlinkManager { this.vrmBlinkers.push(vrm) } + enableScreenshot() { + this.isTakingScreenShot = true; + this._eyeOpen = SCREENSHOT_EYES_OPEN_THRESHOLD; + this._updateBlinkers(); + } + + disableScreenshot() { + this.isTakingScreenShot = false; + } + update(){ setInterval(() => { + if (this.isTakingScreenShot) { + return; + } const deltaTime = this.clock.getDelta() switch (this.mode){ @@ -33,7 +49,7 @@ export class BlinkManager { if ( this._eyeOpen > 0) this._eyeOpen -= deltaTime / this.closeTime; else{ - this._eyeOpen =0 + this._eyeOpen = 0 this.mode = 'open' } this._updateBlinkers(); @@ -42,7 +58,7 @@ export class BlinkManager { if ( this._eyeOpen < 1) this._eyeOpen += deltaTime / this.openTime; else{ - this._eyeOpen =1 + this._eyeOpen = 1 this.mode = 'ready' } this._updateBlinkers(); diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 720ea81b..db0503f9 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -36,7 +36,7 @@ export class ScreenshotManager { this.cameraDir.normalize(); this.camera.position.x -= this.cameraDir.x * playerCameraDistance; this.camera.position.z -= this.cameraDir.z * playerCameraDistance; - + } saveAsImage(imageName) { diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index fb53258a..072d24c7 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -5,7 +5,7 @@ import { ViewMode, ViewContext } from "../context/ViewContext" import Mint from "../components/Mint" import CustomButton from "../components/custom-button" -function MintComponent({screenshotManager}) { +function MintComponent({screenshotManager, blinkManager}) { const { setViewMode } = React.useContext(ViewContext) // const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); @@ -25,7 +25,7 @@ function MintComponent({screenshotManager}) {
- +
From 698f426b5e77442b7d3328dddcc4ca99b7d388a8 Mon Sep 17 00:00:00 2001 From: soulofmischief <30357883+soulofmischief@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:24:35 -0800 Subject: [PATCH 21/79] Set screenshot size to 4096x4096 --- src/library/screenshotManager.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index db0503f9..76c95e6e 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -1,6 +1,8 @@ import * as THREE from "three" import { Buffer } from "buffer"; +const screenshotSize = 4096; + const localVector = new THREE.Vector3(); const textureLoader = new THREE.TextureLoader(); @@ -13,19 +15,10 @@ export class ScreenshotManager { preserveDrawingBuffer: true, antialias: true }); - this.renderer.outputEncoding = THREE.sRGBEncoding - - const width = 512; - const height = 512; + this.renderer.outputEncoding = THREE.sRGBEncoding; + this.renderer.setSize(screenshotSize, screenshotSize); - this.renderer.setSize(width, height); - - this.camera = new THREE.PerspectiveCamera( - 30, - width / height, - 0.1, - 1000, - ) + this.camera = new THREE.PerspectiveCamera( 30, 1, 0.1, 1000 ); } setCamera(headPosition, playerCameraDistance) { @@ -36,7 +29,7 @@ export class ScreenshotManager { this.cameraDir.normalize(); this.camera.position.x -= this.cameraDir.x * playerCameraDistance; this.camera.position.z -= this.cameraDir.z * playerCameraDistance; - + } saveAsImage(imageName) { From 916d909894bd739771979217255c73c8b0c53917 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 16:52:19 -0500 Subject: [PATCH 22/79] missing uri --- src/library/screenshotManager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index db0503f9..173a02c5 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -73,7 +73,8 @@ export class ScreenshotManager { link.click(); document.body.removeChild(link); //remove the link when done } else { - location.replace(uri); + const win = window.open(strData, "_blank"); + win.document.write("" + filename + ""); } } From a86e9c7190ef23f5d0945b742d30f430b2d88a9f Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 18:09:36 -0500 Subject: [PATCH 23/79] let all screenshot have the same frame of the animation --- src/App.jsx | 2 +- src/components/Mint.jsx | 5 ++++- src/library/animationManager.js | 21 +++++++++++++++++++++ src/pages/Mint.jsx | 4 ++-- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 06bc5676..3aa8e597 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -299,7 +299,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index b69a6d48..e0ed6bb9 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -19,7 +19,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotManager, blinkManager}) { +export default function MintPopup({screenshotManager, blinkManager, animationManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -101,6 +101,7 @@ export default function MintPopup({screenshotManager, blinkManager}) { const pass = true; if(pass) { + animationManager.enableScreenshot(); blinkManager.enableScreenshot(); setMintStatus("Uploading...") let imageHash, glbHash; @@ -116,8 +117,10 @@ export default function MintPopup({screenshotManager, blinkManager}) { const cameraFov = female ? 0.78 : 0.85; screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; + const screenshot = screenshotManager.saveAsImage(imageName); blinkManager.disableScreenshot(); + animationManager.disableScreenshot(); // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) if (screenshot) { diff --git a/src/library/animationManager.js b/src/library/animationManager.js index 9db19464..67474528 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -48,6 +48,15 @@ class AnimationControl { this.actions[curIdx].play(); } + enableScreenshot() { + this.mixer.setTime(0); + this.to.paused = true; + } + + disableScreenshot() { + this.to.paused = false; + } + dispose(){ this.animationManager.disposeAnimation(this); //console.log("todo dispose animation control") @@ -93,6 +102,18 @@ export class AnimationManager{ } + enableScreenshot() { + this.animationControls.forEach(control => { + control.enableScreenshot() + }); + } + + disableScreenshot() { + this.animationControls.forEach(control => { + control.disableScreenshot() + }); + } + offsetHips(){ this.animations.forEach(anim => { for (let i =0; i < anim.tracks.length; i++){ diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 072d24c7..500535d1 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -5,7 +5,7 @@ import { ViewMode, ViewContext } from "../context/ViewContext" import Mint from "../components/Mint" import CustomButton from "../components/custom-button" -function MintComponent({screenshotManager, blinkManager}) { +function MintComponent({screenshotManager, blinkManager, animationManager}) { const { setViewMode } = React.useContext(ViewContext) // const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); @@ -25,7 +25,7 @@ function MintComponent({screenshotManager, blinkManager}) {
- +
From 7b6fe35d80fc4fae005571b942510859a09bfbf5 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 18:36:12 -0500 Subject: [PATCH 24/79] rename --- src/library/animationManager.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/library/animationManager.js b/src/library/animationManager.js index 67474528..f563f277 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -48,12 +48,12 @@ class AnimationControl { this.actions[curIdx].play(); } - enableScreenshot() { + reset() { this.mixer.setTime(0); this.to.paused = true; } - disableScreenshot() { + resume() { this.to.paused = false; } @@ -104,13 +104,13 @@ export class AnimationManager{ enableScreenshot() { this.animationControls.forEach(control => { - control.enableScreenshot() + control.reset() }); } disableScreenshot() { this.animationControls.forEach(control => { - control.disableScreenshot() + control.resume() }); } From 044d89a14a7a9976986ee0243fc3e8fad66408db Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 17 Feb 2023 08:49:04 -0600 Subject: [PATCH 25/79] fix merge commit issues --- src/App.jsx | 1 - src/pages/Mint.jsx | 21 --------------------- 2 files changed, 22 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 822669e4..4c1f8d5c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -24,7 +24,6 @@ import BioPage from "./pages/Bio" import Create from "./pages/Create" import Landing from "./pages/Landing" import Appearance from "./pages/Appearance" -import Mint from "./pages/Mint" // dynamically import the manifest const assetImportPath = import.meta.env.VITE_ASSET_PATH + "/manifest.json" diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index cc33fff9..172dc084 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -1,13 +1,6 @@ import React from "react" import styles from "./Mint.module.scss" import { ViewMode, ViewContext } from "../context/ViewContext" - -///<<<<<<< tcm-screenshot -///import Mint from "../components/Mint" -///======= -// import Mint from "../components/Mint" -// import ResizableDiv from "../components/Resizable" -///>>>>>>> full-mint-support import CustomButton from "../components/custom-button" function MintComponent({screenshotManager, blinkManager, animationManager}) { @@ -34,20 +27,9 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { return (
Mint Your Character
-///<<<<<<< tcm-screenshot - ///
- ///
- ///
- ///
- - /// -///======= - {/* */} -
-
-
- (Genesis pass holders only) -///>>>>>>> full-mint-support
From f0e5593af04815a5f96599b5c08f65ef45545834 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 17 Feb 2023 09:08:41 -0600 Subject: [PATCH 26/79] create screenshot function --- src/App.jsx | 30 ++++++++++++++++++++++++------ src/components/ExportMenu.jsx | 3 ++- src/pages/Save.jsx | 4 ++-- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 4c1f8d5c..7208743e 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -177,6 +177,7 @@ export default function App() { moveCamera, setManifest, manifest, + model, } = useContext(SceneContext) const { viewMode } = useContext(ViewContext) @@ -268,6 +269,27 @@ export default function App() { }) } + const takeFaceScreenshot = () => { + blinkManager.enableScreenshot(); + model.traverse(o => { + if (o.isSkinnedMesh) { + const headBone = o.skeleton.bones.filter(bone => bone.name === 'head')[0]; + headBone.getWorldPosition(localVector3); + } + }); + const headPosition = localVector3; + const female = templateInfo.name === "Drophunter"; + const cameraFov = female ? 0.78 : 0.85; + screenshotManager.setCamera(headPosition, cameraFov); + let imageName = "AvatarImage_" + Date.now() + ".png"; + + const screenshot = screenshotManager.saveAsImage(imageName); + blinkManager.disableScreenshot(); + animationManager.disableScreenshot(); + + return screenshot; + } + // map current app mode to a page const pages = { [ViewMode.LANDING]: , @@ -285,12 +307,8 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , -///<<<<<<< tcm-screenshot - ///[ViewMode.MINT]: , -///======= - [ViewMode.MINT]: , -///>>>>>>> full-mint-support - [ViewMode.SAVE]: , + [ViewMode.MINT]: , + [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/ExportMenu.jsx b/src/components/ExportMenu.jsx index 8d97e2fa..889f4adc 100644 --- a/src/components/ExportMenu.jsx +++ b/src/components/ExportMenu.jsx @@ -20,7 +20,7 @@ import styles from "./ExportMenu.module.css" const defaultName = "Anon" -export const ExportMenu = () => { +export const ExportMenu = ({takeFaceScreenshot}) => { // const type = "_Gen1" // class type const [showDownloadOptions, setShowDownloadOptions] = useState(false) @@ -260,6 +260,7 @@ export const ExportMenu = () => { size={14} className={styles.button} onClick={() => { + takeFaceScreenshot(); downloadVRM(model, avatar, name, 4096, true) //download(model, name, "vrm") }} diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index 19d01ecb..9aac58f9 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -5,7 +5,7 @@ import { ExportMenu } from '../components/ExportMenu'; import { ViewMode, ViewContext } from '../context/ViewContext'; import CustomButton from '../components/custom-button'; -function Save() { +function Save({takeFaceScreenshot}) { const { setViewMode } = React.useContext(ViewContext); const back = () => { @@ -36,7 +36,7 @@ function Save() {
- +
{/* Date: Fri, 17 Feb 2023 10:27:25 -0600 Subject: [PATCH 27/79] update functions in screnshot manager --- src/components/ExportMenu.jsx | 4 ++-- src/library/VRMExporter.js | 2 +- src/library/VRMExporterv0.js | 11 +++++++---- src/library/download-utils.js | 16 ++++++++-------- src/library/screenshotManager.js | 30 ++++++++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/components/ExportMenu.jsx b/src/components/ExportMenu.jsx index 889f4adc..75dba4f8 100644 --- a/src/components/ExportMenu.jsx +++ b/src/components/ExportMenu.jsx @@ -260,8 +260,8 @@ export const ExportMenu = ({takeFaceScreenshot}) => { size={14} className={styles.button} onClick={() => { - takeFaceScreenshot(); - downloadVRM(model, avatar, name, 4096, true) + const screenshot = takeFaceScreenshot(); + downloadVRM(model, avatar, name, screenshot, 4096, true) //download(model, name, "vrm") }} /> diff --git a/src/library/VRMExporter.js b/src/library/VRMExporter.js index 09e8b635..120e91dd 100644 --- a/src/library/VRMExporter.js +++ b/src/library/VRMExporter.js @@ -62,7 +62,7 @@ const SPRINGBONE_COLLIDER_NAME = "vrmColliderSphere"; // const GLTF_VERSION = 2; // const HEADER_SIZE = 12; export default class VRMExporter { - parse(vrm, avatar, onDone) { + parse(vrm, avatar, screenshot, onDone) { const humanoid = vrm.humanoid; const vrmMeta = vrm.meta; const materials = vrm.materials; diff --git a/src/library/VRMExporterv0.js b/src/library/VRMExporterv0.js index f46baea8..6f4ae37e 100644 --- a/src/library/VRMExporterv0.js +++ b/src/library/VRMExporterv0.js @@ -97,7 +97,7 @@ function getVRM0BoneName(name){ return name; } export default class VRMExporterv0 { - parse(vrm, avatar, onDone) { + parse(vrm, avatar, screenshot, onDone) { const vrmMeta = convertMetaToVRM0(vrm.meta); const humanoid = convertHumanoidToVRM0(vrm.humanoid); @@ -137,9 +137,12 @@ export default class VRMExporterv0 { .map((material) => material); const uniqueMaterialNames = uniqueMaterials.map((material) => material.name); - const icon = vrmMeta.texture - ? { name: "icon", imageBitmap: vrmMeta.texture.image } - : null; // TODO: ない場合もある + console.log(vrmMeta.texture) + console.log(screenshot) + const icon = { name: "icon", imageBitmap: screenshot } + // const icon = vrmMeta.texture + // ? { name: "icon", imageBitmap: vrmMeta.texture.image } + // : null; // TODO: ない場合もある const mainImages = uniqueMaterials .filter((material) => material.map) .map((material) => { diff --git a/src/library/download-utils.js b/src/library/download-utils.js index a2b3c54a..86af7910 100644 --- a/src/library/download-utils.js +++ b/src/library/download-utils.js @@ -76,9 +76,9 @@ export async function getGLBBlobData(avatarToDownload, atlasSize = 4096, optimi return new Blob([glb], { type: 'model/gltf-binary' }); } -export async function getVRMBlobData(avatarToDownload, avatar, atlasSize = 4096, isVrm0 = false){ +export async function getVRMBlobData(avatarToDownload, avatar, screenshot = null, atlasSize = 4096, isVrm0 = false){ const model = await getOptimizedGLB(avatarToDownload, atlasSize, isVrm0) - const vrm = await parseVRM(model, avatar, isVrm0); + const vrm = await parseVRM(model, avatar, screenshot, isVrm0); // save it as glb now return new Blob([vrm], { type: 'model/gltf-binary' }); } @@ -94,17 +94,17 @@ async function getGLBData(avatarToDownload, atlasSize = 4096, optimized = true) return parseGLB(model); } } -async function getVRMData(avatarToDownload, avatar, atlasSize = 4096, isVrm0 = false){ +async function getVRMData(avatarToDownload, avatar, screenshot = null, atlasSize = 4096, isVrm0 = false){ const vrmModel = await getOptimizedGLB(avatarToDownload, atlasSize, isVrm0); - return parseVRM(vrmModel,avatar, isVrm0) + return parseVRM(vrmModel,avatar,screenshot, isVrm0) } -export async function downloadVRM(avatarToDownload, avatar, fileName = "", atlasSize = 4096, isVrm0 = false){ +export async function downloadVRM(avatarToDownload, avatar, fileName = "", screenshot = null, atlasSize = 4096, isVrm0 = false){ const downloadFileName = `${ fileName && fileName !== "" ? fileName : "AvatarCreatorModel" }` - getVRMData(avatarToDownload, avatar, atlasSize, isVrm0).then((vrm)=>{ + getVRMData(avatarToDownload, avatar, screenshot, atlasSize, isVrm0).then((vrm)=>{ saveArrayBuffer(vrm, `${downloadFileName}.vrm`) }) } @@ -150,7 +150,7 @@ function parseGLB (glbModel){ }) } -function parseVRM (glbModel, avatar, isVrm0 = false){ +function parseVRM (glbModel, avatar, screenshot = null, isVrm0 = false){ return new Promise((resolve) => { const exporter = isVrm0 ? new VRMExporterv0() : new VRMExporter() const vrmData = { @@ -181,7 +181,7 @@ function parseVRM (glbModel, avatar, isVrm0 = false){ skinnedMesh.skeleton.calculateInverses(); skinnedMesh.skeleton.computeBoneTexture(); skinnedMesh.skeleton.update(); - exporter.parse(vrmData, glbModel, (vrm) => { + exporter.parse(vrmData, glbModel,screenshot, (vrm) => { resolve(vrm) }) }) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 1dc26368..cc55a0b1 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -57,6 +57,36 @@ export class ScreenshotManager { } + _createImage(){ + try { + this.scene.background = backgroundTexture; + this.renderer.render(this.scene, this.camera); + const strMime = "image/png"; + let imgData = this.renderer.domElement.toDataURL(strMime); + return imgData + } catch (e) { + console.log(e); + return null; + } + } + saveScreenshot(){ + const imgData = this._createImage() + this.saveFile(imgData.replace(strMime, strDownloadMime), imageName); + } + + getScreenhotImage(){ + return this._createImage(); + } + getScreenshotBlob(){ + const imgData = this._createImage() + const base64Data = Buffer.from( + imgData.replace(/^data:image\/\w+;base64,/, ""), + "base64" + ); + const blob = new Blob([base64Data], { type: "image/jpeg" }); + return blob; + } + saveFile (strData, filename) { const link = document.createElement('a'); if (typeof link.download === 'string') { From 158be65324c5c0bf84bb4f2ba57beb0f09c2e808 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 17 Feb 2023 10:46:02 -0600 Subject: [PATCH 28/79] get screenshot name and change function --- src/App.jsx | 7 ++++--- src/components/ExportMenu.jsx | 4 ++-- src/library/screenshotManager.js | 16 ++++++++++++++-- src/pages/Save.jsx | 4 ++-- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 7208743e..7482ef13 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -269,7 +269,7 @@ export default function App() { }) } - const takeFaceScreenshot = () => { + const getFaceScreenshot = () => { blinkManager.enableScreenshot(); model.traverse(o => { if (o.isSkinnedMesh) { @@ -283,7 +283,8 @@ export default function App() { screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; - const screenshot = screenshotManager.saveAsImage(imageName); + //const screenshot = screenshotManager.saveAsImage(imageName); + const screenshot = screenshotManager.getScreenhotImage(); blinkManager.disableScreenshot(); animationManager.disableScreenshot(); @@ -308,7 +309,7 @@ export default function App() { [ViewMode.CREATE]: , [ViewMode.LOAD]: , [ViewMode.MINT]: , - [ViewMode.SAVE]: , + [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/ExportMenu.jsx b/src/components/ExportMenu.jsx index 75dba4f8..83ef4988 100644 --- a/src/components/ExportMenu.jsx +++ b/src/components/ExportMenu.jsx @@ -20,7 +20,7 @@ import styles from "./ExportMenu.module.css" const defaultName = "Anon" -export const ExportMenu = ({takeFaceScreenshot}) => { +export const ExportMenu = ({getFaceScreenshot}) => { // const type = "_Gen1" // class type const [showDownloadOptions, setShowDownloadOptions] = useState(false) @@ -260,7 +260,7 @@ export const ExportMenu = ({takeFaceScreenshot}) => { size={14} className={styles.button} onClick={() => { - const screenshot = takeFaceScreenshot(); + const screenshot = getFaceScreenshot(); downloadVRM(model, avatar, name, screenshot, 4096, true) //download(model, name, "vrm") }} diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index cc55a0b1..65ad05c0 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -69,13 +69,25 @@ export class ScreenshotManager { return null; } } - saveScreenshot(){ + saveScreenshot(imageName){ const imgData = this._createImage() + const strDownloadMime = "image/octet-stream"; + const strMime = "image/png"; this.saveFile(imgData.replace(strMime, strDownloadMime), imageName); } getScreenhotImage(){ - return this._createImage(); + const imgData = this._createImage(); + + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + canvas.width = imgData.width; + canvas.height = imgData.height; + ctx.putImageData(imgData, 0, 0); + + var image = new Image(); + image.src = canvas.toDataURL(); + return image; } getScreenshotBlob(){ const imgData = this._createImage() diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index 9aac58f9..b402d6b5 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -5,7 +5,7 @@ import { ExportMenu } from '../components/ExportMenu'; import { ViewMode, ViewContext } from '../context/ViewContext'; import CustomButton from '../components/custom-button'; -function Save({takeFaceScreenshot}) { +function Save({getFaceScreenshot}) { const { setViewMode } = React.useContext(ViewContext); const back = () => { @@ -36,7 +36,7 @@ function Save({takeFaceScreenshot}) {
- +
{/* Date: Fri, 17 Feb 2023 10:46:31 -0600 Subject: [PATCH 29/79] remove next button in view page --- src/pages/View.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/View.jsx b/src/pages/View.jsx index aa8ff1c5..72f2bf06 100644 --- a/src/pages/View.jsx +++ b/src/pages/View.jsx @@ -44,13 +44,13 @@ function View({templateInfo}) { className={styles.buttonLeft} onClick={back} /> - + /> */}
) From 3fffadfb96cabf1340226fd619cc8466b623f8b4 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 17 Feb 2023 12:33:54 -0600 Subject: [PATCH 30/79] save to vrm0 --- src/App.jsx | 2 +- src/library/VRMExporterv0.js | 17 ++++++++-------- src/library/screenshotManager.js | 35 ++++++++++++++++---------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 7482ef13..433fbcc8 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -284,7 +284,7 @@ export default function App() { let imageName = "AvatarImage_" + Date.now() + ".png"; //const screenshot = screenshotManager.saveAsImage(imageName); - const screenshot = screenshotManager.getScreenhotImage(); + const screenshot = screenshotManager.getScreenshotTexture(256,256); blinkManager.disableScreenshot(); animationManager.disableScreenshot(); diff --git a/src/library/VRMExporterv0.js b/src/library/VRMExporterv0.js index 6f4ae37e..cf565203 100644 --- a/src/library/VRMExporterv0.js +++ b/src/library/VRMExporterv0.js @@ -137,12 +137,11 @@ export default class VRMExporterv0 { .map((material) => material); const uniqueMaterialNames = uniqueMaterials.map((material) => material.name); - console.log(vrmMeta.texture) - console.log(screenshot) - const icon = { name: "icon", imageBitmap: screenshot } - // const icon = vrmMeta.texture - // ? { name: "icon", imageBitmap: vrmMeta.texture.image } - // : null; // TODO: ない場合もある + + const icon = screenshot + ? { name: "icon", imageBitmap: screenshot.image } + : null; // TODO: ない場合もある + const mainImages = uniqueMaterials .filter((material) => material.map) .map((material) => { @@ -157,10 +156,7 @@ export default class VRMExporterv0 { throw new Error(material.userData.shadeTexture + " map is null"); return { name: material.name + "_shade", imageBitmap: material.userData.shadeTexture.image }; }); // TODO: 画像がないMaterialもある\ - - - const images = mainImages.concat(shadeImages); const outputImages = toOutputImages(images, icon); @@ -193,6 +189,7 @@ export default class VRMExporterv0 { const meshes = avatar.children.filter((child) => child.type === VRMObjectType.Group || child.type === VRMObjectType.SkinnedMesh); const meshDatas = []; + meshes.forEach((object) => { const mesh = (object.type === VRMObjectType.Group ? object.children[0] @@ -420,6 +417,8 @@ export default class VRMExporterv0 { //const outputVrmMeta = ToOutputVRMMeta(vrmMeta, icon, outputImages); const outputVrmMeta = vrmMeta; + outputVrmMeta.texture = icon ? outputImages.length - 1 : undefined; + //const outputSecondaryAnimation = toOutputSecondaryAnimation(springBone, nodeNames); const bufferViews = []; bufferViews.push(...images.map((image) => ({ diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 65ad05c0..92660dd8 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -57,40 +57,41 @@ export class ScreenshotManager { } - _createImage(){ + _createImage(width, height){ + this.renderer.setSize(width, height); try { this.scene.background = backgroundTexture; this.renderer.render(this.scene, this.camera); const strMime = "image/png"; let imgData = this.renderer.domElement.toDataURL(strMime); + this.scene.background = null; return imgData } catch (e) { console.log(e); return null; } } - saveScreenshot(imageName){ - const imgData = this._createImage() + saveScreenshot(imageName,width, height){ + const imgData = this._createImage(width, height) const strDownloadMime = "image/octet-stream"; const strMime = "image/png"; this.saveFile(imgData.replace(strMime, strDownloadMime), imageName); } - getScreenhotImage(){ - const imgData = this._createImage(); - - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - canvas.width = imgData.width; - canvas.height = imgData.height; - ctx.putImageData(imgData, 0, 0); - - var image = new Image(); - image.src = canvas.toDataURL(); - return image; + getScreenshotImage(width, height){ + const imgData = this._createImage(width, height); + const img = new Image(); + img.src = imgData; + return img; + } + getScreenshotTexture(width, height){ + const img = this.getScreenshotImage(width,height) + const texture = new THREE.Texture(img); + texture.needsUpdate = true; + return texture; } - getScreenshotBlob(){ - const imgData = this._createImage() + getScreenshotBlob(width, height){ + const imgData = this._createImage(width, height) const base64Data = Buffer.from( imgData.replace(/^data:image\/\w+;base64,/, ""), "base64" From 8a4f808e6d242722e0413cbc17d723ec13f366b0 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:34:47 -0600 Subject: [PATCH 31/79] confix --- src/App.jsx | 12 +- src/components/Mint.jsx | 173 +++++++++++++++------------- src/components/Resizable.jsx | 158 ------------------------- src/components/Resizable.module.css | 62 ---------- src/library/screenshotManager.js | 77 +++++++++++++ src/pages/Mint.jsx | 7 +- src/pages/View.jsx | 10 ++ 7 files changed, 191 insertions(+), 308 deletions(-) delete mode 100644 src/components/Resizable.jsx delete mode 100644 src/components/Resizable.module.css create mode 100644 src/library/screenshotManager.js diff --git a/src/App.jsx b/src/App.jsx index 88438cad..a0547a44 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -12,6 +12,7 @@ import { BlinkManager } from "./library/blinkManager" import { LookAtManager } from "./library/lookatManager" import { EffectManager } from "./library/effectManager" import { AnimationManager } from "./library/animationManager" +import { ScreenshotManager } from "./library/screenshotManager" import Scene from "./components/Scene" import Background from "./components/Background" @@ -24,6 +25,8 @@ import Create from "./pages/Create" import Landing from "./pages/Landing" import Appearance from "./pages/Appearance" import LanguageSwitch from "./components/LanguageSwitch" +import Mint from "./pages/Mint" + // dynamically import the manifest const assetImportPath = import.meta.env.VITE_ASSET_PATH + "/manifest.json" @@ -109,6 +112,7 @@ async function fetchAll() { const blinkManager = new BlinkManager(0.1, 0.1, 0.5, 5) const lookatManager = new LookAtManager(80, "editor-scene") const effectManager = new EffectManager() + const screenshotManager = new ScreenshotManager() return { initialManifest, @@ -117,6 +121,7 @@ async function fetchAll() { blinkManager, lookatManager, effectManager, + screenshotManager, } } @@ -158,6 +163,7 @@ export default function App() { blinkManager, lookatManager, effectManager, + screenshotManager, } = resource.read() const [hideUi, setHideUi] = useState(false) @@ -180,6 +186,8 @@ export default function App() { effectManager.camera = camera effectManager.scene = scene + screenshotManager.scene = scene + const updateCameraPosition = () => { if (!effectManager.camera) return @@ -239,7 +247,7 @@ export default function App() { if (controls) { if ( - [ViewMode.APPEARANCE, ViewMode.SAVE, ViewMode.MINT].includes(viewMode) + [ViewMode.APPEARANCE, ViewMode.SAVE].includes(viewMode) ) { controls.enabled = true } else { @@ -280,7 +288,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - // [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 7f494fc0..188c3ec1 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -15,7 +15,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotPosition}) { +export default function MintPopup({screenshotPosition, screenshotManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -90,94 +90,103 @@ export default function MintPopup({screenshotPosition}) { } const mintAsset = async (avatar) => { - let walletAddress = await connectWallet() + console.log(templateInfo) + // let walletAddress = await connectWallet() - const pass = await checkOT(walletAddress); + // const pass = await checkOT(walletAddress); + const pass = true; if(pass) { setMintStatus("Uploading...") let imageHash, glbHash; - const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - if (screenshot) { - let imageName = "AvatarImage_" + Date.now() + ".png"; - imageHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const img_hash = await saveFileToPinata( - screenshot, - imageName - ).catch((reason) => { - console.error(i, "---", reason) - }) - return img_hash - } catch(err) { - console.warn(err); - } - } - throw new Error('failed to upload screenshot'); - setMintStatus("Couldn't save screenshot to pinata") - })(); - } else { - throw new Error("Unable to get screenshot") - } + + const headPosition = templateInfo.traits[0].cameraTarget.height; + const cameraFov = 1.0; + screenshotManager.setCamera(headPosition, cameraFov); + + screenshotManager.saveAsImage(); - const glb = await getGLBBlobData(model) - if (glb) { - let glbName = "AvatarGlb_" + Date.now() + ".glb"; - glbHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const glb_hash = await saveFileToPinata( - glb, - glbName - ).catch((reason) => { - console.error(i, "---", reason) - setMintStatus("Couldn't save glb to pinata") - }) - return glb_hash - } catch(err) { - console.warn(err); - } - } - throw new Error('failed to upload glb'); - setMintStatus("Couldn't save glb to pinata") - })(); - } else { - throw new Error("Unable to get glb") - } + // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) + // if (screenshot) { + // let imageName = "AvatarImage_" + Date.now() + ".png"; + // imageHash = await (async() => { + // for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + // try { + // const img_hash = await saveFileToPinata( + // screenshot, + // imageName + // ).catch((reason) => { + // console.error(i, "---", reason) + // }) + // return img_hash + // } catch(err) { + // console.warn(err); + // } + // } + // throw new Error('failed to upload screenshot'); + // setMintStatus("Couldn't save screenshot to pinata") + // })(); + // } else { + // throw new Error("Unable to get screenshot") + // } - const attributes = getAvatarTraits() - const metadata = { - name: "Avatars", - description: "Character Studio Avatars.", - image: `ipfs://${imageHash.IpfsHash}`, - animation_url: `ipfs://${glbHash.IpfsHash}`, - attributes: attributes - } - const str = JSON.stringify(metadata) - const metaDataHash = await saveFileToPinata( - new Blob([str]), - "AvatarMetadata_" + Date.now() + ".json", - ) - const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` + // const glb = await getGLBBlobData(model) + // if (glb) { + // let glbName = "AvatarGlb_" + Date.now() + ".glb"; + // glbHash = await (async() => { + // for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + // try { + // const glb_hash = await saveFileToPinata( + // glb, + // glbName + // ).catch((reason) => { + // console.error(i, "---", reason) + // setMintStatus("Couldn't save glb to pinata") + // }) + // return glb_hash + // } catch(err) { + // console.warn(err); + // } + // } + // throw new Error('failed to upload glb'); + // setMintStatus("Couldn't save glb to pinata") + // })(); + // } else { + // throw new Error("Unable to get glb") + // } - setMintStatus("Minting...") - const signer = new ethers.providers.Web3Provider( - window.ethereum, - ).getSigner() - const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) - try { - const options = { - value: tokenPrice, - from: walletAddress - } - const tx = await contract.mintToken(1, metadataIpfs, options) - let res = await tx.wait() - if (res.transactionHash) { - setMintStatus("Mint success!") - } - } catch (err) { - setMintStatus("Public Mint failed! Please check your wallet.") - } + // const attributes = getAvatarTraits() + // const metadata = { + // name: "Avatars", + // description: "Character Studio Avatars.", + // image: `ipfs://${imageHash.IpfsHash}`, + // animation_url: `ipfs://${glbHash.IpfsHash}`, + // attributes: attributes + // } + // const str = JSON.stringify(metadata) + // const metaDataHash = await saveFileToPinata( + // new Blob([str]), + // "AvatarMetadata_" + Date.now() + ".json", + // ) + // const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` + + // setMintStatus("Minting...") + // const signer = new ethers.providers.Web3Provider( + // window.ethereum, + // ).getSigner() + // const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) + // try { + // const options = { + // value: tokenPrice, + // from: walletAddress + // } + // const tx = await contract.mintToken(1, metadataIpfs, options) + // let res = await tx.wait() + // if (res.transactionHash) { + // setMintStatus("Mint success!") + // } + // } catch (err) { + // setMintStatus("Public Mint failed! Please check your wallet.") + // } } else { return; } diff --git a/src/components/Resizable.jsx b/src/components/Resizable.jsx deleted file mode 100644 index 08ad41c3..00000000 --- a/src/components/Resizable.jsx +++ /dev/null @@ -1,158 +0,0 @@ -import React, { useState } from 'react'; -import styles from "./Resizable.module.css" - -const ResizableDiv = ({setScreenshotPosition, screenshotPosition}) => { - - const [initialPos, setInitialPos] = useState(null); - const [initialSize, setInitialSize] = useState(null); - - const [moving, setMoving] = useState(false) - const [scaling, setScaling] = useState(false) - - - const windowResize = () => { - updateMask() - } - - - - React.useEffect (() => { - let resizable = document.getElementById('screenshots'); - let draggable = document.getElementById('Screenshot-block'); - - resizable.style.width = `${screenshotPosition.width}px`; - resizable.style.height = `${screenshotPosition.height}px`; - - draggable.style.paddingTop = `${screenshotPosition.y+20}px` - draggable.style.paddingLeft = `${screenshotPosition.x}px` - - - updateMask() - window.addEventListener('resize', windowResize); - return () => { - window.removeEventListener('resize', windowResize) - } - },[]) - - - - const handleMouseMove = (e) => { - //console.log(moving) - if (moving){ - let draggable = document.getElementById('Screenshot-block'); - let resizable = document.getElementById('screenshots'); - - const posX = (e.clientX - resizable.offsetWidth/2)// + initialPos.x - const posY = (e.clientY - resizable.offsetHeight/2)// + initialPos.y - - draggable.style.paddingTop = `${posY+20}px` - - draggable.style.paddingLeft = `${posX}px` - - //moveMask(posX, posY, resizable.offsetWidth, resizable.offsetHeight); - updateMask(); - setScreenshotPosition({...screenshotPosition, ...{x:posX, y:posY}}); - - } - - if (scaling){ - let resizable = document.getElementById('screenshots'); - - const newWidth = parseInt(initialSize.width) + parseInt(e.clientX - initialPos.x) - const newHeight = parseInt(initialSize.height) + parseInt(e.clientY - initialPos.y) - - const sameRatio = newWidth >= newHeight ? newWidth : newHeight - if (newWidth > 50 && newHeight > 50){ - resizable.style.width = `${sameRatio}px`; - resizable.style.height = `${sameRatio}px`; - - //resizeMask() - updateMask(); - - setScreenshotPosition({...screenshotPosition,...{width:sameRatio, height:sameRatio}}); - } - } - } - const updateMask = () =>{ - const fscreen = document.getElementById('fscreen-div'); - - const maskLeft = document.getElementById('maskLeft'); - const maskTop = document.getElementById('maskTop'); - const maskRight = document.getElementById('maskRight'); - const maskBottom = document.getElementById('maskBottom'); - - const clientHeight = fscreen.clientHeight; - const clientWidth = fscreen.clientWidth; - - maskLeft.style.width = `${screenshotPosition.x}px` - - maskTop.style.left = `${screenshotPosition.x}px` - maskTop.style.height = `${screenshotPosition.y}px` - maskTop.style.width = `${screenshotPosition.width}px` - - maskRight.style.width = `${clientWidth - screenshotPosition.x - screenshotPosition.width}px` - - maskBottom.style.left = `${screenshotPosition.x}px` - maskBottom.style.height = `${clientHeight - screenshotPosition.y - screenshotPosition.height}px` - maskBottom.style.width = `${screenshotPosition.width}px` - } - - const initialFrame = (e) => { - setMoving(true) - let draggable = document.getElementById('Screenshot-block'); - let resizable = document.getElementById('screenshots'); - - const leftPos = e.clientX - draggable.style.paddingLeft; - - draggable.style.paddingTop = e.clientY - resizable.offsetHeight/2; - - - setInitialPos({x:leftPos, y:e.clientY}); - - } - - const initial = (e) => { - setScaling(true) - let resizable = document.getElementById('screenshots'); - - setInitialPos({x:e.clientX, y:e.clientY}); - setInitialSize({width:resizable.offsetWidth, height:resizable.offsetHeight}); - - } - - const endInteraction = () => { - setScaling(false) - setMoving(false) - } - - return( -
handleMouseMove(ev)} - onMouseLeave = {endInteraction} - onMouseUp = {endInteraction} - onTouchEnd = {endInteraction} - onTouchCancel = {endInteraction}> -
-
-
-
- -
-
-
-
-
- ); - -} - -export default ResizableDiv; \ No newline at end of file diff --git a/src/components/Resizable.module.css b/src/components/Resizable.module.css deleted file mode 100644 index 4754b7cf..00000000 --- a/src/components/Resizable.module.css +++ /dev/null @@ -1,62 +0,0 @@ -.Block{ - display: flex; - align-items: flex-end; - position: absolute; - overflow: hidden; - -} -.Draggable{ - background: rgb(230, 230, 230); - cursor: pointer; - height: 20px; - width: 20px; -} -.FullScreen{ - display: flex; - overflow: hidden; - position: absolute; - width: 100%; - height: 100%; -} -.BlockScreen{ - position:relative; - width: 100%; - height: 100%; -} - -.leftBlock{ - animation: fadein 1s; - position:absolute; - background-color: rgba(0, 0, 0, 0.6); - height: 100%; -} -.rightBlock{ - animation: fadein 1s; - position:absolute; - right: 0; - background-color: rgba(0, 0, 0, 0.6); - height: 100%; -} -.topBlock{ - animation: fadein 1s; - position:absolute; - top: 0; - background-color: rgba(0, 0, 0, 0.6); - height: 25px; -} -.lowerBlock{ - animation: fadein 1s; - position:absolute; - bottom: 0; - background-color: rgba(0, 0, 0, 0.6); -} - -body { - animation: fadeInAnimation ease 3s; - animation-iteration-count: 1; - animation-fill-mode: forwards; -} -@keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} \ No newline at end of file diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js new file mode 100644 index 00000000..57a6d7de --- /dev/null +++ b/src/library/screenshotManager.js @@ -0,0 +1,77 @@ +import * as THREE from "three" + +const localVector = new THREE.Vector3(); + +export class ScreenshotManager { + constructor() { + this.frameRate = 1000 / 30; + + this.renderer = new THREE.WebGLRenderer({ + preserveDrawingBuffer: true + }); + + this.renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight); + this.renderTarget.texture.encoding = THREE.sRGBEncoding; + + this.renderer.setSize(window.innerWidth, window.innerHeight); + + this.camera = new THREE.PerspectiveCamera( + 30, + window.innerWidth / window.innerHeight, + 0.1, + 1000, + ) + // this.setUpCamera(); + this.update(); + } + + setCamera(height, playerCameraDistance) { + this.camera.position.y = height; + + localVector.set(0, 0, -1); + this.cameraDir = localVector.applyQuaternion(this.camera.quaternion); + this.cameraDir.normalize(); + this.camera.position.x = -this.cameraDir.x * playerCameraDistance; + this.camera.position.z = -this.cameraDir.z * playerCameraDistance; + + } + + saveAsImage() { + let imgData; + try { + this.renderer.render(this.scene, this.camera); + const strDownloadMime = "image/octet-stream"; + const strMime = "image/jpeg"; + imgData = this.renderer.domElement.toDataURL(strMime); + this.saveFile(imgData.replace(strMime, strDownloadMime), "test.jpg"); + } catch (e) { + console.log(e); + return; + } + + } + + saveFile (strData, filename) { + const link = document.createElement('a'); + if (typeof link.download === 'string') { + document.body.appendChild(link); //Firefox requires the link to be in the body + link.download = filename; + link.href = strData; + link.click(); + document.body.removeChild(link); //remove the link when done + } else { + location.replace(uri); + } + } + + update() { + setInterval(() => { + + // this.renderer.render(this.scene, this.camera); + + }, this.frameRate); + } + + + +} \ No newline at end of file diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index e8abe2fb..ba14ef95 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -3,13 +3,13 @@ import styles from "./Mint.module.css" import { ViewMode, ViewContext } from "../context/ViewContext" import Mint from "../components/Mint" -import ResizableDiv from "../components/Resizable" import CustomButton from "../components/custom-button" import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" -function MintComponent() { +function MintComponent({screenshotManager}) { + const { setViewMode } = React.useContext(ViewContext) const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); const { playSound } = React.useContext(SoundContext) @@ -28,13 +28,12 @@ function MintComponent() { return (
Mint Your Character
-
- +
diff --git a/src/pages/View.jsx b/src/pages/View.jsx index 1aa5e0b5..5274e702 100644 --- a/src/pages/View.jsx +++ b/src/pages/View.jsx @@ -24,6 +24,9 @@ function View({templateInfo}) { speechRecognition.stop() setMicEnabled(false) } + const next = () =>{ + setViewMode(ViewMode.MINT) + } // Translate hook const { t } = useContext(LanguageContext); @@ -52,6 +55,13 @@ function View({templateInfo}) { className={styles.buttonLeft} onClick={back} /> +
) From 9f4f08f26e2dbd11fb3f5b9cc831d6992c6b2583 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Fri, 10 Feb 2023 17:37:20 -0500 Subject: [PATCH 32/79] clean code --- src/components/Mint.jsx | 8 +++++--- src/library/screenshotManager.js | 21 +++++---------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 188c3ec1..9895c615 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -90,7 +90,6 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { } const mintAsset = async (avatar) => { - console.log(templateInfo) // let walletAddress = await connectWallet() // const pass = await checkOT(walletAddress); @@ -99,11 +98,14 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { setMintStatus("Uploading...") let imageHash, glbHash; - const headPosition = templateInfo.traits[0].cameraTarget.height; + const female = templateInfo.name === 'Drophunter' ? true : false; + const headPosition = female ? 1.35 : 1.45; const cameraFov = 1.0; + screenshotManager.setCamera(headPosition, cameraFov); + let imageName = "AvatarImage_" + Date.now() + ".png"; + screenshotManager.saveAsImage(imageName); - screenshotManager.saveAsImage(); // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) // if (screenshot) { diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 57a6d7de..9001c27c 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -21,8 +21,6 @@ export class ScreenshotManager { 0.1, 1000, ) - // this.setUpCamera(); - this.update(); } setCamera(height, playerCameraDistance) { @@ -36,17 +34,18 @@ export class ScreenshotManager { } - saveAsImage() { + saveAsImage(imageName) { let imgData; try { this.renderer.render(this.scene, this.camera); const strDownloadMime = "image/octet-stream"; - const strMime = "image/jpeg"; + const strMime = "image/png"; imgData = this.renderer.domElement.toDataURL(strMime); - this.saveFile(imgData.replace(strMime, strDownloadMime), "test.jpg"); + this.saveFile(imgData.replace(strMime, strDownloadMime), imageName); + return true; } catch (e) { console.log(e); - return; + return false; } } @@ -64,14 +63,4 @@ export class ScreenshotManager { } } - update() { - setInterval(() => { - - // this.renderer.render(this.scene, this.camera); - - }, this.frameRate); - } - - - } \ No newline at end of file From 1038cb74a948c3797f5ea51ad88c1607b678861d Mon Sep 17 00:00:00 2001 From: tcm390 Date: Fri, 10 Feb 2023 18:03:53 -0500 Subject: [PATCH 33/79] convert image to blob --- src/components/Mint.jsx | 158 +++++++++++++++---------------- src/library/screenshotManager.js | 12 ++- 2 files changed, 88 insertions(+), 82 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 9895c615..fe79812f 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -104,91 +104,91 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; - screenshotManager.saveAsImage(imageName); + const screenshot = screenshotManager.saveAsImage(imageName); // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - // if (screenshot) { - // let imageName = "AvatarImage_" + Date.now() + ".png"; - // imageHash = await (async() => { - // for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - // try { - // const img_hash = await saveFileToPinata( - // screenshot, - // imageName - // ).catch((reason) => { - // console.error(i, "---", reason) - // }) - // return img_hash - // } catch(err) { - // console.warn(err); - // } - // } - // throw new Error('failed to upload screenshot'); - // setMintStatus("Couldn't save screenshot to pinata") - // })(); - // } else { - // throw new Error("Unable to get screenshot") - // } + if (screenshot) { + let imageName = "AvatarImage_" + Date.now() + ".png"; + imageHash = await (async() => { + for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + try { + const img_hash = await saveFileToPinata( + screenshot, + imageName + ).catch((reason) => { + console.error(i, "---", reason) + }) + return img_hash + } catch(err) { + console.warn(err); + } + } + throw new Error('failed to upload screenshot'); + setMintStatus("Couldn't save screenshot to pinata") + })(); + } else { + throw new Error("Unable to get screenshot") + } - // const glb = await getGLBBlobData(model) - // if (glb) { - // let glbName = "AvatarGlb_" + Date.now() + ".glb"; - // glbHash = await (async() => { - // for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - // try { - // const glb_hash = await saveFileToPinata( - // glb, - // glbName - // ).catch((reason) => { - // console.error(i, "---", reason) - // setMintStatus("Couldn't save glb to pinata") - // }) - // return glb_hash - // } catch(err) { - // console.warn(err); - // } - // } - // throw new Error('failed to upload glb'); - // setMintStatus("Couldn't save glb to pinata") - // })(); - // } else { - // throw new Error("Unable to get glb") - // } + const glb = await getGLBBlobData(model) + if (glb) { + let glbName = "AvatarGlb_" + Date.now() + ".glb"; + glbHash = await (async() => { + for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + try { + const glb_hash = await saveFileToPinata( + glb, + glbName + ).catch((reason) => { + console.error(i, "---", reason) + setMintStatus("Couldn't save glb to pinata") + }) + return glb_hash + } catch(err) { + console.warn(err); + } + } + throw new Error('failed to upload glb'); + setMintStatus("Couldn't save glb to pinata") + })(); + } else { + throw new Error("Unable to get glb") + } - // const attributes = getAvatarTraits() - // const metadata = { - // name: "Avatars", - // description: "Character Studio Avatars.", - // image: `ipfs://${imageHash.IpfsHash}`, - // animation_url: `ipfs://${glbHash.IpfsHash}`, - // attributes: attributes - // } - // const str = JSON.stringify(metadata) - // const metaDataHash = await saveFileToPinata( - // new Blob([str]), - // "AvatarMetadata_" + Date.now() + ".json", - // ) - // const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` + const attributes = getAvatarTraits() + const metadata = { + name: "Avatars", + description: "Character Studio Avatars.", + image: `ipfs://${imageHash.IpfsHash}`, + animation_url: `ipfs://${glbHash.IpfsHash}`, + attributes: attributes + } + const str = JSON.stringify(metadata) + const metaDataHash = await saveFileToPinata( + new Blob([str]), + "AvatarMetadata_" + Date.now() + ".json", + ) + const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` - // setMintStatus("Minting...") - // const signer = new ethers.providers.Web3Provider( - // window.ethereum, - // ).getSigner() - // const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) - // try { - // const options = { - // value: tokenPrice, - // from: walletAddress - // } - // const tx = await contract.mintToken(1, metadataIpfs, options) - // let res = await tx.wait() - // if (res.transactionHash) { - // setMintStatus("Mint success!") - // } - // } catch (err) { - // setMintStatus("Public Mint failed! Please check your wallet.") - // } + setMintStatus("Minting...") + const signer = new ethers.providers.Web3Provider( + window.ethereum, + ).getSigner() + const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) + try { + const options = { + value: tokenPrice, + from: walletAddress + } + const tx = await contract.mintToken(1, metadataIpfs, options) + let res = await tx.wait() + if (res.transactionHash) { + setMintStatus("Mint success!") + } + } catch (err) { + setMintStatus("Public Mint failed! Please check your wallet.") + } } else { return; } diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 9001c27c..4106da32 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -1,11 +1,10 @@ import * as THREE from "three" +import { Buffer } from "buffer"; const localVector = new THREE.Vector3(); export class ScreenshotManager { constructor() { - this.frameRate = 1000 / 30; - this.renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true }); @@ -41,8 +40,15 @@ export class ScreenshotManager { const strDownloadMime = "image/octet-stream"; const strMime = "image/png"; imgData = this.renderer.domElement.toDataURL(strMime); + + const base64Data = Buffer.from( + imgData.replace(/^data:image\/\w+;base64,/, ""), + "base64" + ); + const blob = new Blob([base64Data], { type: "image/jpeg" }); + this.saveFile(imgData.replace(strMime, strDownloadMime), imageName); - return true; + return blob; } catch (e) { console.log(e); return false; From 20bf72baafc20cb7b0f0d9b82895c97d0917db59 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Fri, 10 Feb 2023 18:39:34 -0500 Subject: [PATCH 34/79] open eyes when screenshot --- src/App.jsx | 1 + src/library/blinkManager.js | 4 ++++ src/library/screenshotManager.js | 9 ++++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index a0547a44..6b8fc782 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -187,6 +187,7 @@ export default function App() { effectManager.scene = scene screenshotManager.scene = scene + screenshotManager.blinkManager = blinkManager const updateCameraPosition = () => { if (!effectManager.camera) return diff --git a/src/library/blinkManager.js b/src/library/blinkManager.js index 1650e8ae..3a59757d 100644 --- a/src/library/blinkManager.js +++ b/src/library/blinkManager.js @@ -24,6 +24,10 @@ export class BlinkManager { this.vrmBlinkers.push(vrm) } + setEyeOpen() { + this._eyeOpen = 2; + } + update(){ setInterval(() => { const deltaTime = this.clock.getDelta() diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 4106da32..b69fc88b 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -9,14 +9,16 @@ export class ScreenshotManager { preserveDrawingBuffer: true }); - this.renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight); + const width = 500; + const height = 750; + this.renderTarget = new THREE.WebGLRenderTarget(width, height); this.renderTarget.texture.encoding = THREE.sRGBEncoding; - this.renderer.setSize(window.innerWidth, window.innerHeight); + this.renderer.setSize(width, height); this.camera = new THREE.PerspectiveCamera( 30, - window.innerWidth / window.innerHeight, + width / height, 0.1, 1000, ) @@ -36,6 +38,7 @@ export class ScreenshotManager { saveAsImage(imageName) { let imgData; try { + this.blinkManager.setEyeOpen(); this.renderer.render(this.scene, this.camera); const strDownloadMime = "image/octet-stream"; const strMime = "image/png"; From 1217378af4f9542980943b2bea4479491b68db56 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 10 Feb 2023 18:01:03 -0600 Subject: [PATCH 35/79] screenshot encoding --- src/library/screenshotManager.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index b69fc88b..bc5305e2 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -8,11 +8,10 @@ export class ScreenshotManager { this.renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true }); + this.renderer.outputEncoding = THREE.sRGBEncoding const width = 500; const height = 750; - this.renderTarget = new THREE.WebGLRenderTarget(width, height); - this.renderTarget.texture.encoding = THREE.sRGBEncoding; this.renderer.setSize(width, height); From 6512c10287e6c9997d9fe99ed267066367affd67 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 10 Feb 2023 18:07:48 -0600 Subject: [PATCH 36/79] add pause to animation manager --- src/library/animationManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/animationManager.js b/src/library/animationManager.js index 31201aaf..52a89474 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -76,7 +76,7 @@ export class AnimationManager{ ); } setInterval(() => { - this.update(); + //this.update(); }, 1000/30); } async loadAnimations(path){ From 7f0933000956c21f934a5630321abd23d536b9f9 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 10 Feb 2023 18:09:06 -0600 Subject: [PATCH 37/79] fix paused var --- src/library/animationManager.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/library/animationManager.js b/src/library/animationManager.js index 52a89474..fa0d9474 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -75,10 +75,18 @@ export class AnimationManager{ offset[2] ); } + this.paused = false; setInterval(() => { - //this.update(); + if (!this.paused) + this.update(); }, 1000/30); } + pause(){ + this.paused = true; + } + resume(){ + this.paused = false; + } async loadAnimations(path){ const loader = path.endsWith('.fbx') ? fbxLoader : gltfLoader; const anim = await loader.loadAsync(path); From d743f2cb36e506bb0a0f45cf4a2957fa4d1a8c87 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:35:37 -0600 Subject: [PATCH 38/79] confix --- src/App.jsx | 2 +- src/components/Mint.jsx | 6 +++--- src/library/animationManager.js | 10 ++++++++++ src/pages/Mint.jsx | 5 +++-- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 6b8fc782..a9a8b734 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -289,7 +289,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index fe79812f..85e3eb31 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -15,12 +15,12 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotPosition, screenshotManager}) { +export default function MintPopup({screenshotPosition, screenshotManager, animationManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); const chainId = "0x89"; - + useEffect(() => { ( async () => { const defaultProvider = new ethers.providers.StaticJsonRpcProvider('https://polygon-rpc.com/') @@ -101,7 +101,7 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { const female = templateInfo.name === 'Drophunter' ? true : false; const headPosition = female ? 1.35 : 1.45; const cameraFov = 1.0; - + animationManager.reset(); screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; const screenshot = screenshotManager.saveAsImage(imageName); diff --git a/src/library/animationManager.js b/src/library/animationManager.js index fa0d9474..cc8d6dc5 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -48,6 +48,11 @@ class AnimationControl { this.actions[curIdx].play(); } + reset(){ + this.to.reset(); + this.to.play(); + } + dispose(){ this.animationManager.disposeAnimation(this); //console.log("todo dispose animation control") @@ -87,6 +92,11 @@ export class AnimationManager{ resume(){ this.paused = false; } + reset(){ + this.animationControls.forEach(control => { + control.reset() + }); + } async loadAnimations(path){ const loader = path.endsWith('.fbx') ? fbxLoader : gltfLoader; const anim = await loader.loadAsync(path); diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index ba14ef95..071e4a4c 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -5,10 +5,11 @@ import { ViewMode, ViewContext } from "../context/ViewContext" import Mint from "../components/Mint" import CustomButton from "../components/custom-button" + import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" -function MintComponent({screenshotManager}) { +function MintComponent({screenshotManager, animationManager}) { const { setViewMode } = React.useContext(ViewContext) const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); @@ -33,7 +34,7 @@ function MintComponent({screenshotManager}) {
- +
From 16eb5d12793a19f69712257ff579e67a7e59caae Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:36:24 -0600 Subject: [PATCH 39/79] confix --- src/App.jsx | 3 +-- src/components/Mint.jsx | 3 +-- src/library/animationManager.js | 22 ++-------------------- src/library/blinkManager.js | 4 ---- src/library/screenshotManager.js | 1 - src/pages/Mint.jsx | 6 +++++- 6 files changed, 9 insertions(+), 30 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index a9a8b734..a0547a44 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -187,7 +187,6 @@ export default function App() { effectManager.scene = scene screenshotManager.scene = scene - screenshotManager.blinkManager = blinkManager const updateCameraPosition = () => { if (!effectManager.camera) return @@ -289,7 +288,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 85e3eb31..65c2871b 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -15,7 +15,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotPosition, screenshotManager, animationManager}) { +export default function MintPopup({screenshotPosition, screenshotManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -101,7 +101,6 @@ export default function MintPopup({screenshotPosition, screenshotManager, animat const female = templateInfo.name === 'Drophunter' ? true : false; const headPosition = female ? 1.35 : 1.45; const cameraFov = 1.0; - animationManager.reset(); screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; const screenshot = screenshotManager.saveAsImage(imageName); diff --git a/src/library/animationManager.js b/src/library/animationManager.js index cc8d6dc5..9db19464 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -48,11 +48,6 @@ class AnimationControl { this.actions[curIdx].play(); } - reset(){ - this.to.reset(); - this.to.play(); - } - dispose(){ this.animationManager.disposeAnimation(this); //console.log("todo dispose animation control") @@ -80,23 +75,10 @@ export class AnimationManager{ offset[2] ); } - this.paused = false; setInterval(() => { - if (!this.paused) - this.update(); + this.update(); }, 1000/30); } - pause(){ - this.paused = true; - } - resume(){ - this.paused = false; - } - reset(){ - this.animationControls.forEach(control => { - control.reset() - }); - } async loadAnimations(path){ const loader = path.endsWith('.fbx') ? fbxLoader : gltfLoader; const anim = await loader.loadAsync(path); @@ -219,4 +201,4 @@ export class AnimationManager{ else this.weightOut = 0; } } -} +} \ No newline at end of file diff --git a/src/library/blinkManager.js b/src/library/blinkManager.js index 3a59757d..1650e8ae 100644 --- a/src/library/blinkManager.js +++ b/src/library/blinkManager.js @@ -24,10 +24,6 @@ export class BlinkManager { this.vrmBlinkers.push(vrm) } - setEyeOpen() { - this._eyeOpen = 2; - } - update(){ setInterval(() => { const deltaTime = this.clock.getDelta() diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index bc5305e2..0e407da7 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -37,7 +37,6 @@ export class ScreenshotManager { saveAsImage(imageName) { let imgData; try { - this.blinkManager.setEyeOpen(); this.renderer.render(this.scene, this.camera); const strDownloadMime = "image/octet-stream"; const strMime = "image/png"; diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 071e4a4c..70883c65 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -5,12 +5,16 @@ import { ViewMode, ViewContext } from "../context/ViewContext" import Mint from "../components/Mint" import CustomButton from "../components/custom-button" +<<<<<<< HEAD import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" function MintComponent({screenshotManager, animationManager}) { +======= +function MintComponent({screenshotManager}) { +>>>>>>> d1a3866 (revert blink manager and animation manager) const { setViewMode } = React.useContext(ViewContext) const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); const { playSound } = React.useContext(SoundContext) @@ -34,7 +38,7 @@ function MintComponent({screenshotManager, animationManager}) {
- +
From 0ae9411d8f5b255b608093eb5f59baa78486908c Mon Sep 17 00:00:00 2001 From: tcm390 Date: Mon, 13 Feb 2023 11:10:36 -0500 Subject: [PATCH 40/79] use head world position for screenshot instead of harded code --- src/components/Mint.jsx | 14 ++++++++++---- src/library/screenshotManager.js | 8 ++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 65c2871b..ba4d4099 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -1,3 +1,5 @@ +import * as THREE from 'three'; + import axios from "axios" import { BigNumber, ethers } from "ethers" import React, { Fragment, useContext, useState, useEffect } from "react" @@ -88,8 +90,15 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { }) return metadataTraits } - + const headPosition = new THREE.Vector3(); const mintAsset = async (avatar) => { + console.log(avatar) + avatar.traverse(o => { + if (o.isSkinnedMesh) { + const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] + headBone.getWorldPosition(headPosition) + } + }); // let walletAddress = await connectWallet() // const pass = await checkOT(walletAddress); @@ -97,9 +106,6 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { if(pass) { setMintStatus("Uploading...") let imageHash, glbHash; - - const female = templateInfo.name === 'Drophunter' ? true : false; - const headPosition = female ? 1.35 : 1.45; const cameraFov = 1.0; screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 0e407da7..5e772ae3 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -23,14 +23,14 @@ export class ScreenshotManager { ) } - setCamera(height, playerCameraDistance) { - this.camera.position.y = height; + setCamera(headPosition, playerCameraDistance) { + this.camera.position.copy(headPosition); localVector.set(0, 0, -1); this.cameraDir = localVector.applyQuaternion(this.camera.quaternion); this.cameraDir.normalize(); - this.camera.position.x = -this.cameraDir.x * playerCameraDistance; - this.camera.position.z = -this.cameraDir.z * playerCameraDistance; + this.camera.position.x -= this.cameraDir.x * playerCameraDistance; + this.camera.position.z -= this.cameraDir.z * playerCameraDistance; } From f25954312d8ef6265a55d96dfbdf9e19899087f8 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Mon, 13 Feb 2023 11:11:20 -0500 Subject: [PATCH 41/79] clean code --- src/components/Mint.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index ba4d4099..4e78ceb8 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -92,7 +92,6 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { } const headPosition = new THREE.Vector3(); const mintAsset = async (avatar) => { - console.log(avatar) avatar.traverse(o => { if (o.isSkinnedMesh) { const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] From 6f56cf6ffa2736d0e99c3d3a0b9c8f8e6e85bd09 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:37:28 -0600 Subject: [PATCH 42/79] confix --- src/components/Mint.jsx | 10 +++++----- src/pages/Mint.jsx | 11 ++--------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 4e78ceb8..a1a27ca1 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -17,7 +17,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotPosition, screenshotManager}) { +export default function MintPopup({screenshotManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -198,10 +198,10 @@ export default function MintPopup({screenshotPosition, screenshotManager}) { } } - const takeScreenshot = async () => { - const img = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - const glb = await getGLBBlobData(model) - } + // const takeScreenshot = async () => { + // const img = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) + // const glb = await getGLBBlobData(model) + // } const checkOT = async (address) => { if(address) { diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 70883c65..368d3e3b 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -4,19 +4,12 @@ import { ViewMode, ViewContext } from "../context/ViewContext" import Mint from "../components/Mint" import CustomButton from "../components/custom-button" - -<<<<<<< HEAD - import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" -function MintComponent({screenshotManager, animationManager}) { - -======= function MintComponent({screenshotManager}) { ->>>>>>> d1a3866 (revert blink manager and animation manager) + const { setViewMode } = React.useContext(ViewContext) - const [screenshotPosition, setScreenshotPosition] = React.useState({x:250,y:25,width:256,height:256}); const { playSound } = React.useContext(SoundContext) const { isMute } = React.useContext(AudioContext) @@ -38,7 +31,7 @@ function MintComponent({screenshotManager}) {
- +
From 699ca66ffc5f6b5a683c86f0dfe11fc592b20ffb Mon Sep 17 00:00:00 2001 From: tcm390 Date: Mon, 13 Feb 2023 11:27:38 -0500 Subject: [PATCH 43/79] clean code --- src/components/Mint.jsx | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index a1a27ca1..ccd2aacf 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -12,6 +12,8 @@ import { CharacterContract, EternalProxyContract, webaverseGenesisAddress } from import { getGLBBlobData } from "../library/download-utils" import styles from "./Mint.module.css" +const localVector = new THREE.Vector3(); + const pinataApiKey = import.meta.env.VITE_PINATA_API_KEY const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET @@ -90,21 +92,25 @@ export default function MintPopup({screenshotManager}) { }) return metadataTraits } - const headPosition = new THREE.Vector3(); + + const mintAsset = async (avatar) => { - avatar.traverse(o => { - if (o.isSkinnedMesh) { - const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] - headBone.getWorldPosition(headPosition) - } - }); // let walletAddress = await connectWallet() // const pass = await checkOT(walletAddress); const pass = true; + if(pass) { setMintStatus("Uploading...") let imageHash, glbHash; + + avatar.traverse(o => { + if (o.isSkinnedMesh) { + const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] + headBone.getWorldPosition(localVector) + } + }); + const headPosition = localVector; const cameraFov = 1.0; screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; From a4a321c93f502a621c7938b2771cf04b73115888 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Mon, 13 Feb 2023 11:31:52 -0500 Subject: [PATCH 44/79] spacing --- src/components/Mint.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index ccd2aacf..6dc66683 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -106,8 +106,8 @@ export default function MintPopup({screenshotManager}) { avatar.traverse(o => { if (o.isSkinnedMesh) { - const headBone = o.skeleton.bones.filter(bone=>bone.name==='head')[0] - headBone.getWorldPosition(localVector) + const headBone = o.skeleton.bones.filter(bone => bone.name === 'head')[0]; + headBone.getWorldPosition(localVector); } }); const headPosition = localVector; From e19cfa6a8cf18b9f285f020c42d37edcdeb6a227 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 11:28:05 -0500 Subject: [PATCH 45/79] change screen shot ratio and camera fov --- src/components/Mint.jsx | 3 ++- src/library/screenshotManager.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index 6dc66683..eab968f5 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -111,7 +111,8 @@ export default function MintPopup({screenshotManager}) { } }); const headPosition = localVector; - const cameraFov = 1.0; + const female = templateInfo.name === "Drophunter"; + const cameraFov = female ? 0.78 : 0.85; screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; const screenshot = screenshotManager.saveAsImage(imageName); diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 5e772ae3..635a3183 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -10,8 +10,8 @@ export class ScreenshotManager { }); this.renderer.outputEncoding = THREE.sRGBEncoding - const width = 500; - const height = 750; + const width = 512; + const height = 512; this.renderer.setSize(width, height); From 03aa89085e081e5c1a726ba0965a3a585b0ac51e Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 11:49:16 -0500 Subject: [PATCH 46/79] add screenshot background --- src/library/screenshotManager.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 635a3183..3d36d7b7 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -3,6 +3,10 @@ import { Buffer } from "buffer"; const localVector = new THREE.Vector3(); +const textureLoader = new THREE.TextureLoader(); +const backgroundTexture = textureLoader.load(`/assets/backgrounds/main-background2.jpg`); +backgroundTexture.wrapS = backgroundTexture.wrapT = THREE.RepeatWrapping; + export class ScreenshotManager { constructor() { this.renderer = new THREE.WebGLRenderer({ @@ -37,6 +41,7 @@ export class ScreenshotManager { saveAsImage(imageName) { let imgData; try { + this.scene.background = backgroundTexture; this.renderer.render(this.scene, this.camera); const strDownloadMime = "image/octet-stream"; const strMime = "image/png"; @@ -49,6 +54,7 @@ export class ScreenshotManager { const blob = new Blob([base64Data], { type: "image/jpeg" }); this.saveFile(imgData.replace(strMime, strDownloadMime), imageName); + this.scene.background = null; return blob; } catch (e) { console.log(e); From b589984371144b3540cf0b7325e37beba746264d Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 13:09:57 -0500 Subject: [PATCH 47/79] add antialias to screenshot renderer --- src/library/screenshotManager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 3d36d7b7..720ea81b 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -10,7 +10,8 @@ backgroundTexture.wrapS = backgroundTexture.wrapT = THREE.RepeatWrapping; export class ScreenshotManager { constructor() { this.renderer = new THREE.WebGLRenderer({ - preserveDrawingBuffer: true + preserveDrawingBuffer: true, + antialias: true }); this.renderer.outputEncoding = THREE.sRGBEncoding From 7568078a10ca67c76b2b03377ae82670de7ee5fb Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:37:59 -0600 Subject: [PATCH 48/79] confix --- src/App.jsx | 2 +- src/components/Mint.jsx | 5 +++-- src/library/blinkManager.js | 20 ++++++++++++++++++-- src/library/screenshotManager.js | 2 +- src/pages/Mint.jsx | 4 ++-- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index a0547a44..24ee6120 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -288,7 +288,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index eab968f5..b69a6d48 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -19,7 +19,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotManager}) { +export default function MintPopup({screenshotManager, blinkManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -101,6 +101,7 @@ export default function MintPopup({screenshotManager}) { const pass = true; if(pass) { + blinkManager.enableScreenshot(); setMintStatus("Uploading...") let imageHash, glbHash; @@ -116,7 +117,7 @@ export default function MintPopup({screenshotManager}) { screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; const screenshot = screenshotManager.saveAsImage(imageName); - + blinkManager.disableScreenshot(); // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) if (screenshot) { diff --git a/src/library/blinkManager.js b/src/library/blinkManager.js index 1650e8ae..ae744e6d 100644 --- a/src/library/blinkManager.js +++ b/src/library/blinkManager.js @@ -1,6 +1,7 @@ import { VRMExpressionPresetName } from "@pixiv/three-vrm"; import { Clock } from "three"; +const SCREENSHOT_EYES_OPEN_THRESHOLD = 2; export class BlinkManager { constructor(closeTime = 0.5, openTime = 0.5, continuity = 1, randomness = 5) { @@ -17,6 +18,8 @@ export class BlinkManager { this._eyeOpen = 1 this._blinkCounter = 0; + this.isTakingScreenShot = false; + this.update() } @@ -24,8 +27,21 @@ export class BlinkManager { this.vrmBlinkers.push(vrm) } + enableScreenshot() { + this.isTakingScreenShot = true; + this._eyeOpen = SCREENSHOT_EYES_OPEN_THRESHOLD; + this._updateBlinkers(); + } + + disableScreenshot() { + this.isTakingScreenShot = false; + } + update(){ setInterval(() => { + if (this.isTakingScreenShot) { + return; + } const deltaTime = this.clock.getDelta() switch (this.mode){ @@ -33,7 +49,7 @@ export class BlinkManager { if ( this._eyeOpen > 0) this._eyeOpen -= deltaTime / this.closeTime; else{ - this._eyeOpen =0 + this._eyeOpen = 0 this.mode = 'open' } this._updateBlinkers(); @@ -42,7 +58,7 @@ export class BlinkManager { if ( this._eyeOpen < 1) this._eyeOpen += deltaTime / this.openTime; else{ - this._eyeOpen =1 + this._eyeOpen = 1 this.mode = 'ready' } this._updateBlinkers(); diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 720ea81b..db0503f9 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -36,7 +36,7 @@ export class ScreenshotManager { this.cameraDir.normalize(); this.camera.position.x -= this.cameraDir.x * playerCameraDistance; this.camera.position.z -= this.cameraDir.z * playerCameraDistance; - + } saveAsImage(imageName) { diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 368d3e3b..6f5a4223 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -7,8 +7,8 @@ import CustomButton from "../components/custom-button" import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" -function MintComponent({screenshotManager}) { +function MintComponent({screenshotManager, blinkManager}) { const { setViewMode } = React.useContext(ViewContext) const { playSound } = React.useContext(SoundContext) const { isMute } = React.useContext(AudioContext) @@ -31,7 +31,7 @@ function MintComponent({screenshotManager}) {
- +
From 1e72dc4d6f4de9b67b9e2da56cb6516ae9af5266 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 16:52:19 -0500 Subject: [PATCH 49/79] missing uri --- src/library/screenshotManager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index db0503f9..173a02c5 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -73,7 +73,8 @@ export class ScreenshotManager { link.click(); document.body.removeChild(link); //remove the link when done } else { - location.replace(uri); + const win = window.open(strData, "_blank"); + win.document.write("" + filename + ""); } } From 33c06f79d57e78b395e6f49147ba81bfb9eeb474 Mon Sep 17 00:00:00 2001 From: soulofmischief <30357883+soulofmischief@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:24:35 -0800 Subject: [PATCH 50/79] Set screenshot size to 4096x4096 --- src/library/screenshotManager.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/library/screenshotManager.js b/src/library/screenshotManager.js index 173a02c5..1dc26368 100644 --- a/src/library/screenshotManager.js +++ b/src/library/screenshotManager.js @@ -1,6 +1,8 @@ import * as THREE from "three" import { Buffer } from "buffer"; +const screenshotSize = 4096; + const localVector = new THREE.Vector3(); const textureLoader = new THREE.TextureLoader(); @@ -13,19 +15,10 @@ export class ScreenshotManager { preserveDrawingBuffer: true, antialias: true }); - this.renderer.outputEncoding = THREE.sRGBEncoding - - const width = 512; - const height = 512; + this.renderer.outputEncoding = THREE.sRGBEncoding; + this.renderer.setSize(screenshotSize, screenshotSize); - this.renderer.setSize(width, height); - - this.camera = new THREE.PerspectiveCamera( - 30, - width / height, - 0.1, - 1000, - ) + this.camera = new THREE.PerspectiveCamera( 30, 1, 0.1, 1000 ); } setCamera(headPosition, playerCameraDistance) { @@ -36,7 +29,7 @@ export class ScreenshotManager { this.cameraDir.normalize(); this.camera.position.x -= this.cameraDir.x * playerCameraDistance; this.camera.position.z -= this.cameraDir.z * playerCameraDistance; - + } saveAsImage(imageName) { From d55286ae45f7668995930931cb898defeec50a85 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 18:09:36 -0500 Subject: [PATCH 51/79] let all screenshot have the same frame of the animation --- src/App.jsx | 2 +- src/components/Mint.jsx | 5 ++++- src/library/animationManager.js | 21 +++++++++++++++++++++ src/pages/Mint.jsx | 4 ++-- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 24ee6120..8d7f1eab 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -288,7 +288,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx index b69a6d48..e0ed6bb9 100644 --- a/src/components/Mint.jsx +++ b/src/components/Mint.jsx @@ -19,7 +19,7 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 -export default function MintPopup({screenshotManager, blinkManager}) { +export default function MintPopup({screenshotManager, blinkManager, animationManager}) { const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) const [mintStatus, setMintStatus] = useState("") const [tokenPrice, setTokenPrice] = useState(null); @@ -101,6 +101,7 @@ export default function MintPopup({screenshotManager, blinkManager}) { const pass = true; if(pass) { + animationManager.enableScreenshot(); blinkManager.enableScreenshot(); setMintStatus("Uploading...") let imageHash, glbHash; @@ -116,8 +117,10 @@ export default function MintPopup({screenshotManager, blinkManager}) { const cameraFov = female ? 0.78 : 0.85; screenshotManager.setCamera(headPosition, cameraFov); let imageName = "AvatarImage_" + Date.now() + ".png"; + const screenshot = screenshotManager.saveAsImage(imageName); blinkManager.disableScreenshot(); + animationManager.disableScreenshot(); // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) if (screenshot) { diff --git a/src/library/animationManager.js b/src/library/animationManager.js index 9db19464..67474528 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -48,6 +48,15 @@ class AnimationControl { this.actions[curIdx].play(); } + enableScreenshot() { + this.mixer.setTime(0); + this.to.paused = true; + } + + disableScreenshot() { + this.to.paused = false; + } + dispose(){ this.animationManager.disposeAnimation(this); //console.log("todo dispose animation control") @@ -93,6 +102,18 @@ export class AnimationManager{ } + enableScreenshot() { + this.animationControls.forEach(control => { + control.enableScreenshot() + }); + } + + disableScreenshot() { + this.animationControls.forEach(control => { + control.disableScreenshot() + }); + } + offsetHips(){ this.animations.forEach(anim => { for (let i =0; i < anim.tracks.length; i++){ diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 6f5a4223..ae428065 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -8,7 +8,7 @@ import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" -function MintComponent({screenshotManager, blinkManager}) { +function MintComponent({screenshotManager, blinkManager, animationManager}) { const { setViewMode } = React.useContext(ViewContext) const { playSound } = React.useContext(SoundContext) const { isMute } = React.useContext(AudioContext) @@ -31,7 +31,7 @@ function MintComponent({screenshotManager, blinkManager}) {
- +
From 83df9593d9ca3bd1c97b975dca81f18258c5dcd1 Mon Sep 17 00:00:00 2001 From: tcm390 Date: Tue, 14 Feb 2023 18:36:12 -0500 Subject: [PATCH 52/79] rename --- src/library/animationManager.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/library/animationManager.js b/src/library/animationManager.js index 67474528..f563f277 100644 --- a/src/library/animationManager.js +++ b/src/library/animationManager.js @@ -48,12 +48,12 @@ class AnimationControl { this.actions[curIdx].play(); } - enableScreenshot() { + reset() { this.mixer.setTime(0); this.to.paused = true; } - disableScreenshot() { + resume() { this.to.paused = false; } @@ -104,13 +104,13 @@ export class AnimationManager{ enableScreenshot() { this.animationControls.forEach(control => { - control.enableScreenshot() + control.reset() }); } disableScreenshot() { this.animationControls.forEach(control => { - control.disableScreenshot() + control.resume() }); } From fef103d6ee31f905f38c94f6d1cfa5f830916790 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:43:56 -0600 Subject: [PATCH 53/79] confix --- .gitignore | 5 + package.json | 1 + public/assets/icons/polygon.svg | 18 ++ src/App.jsx | 4 +- .../custom-button/IconCollection.jsx | 8 + src/pages/Mint.jsx | 46 +++++- src/pages/Mint.module.css | 113 ------------- src/pages/Mint.module.scss | 154 ++++++++++++++++++ src/pages/Save.jsx | 92 ++++++----- src/pages/Save.module.css | 28 ++-- 10 files changed, 294 insertions(+), 175 deletions(-) create mode 100644 public/assets/icons/polygon.svg delete mode 100644 src/pages/Mint.module.css create mode 100644 src/pages/Mint.module.scss diff --git a/.gitignore b/.gitignore index f6f5676f..d2464ebb 100644 --- a/.gitignore +++ b/.gitignore @@ -99,6 +99,7 @@ web_modules/ # Optional eslint cache .eslintcache +<<<<<<< HEAD # Microbundle cache .rpt2_cache/ @@ -274,3 +275,7 @@ fabric.properties # Documentation here: https://yarnpkg.com/features/zero-installs #!/.yarn/cache /.pnp.* +======= +lerna-debug.log +.vscode +>>>>>>> 994de2e (adjust mint page to match figma mockups) diff --git a/package.json b/package.json index 68f4ab07..1c8f2f8c 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "eslint-plugin-no-inline-styles": "^1.0.5", "eslint-plugin-react": "^7.31.11", "prettier": "^2.3.2", + "sass": "^1.58.0", "vite": "^4.0.0" } } diff --git a/public/assets/icons/polygon.svg b/public/assets/icons/polygon.svg new file mode 100644 index 00000000..2ee2e72a --- /dev/null +++ b/public/assets/icons/polygon.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/src/App.jsx b/src/App.jsx index 8d7f1eab..13ce582c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -191,7 +191,7 @@ export default function App() { const updateCameraPosition = () => { if (!effectManager.camera) return - if ([ViewMode.BIO, ViewMode.MINT, ViewMode.CHAT].includes(viewMode)) { + if ([ViewMode.BIO, ViewMode.CHAT].includes(viewMode)) { // auto move camera if (viewMode === ViewMode.CHAT) { cameraDistance = cameraDistanceChat @@ -288,7 +288,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/components/custom-button/IconCollection.jsx b/src/components/custom-button/IconCollection.jsx index 5918c6fa..68363aef 100644 --- a/src/components/custom-button/IconCollection.jsx +++ b/src/components/custom-button/IconCollection.jsx @@ -123,4 +123,12 @@ export const IconCollection = [ name: 'soundoff', file: '/assets/icons/soundoff.svg', }, + { + name: 'soundoff', + file: '/assets/icons/soundoff.svg', + }, + { + name: 'polygon', + file: '/assets/icons/polygon.svg', + }, ]; \ No newline at end of file diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index ae428065..d4e80146 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -1,8 +1,6 @@ import React from "react" -import styles from "./Mint.module.css" +import styles from "./Mint.module.scss" import { ViewMode, ViewContext } from "../context/ViewContext" - -import Mint from "../components/Mint" import CustomButton from "../components/custom-button" import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" @@ -23,18 +21,48 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { !isMute && playSound('backNextButton'); } + function MenuTitle() { + return ( +
+
+
Mint
+
+ ) + } + return (
Mint Your Character
+ + {/* */} +
-
-
-
- - + + +
+ + +
+ + + + (Genesis pass holders only)
-
+ +
div { + padding: 16px !important; + } + + .genesisText { + opacity: 0.4; + + .required:after { + content: "*"; + color: red; + } + } + + .divider { + width: 80%; + height: 1px; + margin: 8px 0; + opacity: 0.2; + background: #e0e6e5; + } + } + } + + .bottomContainer { + z-index: 0; + display: flex; + padding: 20px 32px; + justify-content: space-between; + + button { + min-width: 120px; + } + } +} + +.topLine { + background: rgb(0, 149, 100); + background: -moz-linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + + background: -webkit-linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + + background: linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + + top: 0; + left: 0; + width: 100%; + height: 1px; + position: absolute; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1); +} + +.bottomLine { + background: rgb(0, 149, 100); + background: -moz-linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + background: -webkit-linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + background: linear-gradient( + 90deg, + rgba(0, 149, 100, 0) 0%, + rgba(8, 234, 160, 1) 50%, + rgba(0, 149, 100, 0) 100% + ); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#009564",endColorstr="#009564",GradientType=1); + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 1px; +} diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index dbd826a5..98c2e2b0 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -9,56 +9,66 @@ import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" function Save() { - const { setViewMode } = React.useContext(ViewContext); + // Translate hook + const { t } = useContext(LanguageContext); const { playSound } = React.useContext(SoundContext) const { isMute } = React.useContext(AudioContext) + + + const { setViewMode } = React.useContext(ViewContext); + + const back = () => { + setViewMode(ViewMode.BIO) + !isMute && playSound('backNextButton'); + } + + const mint = () => { + setViewMode(ViewMode.MINT) + !isMute && playSound('backNextButton'); + } - const back = () => { - setViewMode(ViewMode.BIO) - !isMute && playSound('backNextButton'); - } - const mint = () => { - setViewMode(ViewMode.CHAT) - } const next = () => { setViewMode(ViewMode.CHAT) !isMute && playSound('backNextButton'); } - // Translate hook - const { t } = useContext(LanguageContext); + return ( +
+
{t("pageTitles.saveCharacter")}
+
+
+ +
+ + + - return ( -
-
{t("pageTitles.saveCharacter")}
-
- - - {/* - - */} - -
-
- ) +
+ + + +
+
+
+ ); } export default Save diff --git a/src/pages/Save.module.css b/src/pages/Save.module.css index fa9073a0..416fb1d7 100644 --- a/src/pages/Save.module.css +++ b/src/pages/Save.module.css @@ -1,18 +1,26 @@ +.container{ + height: 100%; + display: flex; + align-items: flex-end; + justify-content: center; +} + .buttonContainer { - position: absolute; - bottom: 20px; - left: 32px; - width: calc(100% - 64px); - width: -webkit-calc(100% - 64px); - text-align: center; + z-index: 0; + width: 100%; + padding: 20px 32px; + display: flex; } -.buttonContainer .buttonLeft { - float: left; +.buttonContainer .leftButtonContainer{ + margin-right: auto; + display: inline-flex; + } -.buttonContainer .buttonRight { - float: Right; +.buttonContainer .rightButtonContainer{ + margin-left: auto; + display: inline-flex; } .buttonContainer .buttonCenter { From 25710cb8b79f4f6d8d1b7187db3520275ac1d037 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:45:33 -0600 Subject: [PATCH 54/79] confix --- src/pages/Save.jsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index 98c2e2b0..a7291834 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -22,11 +22,6 @@ function Save() { !isMute && playSound('backNextButton'); } - const mint = () => { - setViewMode(ViewMode.MINT) - !isMute && playSound('backNextButton'); - } - const next = () => { setViewMode(ViewMode.CHAT) !isMute && playSound('backNextButton'); @@ -50,13 +45,13 @@ function Save() {
- + /> */} Date: Wed, 8 Mar 2023 18:48:44 -0600 Subject: [PATCH 55/79] confix --- src/pages/Mint.jsx | 8 ++++++++ src/pages/Save.jsx | 20 +++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index d4e80146..d33720ba 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -33,6 +33,14 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { return (
Mint Your Character
+ {/* tcm-screenshot + ///
+ ///
+ ///
+ ///
+ + /// +======= */} {/* */} diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index a7291834..a5521afa 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -1,4 +1,4 @@ -import React, { useContext } from "react" + import React, { useContext } from "react" import styles from "./Save.module.css" import { ExportMenu } from "../components/ExportMenu" @@ -15,13 +15,15 @@ function Save() { const { isMute } = React.useContext(AudioContext) - const { setViewMode } = React.useContext(ViewContext); - - const back = () => { - setViewMode(ViewMode.BIO) - !isMute && playSound('backNextButton'); - } + const { setViewMode } = React.useContext(ViewContext); + const back = () => { + setViewMode(ViewMode.BIO) + !isMute && playSound('backNextButton'); + } + const mint = () => { + setViewMode(ViewMode.MINT) + } const next = () => { setViewMode(ViewMode.CHAT) !isMute && playSound('backNextButton'); @@ -45,13 +47,13 @@ function Save() {
- {/* */} + /> Date: Wed, 8 Mar 2023 18:50:02 -0600 Subject: [PATCH 56/79] confix --- src/App.jsx | 2 +- src/pages/Mint.jsx | 47 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 13ce582c..5eaeb5b8 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -288,7 +288,7 @@ export default function App() { ), [ViewMode.CREATE]: , [ViewMode.LOAD]: , - [ViewMode.MINT]: , + [ViewMode.MINT]: , [ViewMode.SAVE]: , [ViewMode.CHAT]: , } diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index d33720ba..fe2b4975 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -1,12 +1,19 @@ import React from "react" import styles from "./Mint.module.scss" import { ViewMode, ViewContext } from "../context/ViewContext" + +import { SceneContext } from "../context/SceneContext" +import * as THREE from 'three' + import CustomButton from "../components/custom-button" import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" +const localVector = new THREE.Vector3(); + function MintComponent({screenshotManager, blinkManager, animationManager}) { + const { templateInfo, model } = React.useContext(SceneContext) const { setViewMode } = React.useContext(ViewContext) const { playSound } = React.useContext(SoundContext) const { isMute } = React.useContext(AudioContext) @@ -30,19 +37,41 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { ) } + function Mint(){ + takeScreenshot(); + } + + function takeScreenshot(){ + animationManager.enableScreenshot(); + blinkManager.enableScreenshot(); + + model.traverse(o => { + if (o.isSkinnedMesh) { + const headBone = o.skeleton.bones.filter(bone => bone.name === 'head')[0]; + headBone.getWorldPosition(localVector); + } + }); + const headPosition = localVector; + + // change it to work from manifest + const female = templateInfo.name === "Drophunter"; + const cameraFov = female ? 0.78 : 0.85; + screenshotManager.setCamera(headPosition, cameraFov); + let imageName = "AvatarImage_" + Date.now() + ".png"; + + const screenshot = screenshotManager.saveAsImage(imageName); + blinkManager.disableScreenshot(); + animationManager.disableScreenshot(); + return screenshot; + } + return (
Mint Your Character
- {/* tcm-screenshot - ///
- ///
- ///
- ///
- /// -======= */} + {/* */} - {/* */} + {/* */}
@@ -54,6 +83,7 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { icon="polygon" text="Open Edition" className={styles.mintButton} + onClick= {Mint} />
@@ -64,6 +94,7 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { icon="tokens" text="Genesis Edition" className={styles.mintButton} + onClick= {Mint} /> (Genesis pass holders only) From bbb9032378ba5c0adc176f010cde4f4c75910ed0 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Thu, 16 Feb 2023 13:56:56 -0600 Subject: [PATCH 57/79] create mint utils file --- src/library/mint-utils.js | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/library/mint-utils.js diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js new file mode 100644 index 00000000..1b5b1dfe --- /dev/null +++ b/src/library/mint-utils.js @@ -0,0 +1,50 @@ + +const pinataApiKey = import.meta.env.VITE_PINATA_API_KEY +const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET + +const mintCost = 0.01 + +const connectWallet = async () => { + if (window.ethereum) { + try { + const chain = await window.ethereum.request({ method: 'eth_chainId' }) + if (parseInt(chain, 16) == parseInt(chainId, 16)) { + const addressArray = await window.ethereum.request({ + method: 'eth_requestAccounts', + }) + return addressArray.length > 0 ? addressArray[0] : "" + } else { + window.ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: chainId }], + }) + const addressArray = await window.ethereum.request({ + method: 'eth_requestAccounts', + }) + return addressArray.length > 0 ? addressArray[0] : "" + } + } catch (err) { + return ""; + } + } else { + return ""; + } + } + + async function saveFileToPinata(fileData, fileName) { + if (!fileData) return console.warn("Error saving to pinata: No file data") + const url = `https://api.pinata.cloud/pinning/pinFileToIPFS` + let data = new FormData() + + data.append("file", fileData, fileName) + let resultOfUpload = await axios.post(url, data, { + maxContentLength: "Infinity", //this is needed to prevent axios from erroring out with large files + maxBodyLength: "Infinity", //this is needed to prevent axios from erroring out with large files + headers: { + "Content-Type": `multipart/form-data; boundary=${data._boundary}`, + pinata_api_key: pinataApiKey, + pinata_secret_api_key: pinataSecretApiKey, + }, + }) + return resultOfUpload.data + } \ No newline at end of file From 6aea51f393f52fd80e38eb18e44a9511956e69ab Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Thu, 16 Feb 2023 17:06:54 -0600 Subject: [PATCH 58/79] wip extract mint logic --- src/library/mint-utils.js | 246 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 237 insertions(+), 9 deletions(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index 1b5b1dfe..e8053a5e 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -1,10 +1,15 @@ +import { BigNumber, ethers } from "ethers" +import { getGLBBlobData } from "../library/download-utils" +import axios from "axios" const pinataApiKey = import.meta.env.VITE_PINATA_API_KEY const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 +const chainId = "0x89"; -const connectWallet = async () => { +// ready to test +async function connectWallet(){ if (window.ethereum) { try { const chain = await window.ethereum.request({ method: 'eth_chainId' }) @@ -29,22 +34,245 @@ const connectWallet = async () => { } else { return ""; } - } +} - async function saveFileToPinata(fileData, fileName) { +// ready to test +async function saveFileToPinata(fileData, fileName) { if (!fileData) return console.warn("Error saving to pinata: No file data") - const url = `https://api.pinata.cloud/pinning/pinFileToIPFS` + const url = `https://api.pinata.cloud/pinning/pinFileToIPFS` let data = new FormData() data.append("file", fileData, fileName) let resultOfUpload = await axios.post(url, data, { - maxContentLength: "Infinity", //this is needed to prevent axios from erroring out with large files - maxBodyLength: "Infinity", //this is needed to prevent axios from erroring out with large files - headers: { + maxContentLength: "Infinity", //this is needed to prevent axios from erroring out with large files + maxBodyLength: "Infinity", //this is needed to prevent axios from erroring out with large files + headers: { "Content-Type": `multipart/form-data; boundary=${data._boundary}`, pinata_api_key: pinataApiKey, pinata_secret_api_key: pinataSecretApiKey, - }, + }, }) return resultOfUpload.data - } \ No newline at end of file +} + +export async function mintAsset(data, screenshot, model, needCheckOT){ + if (!data) + throw new Error("No data was provided") + if (!screenshot) + throw new Error("No screenshot was provided") + if (!model) + throw new Error("No model was provided") + + const walletAddress = connectWallet(); + + const pass = !needCheckOT || await checkOT(walletAddress); + + if (pass){ + console.log("minting") + // set image + let imageName = "AvatarImage_" + Date.now() + ".png"; + let imageHash = await (async() => { + for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + try { + const img_hash = await saveFileToPinata( + screenshot, + imageName + ).catch((reason) => { + console.error(i, "---", reason) + }) + return img_hash + } catch(err) { + console.warn(err); + } + } + throw new Error('failed to upload screenshot'); + }) + + const glb = await getGLBBlobData(model) + if (glb) { + let glbName = "AvatarGlb_" + Date.now() + ".glb"; + let glbHash = await (async() => { + for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + try { + const glb_hash = await saveFileToPinata( + glb, + glbName + ).catch((reason) => { + console.error(i, "---", reason) + console.log(("Couldn't save glb to pinata")) + //setMintStatus("Couldn't save glb to pinata") + }) + return glb_hash + } catch(err) { + console.warn(err); + } + } + console.log(("Couldn't save glb to pinata")) + //setMintStatus("Couldn't save glb to pinata") + throw new Error('failed to upload glb'); + })(); + } else { + throw new Error("Unable to get glb") + } + + + const attributes = getAvatarTraits() + const metadata = { + name: "Avatars", + description: "Character Studio Avatars.", + image: `ipfs://${imageHash.IpfsHash}`, + animation_url: `ipfs://${glbHash.IpfsHash}`, + attributes: attributes + } + const str = JSON.stringify(metadata) + const metaDataHash = await saveFileToPinata( + new Blob([str]), + "AvatarMetadata_" + Date.now() + ".json", + ) + const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` + + + } +} + +const mintAssetPrev = async (avatar) => { + // let walletAddress = await connectWallet() + + // const pass = await checkOT(walletAddress); + const pass = true; + + if(pass) { + // animationManager.enableScreenshot(); + // blinkManager.enableScreenshot(); + // setMintStatus("Uploading...") + // let imageHash, glbHash; + + // avatar.traverse(o => { + // if (o.isSkinnedMesh) { + // const headBone = o.skeleton.bones.filter(bone => bone.name === 'head')[0]; + // headBone.getWorldPosition(localVector); + // } + // }); + // const headPosition = localVector; + // const female = templateInfo.name === "Drophunter"; + // const cameraFov = female ? 0.78 : 0.85; + // screenshotManager.setCamera(headPosition, cameraFov); + // let imageName = "AvatarImage_" + Date.now() + ".png"; + + // const screenshot = screenshotManager.saveAsImage(imageName); + // blinkManager.disableScreenshot(); + // animationManager.disableScreenshot(); + + // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) + if (screenshot) { + let imageName = "AvatarImage_" + Date.now() + ".png"; + imageHash = await (async() => { + for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + try { + const img_hash = await saveFileToPinata( + screenshot, + imageName + ).catch((reason) => { + console.error(i, "---", reason) + }) + return img_hash + } catch(err) { + console.warn(err); + } + } + throw new Error('failed to upload screenshot'); + setMintStatus("Couldn't save screenshot to pinata") + })(); + } else { + throw new Error("Unable to get screenshot") + } + + const glb = await getGLBBlobData(model) + if (glb) { + let glbName = "AvatarGlb_" + Date.now() + ".glb"; + glbHash = await (async() => { + for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason + try { + const glb_hash = await saveFileToPinata( + glb, + glbName + ).catch((reason) => { + console.error(i, "---", reason) + setMintStatus("Couldn't save glb to pinata") + }) + return glb_hash + } catch(err) { + console.warn(err); + } + } + throw new Error('failed to upload glb'); + setMintStatus("Couldn't save glb to pinata") + })(); + } else { + throw new Error("Unable to get glb") + } + + const attributes = getAvatarTraits() + const metadata = { + name: "Avatars", + description: "Character Studio Avatars.", + image: `ipfs://${imageHash.IpfsHash}`, + animation_url: `ipfs://${glbHash.IpfsHash}`, + attributes: attributes + } + const str = JSON.stringify(metadata) + const metaDataHash = await saveFileToPinata( + new Blob([str]), + "AvatarMetadata_" + Date.now() + ".json", + ) + const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` + + setMintStatus("Minting...") + const signer = new ethers.providers.Web3Provider( + window.ethereum, + ).getSigner() + const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) + try { + const options = { + value: tokenPrice, + from: walletAddress + } + const tx = await contract.mintToken(1, metadataIpfs, options) + let res = await tx.wait() + if (res.transactionHash) { + setMintStatus("Mint success!") + } + } catch (err) { + setMintStatus("Public Mint failed! Please check your wallet.") + } + } else { + return; + } +} + +const checkOT = async (address) => { + if(address) { + const address = '0x6e58309CD851A5B124E3A56768a42d12f3B6D104' + const ethersigner = ethers.getDefaultProvider("mainnet", { + alchemy: import.meta.env.VITE_ALCHEMY_API_KEY, + }) + const contract = new ethers.Contract(EternalProxyContract.address, EternalProxyContract.abi, ethersigner); + const webaBalance = await contract.beneficiaryBalanceOf(address, webaverseGenesisAddress, 1); + if(parseInt(webaBalance) > 0) return true; + else { + setMintStatus("Currently in alpha. You need a genesis pass to mint. \n Will be public soon!") + return false; + } + } else { + setMintStatus("Please connect your wallet") + return false; + } +} + +const showTrait = (trait) => { + if (trait.name in avatar) { + if ("traitInfo" in avatar[trait.name]) { + return avatar[trait.name].name + } else return "Default " + trait.name + } else return "No set" +} \ No newline at end of file From 4df5ec1f759151ec4268913a2028ab85ab0649b2 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:50:42 -0600 Subject: [PATCH 59/79] confix --- src/library/mint-utils.js | 188 ++++++++++++-------------------------- src/pages/Mint.jsx | 26 +++++- 2 files changed, 78 insertions(+), 136 deletions(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index e8053a5e..cee49397 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -1,5 +1,6 @@ import { BigNumber, ethers } from "ethers" -import { getGLBBlobData } from "../library/download-utils" +import { getGLBBlobData } from "./download-utils" +import { CharacterContract, EternalProxyContract, webaverseGenesisAddress } from "../components/Contract" import axios from "axios" const pinataApiKey = import.meta.env.VITE_PINATA_API_KEY @@ -7,6 +8,18 @@ const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET const mintCost = 0.01 const chainId = "0x89"; +let tokenPrice; + + +async function getTokenPrice(){ + if (tokenPrice != null) + return tokenPrice + const defaultProvider = new ethers.providers.StaticJsonRpcProvider('https://polygon-rpc.com/') + const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, defaultProvider) + const tp = await contract.tokenPrice() + tokenPrice = BigNumber.from(tp).mul(1); + return tokenPrice +} // ready to test async function connectWallet(){ @@ -55,9 +68,9 @@ async function saveFileToPinata(fileData, fileName) { return resultOfUpload.data } -export async function mintAsset(data, screenshot, model, needCheckOT){ - if (!data) - throw new Error("No data was provided") +export async function mintAsset(attributes, screenshot, model, needCheckOT){ + if (!attributes) + throw new Error("No attributes was provided") if (!screenshot) throw new Error("No screenshot was provided") if (!model) @@ -83,15 +96,18 @@ export async function mintAsset(data, screenshot, model, needCheckOT){ return img_hash } catch(err) { console.warn(err); + return err; } } - throw new Error('failed to upload screenshot'); + return 'failed to upload screenshot'; + //throw new Error('failed to upload screenshot'); }) const glb = await getGLBBlobData(model) + let glbHash; if (glb) { let glbName = "AvatarGlb_" + Date.now() + ".glb"; - let glbHash = await (async() => { + glbHash = await (async() => { for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason try { const glb_hash = await saveFileToPinata( @@ -107,16 +123,18 @@ export async function mintAsset(data, screenshot, model, needCheckOT){ console.warn(err); } } - console.log(("Couldn't save glb to pinata")) + //console.log(("Couldn't save glb to pinata")) //setMintStatus("Couldn't save glb to pinata") - throw new Error('failed to upload glb'); + return 'failed to upload glb' + //throw new Error('failed to upload glb'); })(); } else { - throw new Error("Unable to get glb") + + return 'Unable to get glb' } - - const attributes = getAvatarTraits() + // attributes are noew provided as parameter + // const attributes = getAvatarTraits() const metadata = { name: "Avatars", description: "Character Studio Avatars.", @@ -131,122 +149,28 @@ export async function mintAsset(data, screenshot, model, needCheckOT){ ) const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` + let price = await getTokenPrice() - } -} - -const mintAssetPrev = async (avatar) => { - // let walletAddress = await connectWallet() - - // const pass = await checkOT(walletAddress); - const pass = true; - - if(pass) { - // animationManager.enableScreenshot(); - // blinkManager.enableScreenshot(); - // setMintStatus("Uploading...") - // let imageHash, glbHash; - - // avatar.traverse(o => { - // if (o.isSkinnedMesh) { - // const headBone = o.skeleton.bones.filter(bone => bone.name === 'head')[0]; - // headBone.getWorldPosition(localVector); - // } - // }); - // const headPosition = localVector; - // const female = templateInfo.name === "Drophunter"; - // const cameraFov = female ? 0.78 : 0.85; - // screenshotManager.setCamera(headPosition, cameraFov); - // let imageName = "AvatarImage_" + Date.now() + ".png"; - - // const screenshot = screenshotManager.saveAsImage(imageName); - // blinkManager.disableScreenshot(); - // animationManager.disableScreenshot(); - - // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - if (screenshot) { - let imageName = "AvatarImage_" + Date.now() + ".png"; - imageHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const img_hash = await saveFileToPinata( - screenshot, - imageName - ).catch((reason) => { - console.error(i, "---", reason) - }) - return img_hash - } catch(err) { - console.warn(err); - } + const signer = new ethers.providers.Web3Provider( + window.ethereum, + ).getSigner() + const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) + try { + const options = { + value: price, + from: walletAddress } - throw new Error('failed to upload screenshot'); - setMintStatus("Couldn't save screenshot to pinata") - })(); - } else { - throw new Error("Unable to get screenshot") - } - - const glb = await getGLBBlobData(model) - if (glb) { - let glbName = "AvatarGlb_" + Date.now() + ".glb"; - glbHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const glb_hash = await saveFileToPinata( - glb, - glbName - ).catch((reason) => { - console.error(i, "---", reason) - setMintStatus("Couldn't save glb to pinata") - }) - return glb_hash - } catch(err) { - console.warn(err); - } + const tx = await contract.mintToken(1, metadataIpfs, options) + let res = await tx.wait() + if (res.transactionHash) { + //console.log("Mint success!") + return "Mint success!"; } - throw new Error('failed to upload glb'); - setMintStatus("Couldn't save glb to pinata") - })(); - } else { - throw new Error("Unable to get glb") - } - - const attributes = getAvatarTraits() - const metadata = { - name: "Avatars", - description: "Character Studio Avatars.", - image: `ipfs://${imageHash.IpfsHash}`, - animation_url: `ipfs://${glbHash.IpfsHash}`, - attributes: attributes - } - const str = JSON.stringify(metadata) - const metaDataHash = await saveFileToPinata( - new Blob([str]), - "AvatarMetadata_" + Date.now() + ".json", - ) - const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` - - setMintStatus("Minting...") - const signer = new ethers.providers.Web3Provider( - window.ethereum, - ).getSigner() - const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) - try { - const options = { - value: tokenPrice, - from: walletAddress + } catch (err) { + //console.log("Public Mint failed! Please check your wallet.") + return "Public Mint failed! Please check your wallet." } - const tx = await contract.mintToken(1, metadataIpfs, options) - let res = await tx.wait() - if (res.transactionHash) { - setMintStatus("Mint success!") - } - } catch (err) { - setMintStatus("Public Mint failed! Please check your wallet.") - } - } else { - return; + } } @@ -260,19 +184,19 @@ const checkOT = async (address) => { const webaBalance = await contract.beneficiaryBalanceOf(address, webaverseGenesisAddress, 1); if(parseInt(webaBalance) > 0) return true; else { - setMintStatus("Currently in alpha. You need a genesis pass to mint. \n Will be public soon!") + console.log("Currently in alpha. You need a genesis pass to mint. \n Will be public soon!") return false; } } else { - setMintStatus("Please connect your wallet") + console.log("Please connect your wallet") return false; } } -const showTrait = (trait) => { - if (trait.name in avatar) { - if ("traitInfo" in avatar[trait.name]) { - return avatar[trait.name].name - } else return "Default " + trait.name - } else return "No set" -} \ No newline at end of file +// const showTrait = (trait) => { +// if (trait.name in avatar) { +// if ("traitInfo" in avatar[trait.name]) { +// return avatar[trait.name].name +// } else return "Default " + trait.name +// } else return "No set" +// } \ No newline at end of file diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index fe2b4975..f071ca39 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -8,12 +8,12 @@ import * as THREE from 'three' import CustomButton from "../components/custom-button" import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" - +import { mintAsset } from "../library/mint-utils" const localVector = new THREE.Vector3(); function MintComponent({screenshotManager, blinkManager, animationManager}) { - const { templateInfo, model } = React.useContext(SceneContext) + const { templateInfo, model, avatar } = React.useContext(SceneContext) const { setViewMode } = React.useContext(ViewContext) const { playSound } = React.useContext(SoundContext) const { isMute } = React.useContext(AudioContext) @@ -37,8 +37,26 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { ) } - function Mint(){ - takeScreenshot(); + async function Mint(){ + const screenshot = takeScreenshot(); + console.log(screenshot) + console.log(mintAsset) + const result = await mintAsset(getAvatarTraits(),screenshot,model) + console.log(result); + } + + // + const getAvatarTraits = () => { + let metadataTraits = [] + Object.keys(avatar).map((trait) => { + if (Object.keys(avatar[trait]).length !== 0) { + metadataTraits.push({ + trait_type: trait, + value: avatar[trait].name, + }) + } + }) + return metadataTraits } function takeScreenshot(){ From bcc68f05db60cfbd3f3d88617038622d8b5c379f Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Thu, 16 Feb 2023 19:21:40 -0600 Subject: [PATCH 60/79] fix promise return --- src/library/download-utils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library/download-utils.js b/src/library/download-utils.js index 07e35401..a1cbf1de 100644 --- a/src/library/download-utils.js +++ b/src/library/download-utils.js @@ -69,9 +69,9 @@ function getOptimizedGLB(avatarToDownload, atlasSize, isVrm0 = false){ } export async function getGLBBlobData(avatarToDownload, atlasSize = 4096, optimized = true){ - const model = await optimized ? - getOptimizedGLB(avatarToDownload, atlasSize) : - getUnopotimizedGLB(avatarToDownload) + const model = await (optimized ? + getOptimizedGLB(avatarToDownload, atlasSize) : + getUnopotimizedGLB(avatarToDownload)) const glb = await parseGLB(model); return new Blob([glb], { type: 'model/gltf-binary' }); } From ad988a4076e71b5869aca37942831a422a0664e8 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Thu, 16 Feb 2023 19:44:09 -0600 Subject: [PATCH 61/79] await adress and validate if added --- src/library/mint-utils.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index cee49397..3469cbb8 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -6,7 +6,7 @@ import axios from "axios" const pinataApiKey = import.meta.env.VITE_PINATA_API_KEY const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET -const mintCost = 0.01 +//const mintCost = 0.01 const chainId = "0x89"; let tokenPrice; @@ -76,10 +76,12 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ if (!model) throw new Error("No model was provided") - const walletAddress = connectWallet(); + const walletAddress = await connectWallet(); + if (walletAddress == "") + throw new Error("No adress was connected") const pass = !needCheckOT || await checkOT(walletAddress); - + console.log("debug") if (pass){ console.log("minting") // set image @@ -102,10 +104,12 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ return 'failed to upload screenshot'; //throw new Error('failed to upload screenshot'); }) - + console.log("debug") const glb = await getGLBBlobData(model) + console.log(glb) let glbHash; if (glb) { + console.log("debug") let glbName = "AvatarGlb_" + Date.now() + ".glb"; glbHash = await (async() => { for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason @@ -132,7 +136,7 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ return 'Unable to get glb' } - + console.log("debug") // attributes are noew provided as parameter // const attributes = getAvatarTraits() const metadata = { From 73a2686df54fcd5d91f7a48e7c3bdd56a0f84b8e Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Thu, 16 Feb 2023 19:54:56 -0600 Subject: [PATCH 62/79] test debugs --- src/library/mint-utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index 3469cbb8..3fc60438 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -154,6 +154,7 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` let price = await getTokenPrice() + console.log(price) const signer = new ethers.providers.Web3Provider( window.ethereum, From a0ce2fb889cbba981e058029cedcc094c79bdcc3 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Tue, 21 Feb 2023 13:11:57 -0600 Subject: [PATCH 63/79] remove old mint page --- src/components/Mint.jsx | 295 ---------------------------------------- 1 file changed, 295 deletions(-) delete mode 100644 src/components/Mint.jsx diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx deleted file mode 100644 index e0ed6bb9..00000000 --- a/src/components/Mint.jsx +++ /dev/null @@ -1,295 +0,0 @@ -import * as THREE from 'three'; - -import axios from "axios" -import { BigNumber, ethers } from "ethers" -import React, { Fragment, useContext, useState, useEffect } from "react" -import ethereumIcon from "../../public/ui/mint/ethereum.png" -import mintPopupImage from "../../public/ui/mint/mintPopup.png" -import { AccountContext } from "../context/AccountContext" -import { SceneContext } from "../context/SceneContext" -import { getModelFromScene, getCroppedScreenshot } from "../library/utils" -import { CharacterContract, EternalProxyContract, webaverseGenesisAddress } from "./Contract" -import { getGLBBlobData } from "../library/download-utils" -import styles from "./Mint.module.css" - -const localVector = new THREE.Vector3(); - -const pinataApiKey = import.meta.env.VITE_PINATA_API_KEY -const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET - -const mintCost = 0.01 - -export default function MintPopup({screenshotManager, blinkManager, animationManager}) { - const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) - const [mintStatus, setMintStatus] = useState("") - const [tokenPrice, setTokenPrice] = useState(null); - const chainId = "0x89"; - - useEffect(() => { - ( async () => { - const defaultProvider = new ethers.providers.StaticJsonRpcProvider('https://polygon-rpc.com/') - const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, defaultProvider) - - const tp = await contract.tokenPrice() - setTokenPrice( BigNumber.from(tp).mul(1) ) - })(); - }, []) - - const connectWallet = async () => { - if (window.ethereum) { - try { - const chain = await window.ethereum.request({ method: 'eth_chainId' }) - if (parseInt(chain, 16) == parseInt(chainId, 16)) { - const addressArray = await window.ethereum.request({ - method: 'eth_requestAccounts', - }) - return addressArray.length > 0 ? addressArray[0] : "" - } else { - window.ethereum.request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: chainId }], - }) - const addressArray = await window.ethereum.request({ - method: 'eth_requestAccounts', - }) - return addressArray.length > 0 ? addressArray[0] : "" - } - } catch (err) { - return ""; - } - } else { - return ""; - } - } - - async function saveFileToPinata(fileData, fileName) { - if (!fileData) return console.warn("Error saving to pinata: No file data") - const url = `https://api.pinata.cloud/pinning/pinFileToIPFS` - let data = new FormData() - - data.append("file", fileData, fileName) - let resultOfUpload = await axios.post(url, data, { - maxContentLength: "Infinity", //this is needed to prevent axios from erroring out with large files - maxBodyLength: "Infinity", //this is needed to prevent axios from erroring out with large files - headers: { - "Content-Type": `multipart/form-data; boundary=${data._boundary}`, - pinata_api_key: pinataApiKey, - pinata_secret_api_key: pinataSecretApiKey, - }, - }) - return resultOfUpload.data - } - - const getAvatarTraits = () => { - let metadataTraits = [] - Object.keys(avatar).map((trait) => { - if (Object.keys(avatar[trait]).length !== 0) { - metadataTraits.push({ - trait_type: trait, - value: avatar[trait].name, - }) - } - }) - return metadataTraits - } - - - const mintAsset = async (avatar) => { - // let walletAddress = await connectWallet() - - // const pass = await checkOT(walletAddress); - const pass = true; - - if(pass) { - animationManager.enableScreenshot(); - blinkManager.enableScreenshot(); - setMintStatus("Uploading...") - let imageHash, glbHash; - - avatar.traverse(o => { - if (o.isSkinnedMesh) { - const headBone = o.skeleton.bones.filter(bone => bone.name === 'head')[0]; - headBone.getWorldPosition(localVector); - } - }); - const headPosition = localVector; - const female = templateInfo.name === "Drophunter"; - const cameraFov = female ? 0.78 : 0.85; - screenshotManager.setCamera(headPosition, cameraFov); - let imageName = "AvatarImage_" + Date.now() + ".png"; - - const screenshot = screenshotManager.saveAsImage(imageName); - blinkManager.disableScreenshot(); - animationManager.disableScreenshot(); - - // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - if (screenshot) { - let imageName = "AvatarImage_" + Date.now() + ".png"; - imageHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const img_hash = await saveFileToPinata( - screenshot, - imageName - ).catch((reason) => { - console.error(i, "---", reason) - }) - return img_hash - } catch(err) { - console.warn(err); - } - } - throw new Error('failed to upload screenshot'); - setMintStatus("Couldn't save screenshot to pinata") - })(); - } else { - throw new Error("Unable to get screenshot") - } - - const glb = await getGLBBlobData(model) - if (glb) { - let glbName = "AvatarGlb_" + Date.now() + ".glb"; - glbHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const glb_hash = await saveFileToPinata( - glb, - glbName - ).catch((reason) => { - console.error(i, "---", reason) - setMintStatus("Couldn't save glb to pinata") - }) - return glb_hash - } catch(err) { - console.warn(err); - } - } - throw new Error('failed to upload glb'); - setMintStatus("Couldn't save glb to pinata") - })(); - } else { - throw new Error("Unable to get glb") - } - - const attributes = getAvatarTraits() - const metadata = { - name: "Avatars", - description: "Character Studio Avatars.", - image: `ipfs://${imageHash.IpfsHash}`, - animation_url: `ipfs://${glbHash.IpfsHash}`, - attributes: attributes - } - const str = JSON.stringify(metadata) - const metaDataHash = await saveFileToPinata( - new Blob([str]), - "AvatarMetadata_" + Date.now() + ".json", - ) - const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` - - setMintStatus("Minting...") - const signer = new ethers.providers.Web3Provider( - window.ethereum, - ).getSigner() - const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) - try { - const options = { - value: tokenPrice, - from: walletAddress - } - const tx = await contract.mintToken(1, metadataIpfs, options) - let res = await tx.wait() - if (res.transactionHash) { - setMintStatus("Mint success!") - } - } catch (err) { - setMintStatus("Public Mint failed! Please check your wallet.") - } - } else { - return; - } - } - - // const takeScreenshot = async () => { - // const img = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - // const glb = await getGLBBlobData(model) - // } - - const checkOT = async (address) => { - if(address) { - const address = '0x6e58309CD851A5B124E3A56768a42d12f3B6D104' - const ethersigner = ethers.getDefaultProvider("mainnet", { - alchemy: import.meta.env.VITE_ALCHEMY_API_KEY, - }) - const contract = new ethers.Contract(EternalProxyContract.address, EternalProxyContract.abi, ethersigner); - const webaBalance = await contract.beneficiaryBalanceOf(address, webaverseGenesisAddress, 1); - if(parseInt(webaBalance) > 0) return true; - else { - setMintStatus("Currently in alpha. You need a genesis pass to mint. \n Will be public soon!") - return false; - } - } else { - setMintStatus("Please connect your wallet") - return false; - } - } - - const showTrait = (trait) => { - if (trait.name in avatar) { - if ("traitInfo" in avatar[trait.name]) { - return avatar[trait.name].name - } else return "Default " + trait.name - } else return "No set" - } - - return ( - // currentView.includes("MINT") && ( -
-
- {/* {connected && ( */} - -
- -
Mint Avatar
-
-
- {templateInfo.traits && - templateInfo.traits.map((item, index) => ( -
-
- -
{showTrait(item)}
-
- ))} -
-
-
- {"Mint Price: "} -
-
- -
-  {mintCost} -
-
-
- {mintStatus} -
-
-
mintAsset(model)} - > - Mint -
-
- - {/* )} */} -
-
- // ) - ) -} From 127944433fe177e3f82d954572721a54f2029763 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Tue, 21 Feb 2023 16:50:13 -0600 Subject: [PATCH 64/79] remove consoles --- src/library/mint-utils.js | 12 +----------- src/pages/Mint.jsx | 2 -- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index 3fc60438..6b2f6c6f 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -81,7 +81,6 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ throw new Error("No adress was connected") const pass = !needCheckOT || await checkOT(walletAddress); - console.log("debug") if (pass){ console.log("minting") // set image @@ -104,12 +103,9 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ return 'failed to upload screenshot'; //throw new Error('failed to upload screenshot'); }) - console.log("debug") const glb = await getGLBBlobData(model) - console.log(glb) let glbHash; if (glb) { - console.log("debug") let glbName = "AvatarGlb_" + Date.now() + ".glb"; glbHash = await (async() => { for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason @@ -119,7 +115,7 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ glbName ).catch((reason) => { console.error(i, "---", reason) - console.log(("Couldn't save glb to pinata")) + return "Couldn't save glb to pinata" //setMintStatus("Couldn't save glb to pinata") }) return glb_hash @@ -127,8 +123,6 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ console.warn(err); } } - //console.log(("Couldn't save glb to pinata")) - //setMintStatus("Couldn't save glb to pinata") return 'failed to upload glb' //throw new Error('failed to upload glb'); })(); @@ -136,9 +130,6 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ return 'Unable to get glb' } - console.log("debug") - // attributes are noew provided as parameter - // const attributes = getAvatarTraits() const metadata = { name: "Avatars", description: "Character Studio Avatars.", @@ -154,7 +145,6 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` let price = await getTokenPrice() - console.log(price) const signer = new ethers.providers.Web3Provider( window.ethereum, diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index f071ca39..56bb103b 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -39,8 +39,6 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { async function Mint(){ const screenshot = takeScreenshot(); - console.log(screenshot) - console.log(mintAsset) const result = await mintAsset(getAvatarTraits(),screenshot,model) console.log(result); } From ffe2dad4bec9fdd8629f1b96b5fc3554ad88474d Mon Sep 17 00:00:00 2001 From: blockchainFull2022 Date: Tue, 21 Feb 2023 19:31:04 -0800 Subject: [PATCH 65/79] adding polygon chain --- src/library/mint-utils.js | 60 ++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index 6b2f6c6f..a0d447a6 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -23,16 +23,17 @@ async function getTokenPrice(){ // ready to test async function connectWallet(){ - if (window.ethereum) { - try { - const chain = await window.ethereum.request({ method: 'eth_chainId' }) - if (parseInt(chain, 16) == parseInt(chainId, 16)) { - const addressArray = await window.ethereum.request({ - method: 'eth_requestAccounts', - }) - return addressArray.length > 0 ? addressArray[0] : "" - } else { - window.ethereum.request({ + if (window.ethereum) { + try { + const chain = await window.ethereum.request({ method: 'eth_chainId' }) + if (parseInt(chain, 16) == parseInt(chainId, 16)) { + const addressArray = await window.ethereum.request({ + method: 'eth_requestAccounts', + }) + return addressArray.length > 0 ? addressArray[0] : "" + } else { + try { + await window.ethereum.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: chainId }], }) @@ -40,13 +41,44 @@ async function connectWallet(){ method: 'eth_requestAccounts', }) return addressArray.length > 0 ? addressArray[0] : "" - } - } catch (err) { - return ""; + } catch (err) { + console.log("polygon not find:", err) + // Add Polygon chain to the metamask. + try { + await window.ethereum.request({ + method: 'wallet_addEthereumChain', + params: [ + { + chainId: '0x89', + chainName: 'Polygon Mainnet', + rpcUrls: ['https://polygon-rpc.com'], + nativeCurrency: { + name: "Matic", + symbol: "MATIC", + decimals: 18 + }, + blockExplorerUrls: ['https://polygonscan.com/'] }, + ] + }); + await window.ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: chainId }], + }) + const addressArray = await window.ethereum.request({ + method: 'eth_requestAccounts', + }) + return addressArray.length > 0 ? addressArray[0] : "" + } catch (error) { + console.log("Adding polygon chain failed", error); + } + } } - } else { + } catch (err) { return ""; } + } else { + return ""; + } } // ready to test From 97f61e71a34d9fc3cf6849b8785413e16fd4c4ed Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 22 Feb 2023 21:16:10 -0600 Subject: [PATCH 66/79] fix call fn --- src/library/mint-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index a0d447a6..70548b73 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -134,7 +134,7 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ } return 'failed to upload screenshot'; //throw new Error('failed to upload screenshot'); - }) + })() const glb = await getGLBBlobData(model) let glbHash; if (glb) { From 952c3815d39f18bbb38d9650d865d259901d35b1 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 22 Feb 2023 21:19:42 -0600 Subject: [PATCH 67/79] save with name --- src/library/mint-utils.js | 4 ++-- src/pages/Mint.jsx | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index 70548b73..f2a3e3cc 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -100,7 +100,7 @@ async function saveFileToPinata(fileData, fileName) { return resultOfUpload.data } -export async function mintAsset(attributes, screenshot, model, needCheckOT){ +export async function mintAsset(attributes, screenshot, model, name, needCheckOT){ if (!attributes) throw new Error("No attributes was provided") if (!screenshot) @@ -163,7 +163,7 @@ export async function mintAsset(attributes, screenshot, model, needCheckOT){ return 'Unable to get glb' } const metadata = { - name: "Avatars", + name: name || "Avatars", description: "Character Studio Avatars.", image: `ipfs://${imageHash.IpfsHash}`, animation_url: `ipfs://${glbHash.IpfsHash}`, diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 56bb103b..31d49d51 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -38,8 +38,10 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { } async function Mint(){ + const fullBioStr = localStorage.getItem(`${templateInfo.id}_fulBio`) + const fullBio = JSON.parse(fullBioStr) const screenshot = takeScreenshot(); - const result = await mintAsset(getAvatarTraits(),screenshot,model) + const result = await mintAsset(getAvatarTraits(),screenshot,model, fullBio.name) console.log(result); } From ec961422d437526080f6be6498651e11506985c0 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 22 Feb 2023 21:47:16 -0600 Subject: [PATCH 68/79] remove consoles --- src/library/mint-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index f2a3e3cc..da14f422 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -190,7 +190,7 @@ export async function mintAsset(attributes, screenshot, model, name, needCheckOT const tx = await contract.mintToken(1, metadataIpfs, options) let res = await tx.wait() if (res.transactionHash) { - //console.log("Mint success!") + console.log("Mint success!") return "Mint success!"; } } catch (err) { From af2062dcbcea2d5369b00ce93c785a90cbfedf65 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 22 Feb 2023 22:12:42 -0600 Subject: [PATCH 69/79] save vrm instead of glb --- src/library/mint-utils.js | 25 +++++++++++++++++++------ src/pages/Mint.jsx | 16 +--------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index da14f422..62e38631 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -1,5 +1,5 @@ import { BigNumber, ethers } from "ethers" -import { getGLBBlobData } from "./download-utils" +import { getGLBBlobData, getVRMBlobData } from "./download-utils" import { CharacterContract, EternalProxyContract, webaverseGenesisAddress } from "../components/Contract" import axios from "axios" @@ -100,9 +100,22 @@ async function saveFileToPinata(fileData, fileName) { return resultOfUpload.data } -export async function mintAsset(attributes, screenshot, model, name, needCheckOT){ - if (!attributes) - throw new Error("No attributes was provided") +const getAvatarTraits = (avatar) => { + let metadataTraits = [] + Object.keys(avatar).map((trait) => { + if (Object.keys(avatar[trait]).length !== 0) { + metadataTraits.push({ + trait_type: trait, + value: avatar[trait].name, + }) + } + }) + return metadataTraits +} + +export async function mintAsset(avatar, screenshot, model, name, needCheckOT){ + if (!avatar) + throw new Error("No avatar was provided") if (!screenshot) throw new Error("No screenshot was provided") if (!model) @@ -135,7 +148,7 @@ export async function mintAsset(attributes, screenshot, model, name, needCheckOT return 'failed to upload screenshot'; //throw new Error('failed to upload screenshot'); })() - const glb = await getGLBBlobData(model) + const glb = await getVRMBlobData(model,avatar,4096,true) let glbHash; if (glb) { let glbName = "AvatarGlb_" + Date.now() + ".glb"; @@ -167,7 +180,7 @@ export async function mintAsset(attributes, screenshot, model, name, needCheckOT description: "Character Studio Avatars.", image: `ipfs://${imageHash.IpfsHash}`, animation_url: `ipfs://${glbHash.IpfsHash}`, - attributes: attributes + attributes: getAvatarTraits(avatar) } const str = JSON.stringify(metadata) const metaDataHash = await saveFileToPinata( diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 31d49d51..b084b031 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -41,24 +41,10 @@ function MintComponent({screenshotManager, blinkManager, animationManager}) { const fullBioStr = localStorage.getItem(`${templateInfo.id}_fulBio`) const fullBio = JSON.parse(fullBioStr) const screenshot = takeScreenshot(); - const result = await mintAsset(getAvatarTraits(),screenshot,model, fullBio.name) + const result = await mintAsset(avatar,screenshot,model, fullBio.name) console.log(result); } - // - const getAvatarTraits = () => { - let metadataTraits = [] - Object.keys(avatar).map((trait) => { - if (Object.keys(avatar[trait]).length !== 0) { - metadataTraits.push({ - trait_type: trait, - value: avatar[trait].name, - }) - } - }) - return metadataTraits - } - function takeScreenshot(){ animationManager.enableScreenshot(); blinkManager.enableScreenshot(); From 23a385204af05f43babbd59dc81cb8597ad66a90 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 22 Feb 2023 22:32:35 -0600 Subject: [PATCH 70/79] remove old glb fn call --- src/library/mint-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/mint-utils.js b/src/library/mint-utils.js index 62e38631..686c826c 100644 --- a/src/library/mint-utils.js +++ b/src/library/mint-utils.js @@ -1,5 +1,5 @@ import { BigNumber, ethers } from "ethers" -import { getGLBBlobData, getVRMBlobData } from "./download-utils" +import { getVRMBlobData } from "./download-utils" import { CharacterContract, EternalProxyContract, webaverseGenesisAddress } from "../components/Contract" import axios from "axios" From d384d59d6465ab6c8b58339e90a445e50cc0dc91 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:54:45 -0600 Subject: [PATCH 71/79] confix --- src/pages/Save.jsx | 70 ++++++++++++++++++--------------------- src/pages/Save.module.css | 6 ++-- 2 files changed, 36 insertions(+), 40 deletions(-) diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index a5521afa..bb4b120a 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -9,14 +9,14 @@ import { SoundContext } from "../context/SoundContext" import { AudioContext } from "../context/AudioContext" function Save() { + // Translate hook const { t } = useContext(LanguageContext); const { playSound } = React.useContext(SoundContext) const { isMute } = React.useContext(AudioContext) - - const { setViewMode } = React.useContext(ViewContext); + const back = () => { setViewMode(ViewMode.BIO) !isMute && playSound('backNextButton'); @@ -30,42 +30,36 @@ function Save() { } return ( -
-
{t("pageTitles.saveCharacter")}
-
-
- -
- - - - -
- - - -
-
-
- ); +
+
{t("pageTitles.saveCharacter")}
+
+ + + + + + +
+
+ ) } export default Save diff --git a/src/pages/Save.module.css b/src/pages/Save.module.css index 416fb1d7..bb6f1b66 100644 --- a/src/pages/Save.module.css +++ b/src/pages/Save.module.css @@ -10,6 +10,7 @@ width: 100%; padding: 20px 32px; display: flex; + justify-content: space-between; } .buttonContainer .leftButtonContainer{ @@ -19,8 +20,9 @@ } .buttonContainer .rightButtonContainer{ - margin-left: auto; - display: inline-flex; + margin-left: auto; + margin-right: 0; + order: 5; } .buttonContainer .buttonCenter { From 02f2f4286f888ded086a05d315ee4fc846c0f829 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Fri, 24 Feb 2023 13:48:48 -0600 Subject: [PATCH 72/79] fix css --- src/pages/Save.module.css | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/pages/Save.module.css b/src/pages/Save.module.css index bb6f1b66..fa9073a0 100644 --- a/src/pages/Save.module.css +++ b/src/pages/Save.module.css @@ -1,28 +1,18 @@ -.container{ - height: 100%; - display: flex; - align-items: flex-end; - justify-content: center; -} - .buttonContainer { - z-index: 0; - width: 100%; - padding: 20px 32px; - display: flex; - justify-content: space-between; + position: absolute; + bottom: 20px; + left: 32px; + width: calc(100% - 64px); + width: -webkit-calc(100% - 64px); + text-align: center; } -.buttonContainer .leftButtonContainer{ - margin-right: auto; - display: inline-flex; - +.buttonContainer .buttonLeft { + float: left; } -.buttonContainer .rightButtonContainer{ - margin-left: auto; - margin-right: 0; - order: 5; +.buttonContainer .buttonRight { + float: Right; } .buttonContainer .buttonCenter { From d966492f20f4b3cee4c2907137944cdd50c0f15e Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Wed, 8 Mar 2023 18:57:24 -0600 Subject: [PATCH 73/79] call to action mint --- src/pages/Save.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index bb4b120a..84af281a 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -44,7 +44,7 @@ function Save() { Date: Fri, 10 Mar 2023 12:54:10 -0600 Subject: [PATCH 74/79] fix blob and cleanup --- src/App.jsx | 8 +++++--- src/pages/Mint.jsx | 2 +- src/pages/Save.jsx | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index c365d482..80750dff 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -272,7 +272,7 @@ export default function App() { }) } - const getFaceScreenshot = () => { + const getFaceScreenshot = (width = 256, height = 256, getBlob = false) => { blinkManager.enableScreenshot(); model.traverse(o => { if (o.isSkinnedMesh) { @@ -284,10 +284,12 @@ export default function App() { const female = templateInfo.name === "Drophunter"; const cameraFov = female ? 0.78 : 0.85; screenshotManager.setCamera(headPosition, cameraFov); - let imageName = "AvatarImage_" + Date.now() + ".png"; + //let imageName = "AvatarImage_" + Date.now() + ".png"; //const screenshot = screenshotManager.saveAsImage(imageName); - const screenshot = screenshotManager.getScreenshotTexture(256,256); + const screenshot = getBlob ? + screenshotManager.getScreenshotBlob(width, height): + screenshotManager.getScreenshotTexture(width, height); blinkManager.disableScreenshot(); animationManager.disableScreenshot(); diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index d63fd21e..0f111630 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -34,7 +34,7 @@ function MintComponent({getFaceScreenshot}) { async function Mint(){ const fullBioStr = localStorage.getItem(`${templateInfo.id}_fulBio`) const fullBio = JSON.parse(fullBioStr) - const screenshot = getFaceScreenshot(); + const screenshot = getFaceScreenshot(256,256,true); const result = await mintAsset(avatar,screenshot,model, fullBio.name) console.log(result); } diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index 0578e007..419a0c5a 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -45,7 +45,7 @@ function Save({getFaceScreenshot}) { Date: Fri, 10 Mar 2023 16:08:56 -0600 Subject: [PATCH 75/79] space evenly --- src/pages/Save.jsx | 4 +++- src/pages/Save.module.css | 28 ++++++++++------------------ 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index 419a0c5a..dbfac9a5 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -41,7 +41,9 @@ function Save({getFaceScreenshot}) { className={styles.buttonLeft} onClick={back} /> - + Date: Mon, 13 Mar 2023 12:06:08 -0600 Subject: [PATCH 76/79] disable genesis edition --- src/components/custom-button/CustomButton.module.css | 8 ++++++-- src/components/custom-button/index.jsx | 5 +++-- src/pages/Mint.jsx | 7 ++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/components/custom-button/CustomButton.module.css b/src/components/custom-button/CustomButton.module.css index e8df23e4..49a1af26 100644 --- a/src/components/custom-button/CustomButton.module.css +++ b/src/components/custom-button/CustomButton.module.css @@ -33,6 +33,7 @@ z-index: 1; height: 100%; width: 100%; + } .iconButtonWrap .icon { @@ -133,6 +134,9 @@ text-transform: uppercase !important; line-height: 106%; } +.buttonWrap:disabled .innerWrap{ + color: #7e7e7e; +} .buttonWrap.dark .innerWrap { border: 1px solid #FFFFFF; @@ -143,14 +147,14 @@ padding: 8px 14px 6px 14px !important; } -.buttonWrap:hover .innerWrap { +.buttonWrap:hover:enabled .innerWrap { border: 1px solid #FFC000; font-family: "TTSC-Bold"; background: #FFC000; color: #EFEFEF; } -.buttonWrap:hover .innerWrap * { +.buttonWrap:hover:enabled .innerWrap * { fill: #EFEFEF !important; } diff --git a/src/components/custom-button/index.jsx b/src/components/custom-button/index.jsx index bda4701f..285d1fda 100644 --- a/src/components/custom-button/index.jsx +++ b/src/components/custom-button/index.jsx @@ -123,12 +123,13 @@ export default function CustomButton(props) { className={classnames( className, styles.buttonWrap, - theme && theme === "dark" ? styles.dark : styles.light, + theme && theme === "dark" ? styles.dark : styles.light )} onClick={onClick} onMouseEnter={onMouseEnter} onSubmit={onSubmit} type={type} + disabled = {disabled} >
)} {text && text} diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 0f111630..e8c7c87b 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -67,10 +67,11 @@ function MintComponent({getFaceScreenshot}) { icon="tokens" text="Genesis Edition" className={styles.mintButton} - onClick= {Mint} + disabled = {true} + // onClick= {Mint} /> - - (Genesis pass holders only) + {/* Genesis pass holders only */} + (Coming Soon!)
From d27a03c8062bbf23f457be15ffbe9faf165e8512 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Mon, 13 Mar 2023 12:09:17 -0600 Subject: [PATCH 77/79] clear css active on disabled --- src/components/custom-button/CustomButton.module.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/custom-button/CustomButton.module.css b/src/components/custom-button/CustomButton.module.css index 49a1af26..e9cf1770 100644 --- a/src/components/custom-button/CustomButton.module.css +++ b/src/components/custom-button/CustomButton.module.css @@ -158,13 +158,13 @@ fill: #EFEFEF !important; } -.buttonWrap:active .innerWrap { +.buttonWrap:active:enabled .innerWrap { border: 1px solid #FFC000; font-family: "TTSC-Bold"; background: #000000; color: #FFC000; } -.buttonWrap:active .innerWrap * { +.buttonWrap:active:enabled .innerWrap * { fill: #FFC000 !important; } From 78577ba25408e23d2b4774b40693f8f228cb5cf6 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Mon, 13 Mar 2023 12:57:02 -0600 Subject: [PATCH 78/79] give user feedback and directions of minting --- src/components/Mint.jsx | 295 ------------------------- src/components/custom-button/index.jsx | 2 + src/library/mint-utils.js | 12 +- src/pages/Mint.jsx | 15 +- src/pages/Mint.module.scss | 9 +- 5 files changed, 29 insertions(+), 304 deletions(-) delete mode 100644 src/components/Mint.jsx diff --git a/src/components/Mint.jsx b/src/components/Mint.jsx deleted file mode 100644 index e0ed6bb9..00000000 --- a/src/components/Mint.jsx +++ /dev/null @@ -1,295 +0,0 @@ -import * as THREE from 'three'; - -import axios from "axios" -import { BigNumber, ethers } from "ethers" -import React, { Fragment, useContext, useState, useEffect } from "react" -import ethereumIcon from "../../public/ui/mint/ethereum.png" -import mintPopupImage from "../../public/ui/mint/mintPopup.png" -import { AccountContext } from "../context/AccountContext" -import { SceneContext } from "../context/SceneContext" -import { getModelFromScene, getCroppedScreenshot } from "../library/utils" -import { CharacterContract, EternalProxyContract, webaverseGenesisAddress } from "./Contract" -import { getGLBBlobData } from "../library/download-utils" -import styles from "./Mint.module.css" - -const localVector = new THREE.Vector3(); - -const pinataApiKey = import.meta.env.VITE_PINATA_API_KEY -const pinataSecretApiKey = import.meta.env.VITE_PINATA_API_SECRET - -const mintCost = 0.01 - -export default function MintPopup({screenshotManager, blinkManager, animationManager}) { - const { avatar, skinColor, model, templateInfo } = useContext(SceneContext) - const [mintStatus, setMintStatus] = useState("") - const [tokenPrice, setTokenPrice] = useState(null); - const chainId = "0x89"; - - useEffect(() => { - ( async () => { - const defaultProvider = new ethers.providers.StaticJsonRpcProvider('https://polygon-rpc.com/') - const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, defaultProvider) - - const tp = await contract.tokenPrice() - setTokenPrice( BigNumber.from(tp).mul(1) ) - })(); - }, []) - - const connectWallet = async () => { - if (window.ethereum) { - try { - const chain = await window.ethereum.request({ method: 'eth_chainId' }) - if (parseInt(chain, 16) == parseInt(chainId, 16)) { - const addressArray = await window.ethereum.request({ - method: 'eth_requestAccounts', - }) - return addressArray.length > 0 ? addressArray[0] : "" - } else { - window.ethereum.request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: chainId }], - }) - const addressArray = await window.ethereum.request({ - method: 'eth_requestAccounts', - }) - return addressArray.length > 0 ? addressArray[0] : "" - } - } catch (err) { - return ""; - } - } else { - return ""; - } - } - - async function saveFileToPinata(fileData, fileName) { - if (!fileData) return console.warn("Error saving to pinata: No file data") - const url = `https://api.pinata.cloud/pinning/pinFileToIPFS` - let data = new FormData() - - data.append("file", fileData, fileName) - let resultOfUpload = await axios.post(url, data, { - maxContentLength: "Infinity", //this is needed to prevent axios from erroring out with large files - maxBodyLength: "Infinity", //this is needed to prevent axios from erroring out with large files - headers: { - "Content-Type": `multipart/form-data; boundary=${data._boundary}`, - pinata_api_key: pinataApiKey, - pinata_secret_api_key: pinataSecretApiKey, - }, - }) - return resultOfUpload.data - } - - const getAvatarTraits = () => { - let metadataTraits = [] - Object.keys(avatar).map((trait) => { - if (Object.keys(avatar[trait]).length !== 0) { - metadataTraits.push({ - trait_type: trait, - value: avatar[trait].name, - }) - } - }) - return metadataTraits - } - - - const mintAsset = async (avatar) => { - // let walletAddress = await connectWallet() - - // const pass = await checkOT(walletAddress); - const pass = true; - - if(pass) { - animationManager.enableScreenshot(); - blinkManager.enableScreenshot(); - setMintStatus("Uploading...") - let imageHash, glbHash; - - avatar.traverse(o => { - if (o.isSkinnedMesh) { - const headBone = o.skeleton.bones.filter(bone => bone.name === 'head')[0]; - headBone.getWorldPosition(localVector); - } - }); - const headPosition = localVector; - const female = templateInfo.name === "Drophunter"; - const cameraFov = female ? 0.78 : 0.85; - screenshotManager.setCamera(headPosition, cameraFov); - let imageName = "AvatarImage_" + Date.now() + ".png"; - - const screenshot = screenshotManager.saveAsImage(imageName); - blinkManager.disableScreenshot(); - animationManager.disableScreenshot(); - - // const screenshot = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - if (screenshot) { - let imageName = "AvatarImage_" + Date.now() + ".png"; - imageHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const img_hash = await saveFileToPinata( - screenshot, - imageName - ).catch((reason) => { - console.error(i, "---", reason) - }) - return img_hash - } catch(err) { - console.warn(err); - } - } - throw new Error('failed to upload screenshot'); - setMintStatus("Couldn't save screenshot to pinata") - })(); - } else { - throw new Error("Unable to get screenshot") - } - - const glb = await getGLBBlobData(model) - if (glb) { - let glbName = "AvatarGlb_" + Date.now() + ".glb"; - glbHash = await (async() => { - for (let i = 0; i < 10; i++) { // hack: give it a few tries, sometimes uploading to pinata fail for some reason - try { - const glb_hash = await saveFileToPinata( - glb, - glbName - ).catch((reason) => { - console.error(i, "---", reason) - setMintStatus("Couldn't save glb to pinata") - }) - return glb_hash - } catch(err) { - console.warn(err); - } - } - throw new Error('failed to upload glb'); - setMintStatus("Couldn't save glb to pinata") - })(); - } else { - throw new Error("Unable to get glb") - } - - const attributes = getAvatarTraits() - const metadata = { - name: "Avatars", - description: "Character Studio Avatars.", - image: `ipfs://${imageHash.IpfsHash}`, - animation_url: `ipfs://${glbHash.IpfsHash}`, - attributes: attributes - } - const str = JSON.stringify(metadata) - const metaDataHash = await saveFileToPinata( - new Blob([str]), - "AvatarMetadata_" + Date.now() + ".json", - ) - const metadataIpfs = `ipfs://${metaDataHash.IpfsHash}` - - setMintStatus("Minting...") - const signer = new ethers.providers.Web3Provider( - window.ethereum, - ).getSigner() - const contract = new ethers.Contract(CharacterContract.address, CharacterContract.abi, signer) - try { - const options = { - value: tokenPrice, - from: walletAddress - } - const tx = await contract.mintToken(1, metadataIpfs, options) - let res = await tx.wait() - if (res.transactionHash) { - setMintStatus("Mint success!") - } - } catch (err) { - setMintStatus("Public Mint failed! Please check your wallet.") - } - } else { - return; - } - } - - // const takeScreenshot = async () => { - // const img = await getCroppedScreenshot("editor-scene",screenshotPosition.x, screenshotPosition.y, screenshotPosition.width, screenshotPosition.height, true) - // const glb = await getGLBBlobData(model) - // } - - const checkOT = async (address) => { - if(address) { - const address = '0x6e58309CD851A5B124E3A56768a42d12f3B6D104' - const ethersigner = ethers.getDefaultProvider("mainnet", { - alchemy: import.meta.env.VITE_ALCHEMY_API_KEY, - }) - const contract = new ethers.Contract(EternalProxyContract.address, EternalProxyContract.abi, ethersigner); - const webaBalance = await contract.beneficiaryBalanceOf(address, webaverseGenesisAddress, 1); - if(parseInt(webaBalance) > 0) return true; - else { - setMintStatus("Currently in alpha. You need a genesis pass to mint. \n Will be public soon!") - return false; - } - } else { - setMintStatus("Please connect your wallet") - return false; - } - } - - const showTrait = (trait) => { - if (trait.name in avatar) { - if ("traitInfo" in avatar[trait.name]) { - return avatar[trait.name].name - } else return "Default " + trait.name - } else return "No set" - } - - return ( - // currentView.includes("MINT") && ( -
-
- {/* {connected && ( */} - -
- -
Mint Avatar
-
-
- {templateInfo.traits && - templateInfo.traits.map((item, index) => ( -
-
- -
{showTrait(item)}
-
- ))} -
-
-
- {"Mint Price: "} -
-
- -
-  {mintCost} -
-
-
- {mintStatus} -
-
-
mintAsset(model)} - > - Mint -
-
- - {/* )} */} -
-
- // ) - ) -} diff --git a/src/components/custom-button/index.jsx b/src/components/custom-button/index.jsx index 285d1fda..c16fc3a2 100644 --- a/src/components/custom-button/index.jsx +++ b/src/components/custom-button/index.jsx @@ -26,6 +26,7 @@ export default function CustomButton(props) { onMouseEnter, active, onSubmit, + minWidth, disabled } = props const svgRef = useRef(null) @@ -130,6 +131,7 @@ export default function CustomButton(props) { onSubmit={onSubmit} type={type} disabled = {disabled} + style={{minWidth:minWidth? minWidth + "px":""}} >
{ setViewMode(ViewMode.SAVE) !isMute && playSound('backNextButton'); @@ -32,10 +35,14 @@ function MintComponent({getFaceScreenshot}) { ) } async function Mint(){ + setMinting(true) + setStatus("Please check your wallet") const fullBioStr = localStorage.getItem(`${templateInfo.id}_fulBio`) const fullBio = JSON.parse(fullBioStr) const screenshot = getFaceScreenshot(256,256,true); const result = await mintAsset(avatar,screenshot,model, fullBio.name) + setStatus(result) + setMinting(false) console.log(result); } @@ -54,9 +61,11 @@ function MintComponent({getFaceScreenshot}) { size={16} theme="light" icon="polygon" - text="Open Edition" + text={minting ? "Minting...":"Open Edition"} className={styles.mintButton} + disabled = {minting} onClick= {Mint} + minWidth = {220} />
@@ -68,11 +77,15 @@ function MintComponent({getFaceScreenshot}) { text="Genesis Edition" className={styles.mintButton} disabled = {true} + minWidth = {220} // onClick= {Mint} /> {/* Genesis pass holders only */} (Coming Soon!) +
+ {status} +
diff --git a/src/pages/Mint.module.scss b/src/pages/Mint.module.scss index 91082c81..a2f001e0 100644 --- a/src/pages/Mint.module.scss +++ b/src/pages/Mint.module.scss @@ -55,7 +55,7 @@ width: 100%; display: flex; margin-top: auto; - margin-bottom: auto; + margin-bottom: 15px; align-items: center; flex-direction: column; @@ -65,7 +65,7 @@ .genesisText { opacity: 0.4; - + margin-top: 5px; .required:after { content: "*"; color: red; @@ -93,6 +93,11 @@ } } } +.mintInfo { + height: 15px; + padding-bottom: 25px; + opacity: 0.5; +} .topLine { background: rgb(0, 149, 100); From 6c4f3248ce679cdedb9a81ad85cdff1ac9fb0c20 Mon Sep 17 00:00:00 2001 From: memelotsqui Date: Mon, 13 Mar 2023 13:03:18 -0600 Subject: [PATCH 79/79] add sfx --- src/pages/Mint.jsx | 1 + src/pages/Save.jsx | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/Mint.jsx b/src/pages/Mint.jsx index 62bc8d6b..63814b0d 100644 --- a/src/pages/Mint.jsx +++ b/src/pages/Mint.jsx @@ -35,6 +35,7 @@ function MintComponent({getFaceScreenshot}) { ) } async function Mint(){ + !isMute && playSound('backNextButton'); setMinting(true) setStatus("Please check your wallet") const fullBioStr = localStorage.getItem(`${templateInfo.id}_fulBio`) diff --git a/src/pages/Save.jsx b/src/pages/Save.jsx index dbfac9a5..c3c9bc35 100644 --- a/src/pages/Save.jsx +++ b/src/pages/Save.jsx @@ -19,11 +19,12 @@ function Save({getFaceScreenshot}) { const back = () => { - setViewMode(ViewMode.BIO) - !isMute && playSound('backNextButton'); + setViewMode(ViewMode.BIO) + !isMute && playSound('backNextButton'); } const mint = () => { - setViewMode(ViewMode.MINT) + setViewMode(ViewMode.MINT) + !isMute && playSound('backNextButton'); } const next = () => { setViewMode(ViewMode.CHAT)