From 2f7ca0d2f14d2eefb7d3ec4209529af87419b791 Mon Sep 17 00:00:00 2001 From: John Shaughnessy Date: Mon, 1 Feb 2021 21:21:03 -0800 Subject: [PATCH] Add controls snapshots --- dist/main-50df94adac52a08a7035.js | 2 + dist/main-50df94adac52a08a7035.js.map | 1 + dist/main-94aa61a7cab659448779.js | 2 - dist/main-94aa61a7cab659448779.js.map | 1 - index.html | 2 +- src/constants.js | 4 ++ src/game.js | 77 +++++++++++++++++++++++++-- src/snapshots.js | 44 +++++++++++++++ 8 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 dist/main-50df94adac52a08a7035.js create mode 100644 dist/main-50df94adac52a08a7035.js.map delete mode 100644 dist/main-94aa61a7cab659448779.js delete mode 100644 dist/main-94aa61a7cab659448779.js.map create mode 100644 src/snapshots.js diff --git a/dist/main-50df94adac52a08a7035.js b/dist/main-50df94adac52a08a7035.js new file mode 100644 index 0000000..739c223 --- /dev/null +++ b/dist/main-50df94adac52a08a7035.js @@ -0,0 +1,2 @@ +(()=>{"use strict";var e={498:(e,a,n)=>{var t=n(294),i=n(935),l=n(212),s=n(886),o=n(509);const r="avatarConfigChanged",u="exportAvatar",d="resetView",m="saveView",c="deleteView",p="goNextView",y="goPreviousView";var h=n(47),v=n(895);function k({candidates:e,predicate:a}){if(!e.length)return null;const n=e.shift();return a(n)?n:k({candidates:e=e.concat(n.children),predicate:a})}function N(e,a){return k({candidates:[e],predicate:e=>e.name===a})}function _({candidates:e,predicate:a,results:n=[]}){if(!e.length)return n;const t=e.shift();return a(t)&&n.push(t),_({candidates:e=e.concat(t.children),predicate:a,results:n})}function f(e,a){return _({candidates:[e],predicate:e=>e.type===a})}function g({object3D:e,depth:a=0,callback:n,result:t}){t.push(n(e,a));const i=e.children;for(let e=0;e{if(n){const a=new Blob([e],{type:"application/octet-stream"}),n=document.createElement("a");n.style.display="none",n.href=URL.createObjectURL(a),n.download="custom_avatar.glb",n.click(),n.remove()}else console.log(e)}),{binary:n,animations:t})}}();function z(e,a){const n=[];for(const t of a.animations)-1===e.animations.findIndex((e=>e.name===t.name))&&n.push(t);for(const a of n)e.animations.push(a)}function C(e,{target:a,position:n,zoom:t=1}){e.target.copy(a),e.object.position.copy(n),e.object.zoom=t,e.object.updateProjectionMatrix(),e.dispatchEvent({type:"change"}),e.update()}const B={DOMContentLoaded:!1,shouldResize:!0,didInit:!1,scene:null,camera:null,renderer:null,controls:null,envMap:null,avatarNodes:{},avatarConfig:{},newAvatarConfig:{},shouldApplyNewAvatarConfig:!1,shouldExportAvatar:!1,shouldResetView:!1,shouldSaveView:!1,shouldGoNextView:!1,shouldGoPreviousView:!1,snapshots:[{target:{x:0,y:.5,z:0},position:{x:0,y:.25,z:1.5},zoom:1},{target:{x:.02307116018084527,y:.6334402516427525,z:.022240041940458772},position:{x:.02307116018084527,y:.5176174441028143,z:.7171768871800882},zoom:1},{target:{x:.09387002157314916,y:.546635562471844,z:.08014199094868098},position:{x:-.3879717518873724,y:.4947348350813956,z:.5914999491959408},zoom:1},{target:{x:-.09493661261301585,y:.5639529591055843,z:.1055502022610856},position:{x:-.671104818392942,y:1.0921215489830267,z:-.6936061291504049},zoom:1},{target:{x:-.008422856623338703,y:.4941459483505538,z:.10198716075212154},position:{x:-.011493544628165472,y:.5417760987144405,z:-.9057404120118234},zoom:1},{target:{x:-.008422856623338703,y:.4941459483505538,z:.10198716075212154},position:{x:.9967533644672771,y:.5785843629152699,z:.1188347112272661},zoom:1},{target:{x:.04413113687842558,y:.49809272819211714,z:.06414813223383779},position:{x:.42686384587556403,y:.5905893343933903,z:.6053669965717776},zoom:1},{target:{x:.41859185291264084,y:.31485181426204567,z:-.08600123811976045},position:{x:.6482708508647577,y:.4157154496534844,z:.22650580642214352},zoom:1},{target:{x:.018173720594482693,y:.44480533951578716,z:-.15500048584516604},position:{x:.001957996317477624,y:.8078606430954935,z:.7318399779720074},zoom:1},{target:{x:0,y:.5,z:0},position:{x:0,y:.35779997693088517,z:.8532001384146891},zoom:1}],viewIndex:0};async function A(e,a,n){const t=await b((i=a,i.startsWith("blob")?i:`assets/${i}.glb`));var i;B.avatarConfig[e]===a&&(t.scene.animations=t.animations,n.clear(),n.add(t.scene),t.scene.traverse((e=>{var a,n;n=e=>{e.isMeshStandardMaterial&&(e.envMap=B.envMap,e.needsUpdate=!0)},(a=e).material&&(Array.isArray(a.material)?a.material.forEach(n):n(a.material))})))}window.gameState=B,window.addEventListener("DOMContentLoaded",(()=>{B.DOMContentLoaded=!0})),window.onresize=()=>{B.shouldResize=!0},document.addEventListener(r,(e=>{B.newAvatarConfig=e.detail.avatarConfig,B.shouldApplyNewAvatarConfig=!0})),document.addEventListener(u,(()=>{B.shouldExportAvatar=!0})),document.addEventListener(d,(()=>{B.shouldResetView=!0})),document.addEventListener(m,(()=>{B.shouldSaveView=!0})),document.addEventListener(c,(()=>{B.shouldDeleteView=!0})),document.addEventListener(p,(()=>{B.shouldGoNextView=!0})),document.addEventListener(y,(()=>{B.shouldGoPreviousView=!0})),document.addEventListener("keydown",(e=>{switch(e.key.toLowerCase()){case"s":document.dispatchEvent(new CustomEvent(m));break;case"d":document.dispatchEvent(new CustomEvent(c));break;case"k":document.dispatchEvent(new CustomEvent(y));break;case"j":document.dispatchEvent(new CustomEvent(p))}})),window.requestAnimationFrame((function e(a){if(B.DOMContentLoaded&&!B.didInit&&(B.didInit=!0,function(){l.CtF.enabled=!0;const e=new l.xsS;e.fog=new l.yo9(9145226,.2),e.background=new l.Ilk(9145226),B.scene=e;const a=new l.cPb(75,window.innerWidth/window.innerHeight,.1,1e3);a.position.set(0,.25,1.5),B.camera=a;const n=new l.Mig(16777215,.4);e.add(n);const t=new l.CP7({canvas:document.getElementById("scene"),antialias:!0});B.renderer=t;const i=function(){const e=new v.q;e.scale.setScalar(45e4);const a=e.material.uniforms;a.turbidity.value=10,a.rayleigh.value=3,a.mieCoefficient.value=.005,a.mieDirectionalG.value=.7;const n=Math.PI*(.7-.5),t=2*Math.PI*(.55-.5),i=new l.Pa4;return i.x=Math.cos(t),i.y=Math.sin(t)*Math.sin(n),i.z=Math.sin(t)*Math.cos(n),a.sunPosition.value.copy(i),e}();B.envMap=function(e,a){const n=new l.xsS;n.add(e);const t=new l.anP(a),i=t.fromScene(n);return t.dispose(),n.remove(e),i.texture}(i,t);const o=new l.Kj0(new l.BKK(100,100),new l.Wid);o.position.y=-.2,o.rotation.x=-Math.PI/2,e.add(o);const r=new s.z(a,t.domElement);r.target=new l.Pa4(0,.5,0),r.update(),r.saveState(),B.controls=r,B.avatarGroup=new l.ZAu,e.add(B.avatarGroup)}()),B.didInit){if(B.shouldResize){B.shouldResize=!1;const{renderer:e,camera:a}=B,n=e.domElement.parentNode.clientWidth,t=e.domElement.parentNode.clientHeight;e.setSize(n,t,!1),a.aspect=n/t,a.updateProjectionMatrix()}if(B.shouldApplyNewAvatarConfig){B.shouldApplyNewAvatarConfig=!1;const e=new Set(Object.keys(B.newAvatarConfig).concat(Object.keys(B.avatarConfig)));for(const a of e)B.avatarNodes[a]||(B.avatarNodes[a]=new l.ZAu,B.avatarGroup.add(B.avatarNodes[a])),B.newAvatarConfig[a]!==B.avatarConfig[a]&&(null!==B.newAvatarConfig[a]?A(a,B.newAvatarConfig[a],B.avatarNodes[a]):B.avatarNodes[a].clear(),B.avatarConfig[a]=B.newAvatarConfig[a])}if(B.shouldExportAvatar&&(B.shouldExportAvatar=!1,function(e){const a=function(e){const a=new l.ZAu;a.name="Scene";const n=e.children.map((e=>N(e,"Scene"))).filter((e=>!!e));for(const e of n)z(a,e);const t=e.children.map((e=>N(e,"AvatarRoot"))).filter((e=>!!e)),i=t[0].clone(!1);for(const e of t)i.userData=(s=i.userData,o=e.userData,x(s),x(o),s.gltfExtensions.MOZ_hubs_components&&(s.gltfExtensions.MOZ_hubs_components=Object.assign(s.gltfExtensions.MOZ_hubs_components,o.gltfExtensions.MOZ_hubs_components)),s);var s,o;const r=f(e,"SkinnedMesh").map((e=>e.clone(!1))),u=function(e){const a=new Map;for(const n of e.skeleton.bones){const e=n.clone(!1);a.set(n,e)}return e.skeleton.bones[0].traverse((e=>{if("Bone"!==e.type)return;const n=a.get(e);for(const t of e.children)n.add(a.get(t))})),new l.OdW(e.skeleton.bones.map((e=>a.get(e))))}(r[0]);for(const e of r)e.bind(u);a.add(i),i.add(u.bones[0]);for(const e of r)i.add(e);return a}(e);console.log(w(a)),console.log(a),E(a,{binary:!1,animations:a.animations}),E(a,{binary:!0,animations:a.animations})}(B.avatarGroup)),B.shouldResetView&&(B.shouldResetView=!1,B.controls.reset()),B.shouldSaveView){B.shouldSaveView=!1;const{snapshots:e,controls:a}=B;e.push(function(e){return{target:e.target.clone(),position:e.object.position.clone(),zoom:e.object.zoom}}(a)),B.viewIndex=e.length-1}if(B.shouldDeleteView){B.shouldDeleteView=!1;const{snapshots:e,controls:a}=B;e.length&&B.viewIndex{e(a.target.selectedOptions[0].getAttribute("value"))},value:n||""},a.map(((e,a)=>t.createElement("option",{key:a,value:e.value},e.displayName))))}function P(){const[e,a]=(0,t.useState)(M),n=Object.keys(e);function i(){const a={};for(const t of n){const n=e[t].filter((e=>!e.excludeFromRandomize));if(0===n.length)continue;const i=Math.floor(Math.random()*n.length);a[t]=n[i].value}return a}const l=i(),[s,o]=(0,t.useState)(l);function m(e){o({...s,...e})}return(0,t.useEffect)((()=>{document.dispatchEvent(new CustomEvent(r,{detail:{avatarConfig:s}}))})),t.createElement(t.Fragment,null,n.map((a=>t.createElement("div",{key:a,className:"category"},t.createElement("span",null,a,": "),t.createElement(R,{selected:s[a],onPartSelected:e=>{m({[a]:e})},parts:e[a]})))),t.createElement("button",{onClick:function(){o(i())}},"Randomize avatar"),t.createElement("button",{onClick:function(){document.dispatchEvent(new CustomEvent(u))}},"Export avatar"),t.createElement("button",{onClick:function(){document.dispatchEvent(new CustomEvent(d))}},"Reset camera view"),t.createElement("label",null,"Upload custom part:",t.createElement("input",{onChange:function(n){const t=n.target.files[0],i=t.name,l=i.substring(0,i.indexOf("_"))||"custom",s=i.substring(i.indexOf("_")+1,i.lastIndexOf(".")),o=URL.createObjectURL(t),r={...e};r[l]=r[l]||[{displayName:"none",value:null}],r[l].push({displayName:s,value:o}),a(r),m({[l]:o})},type:"file",id:"input",accept:"model/gltf-binary,.glb"})))}i.render(t.createElement(P,null),document.getElementById("root"))}},a={};function n(t){if(a[t])return a[t].exports;var i=a[t]={exports:{}};return e[t](i,i.exports,n),i.exports}n.m=e,n.x=e=>{},n.d=(e,a)=>{for(var t in a)n.o(a,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},n.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),(()=>{var e={179:0},a=[[498,536]],t=e=>{},i=(i,l)=>{for(var s,o,[r,u,d,m]=l,c=0,p=[];c{}),t}l.forEach(i.bind(null,0)),l.push=i.bind(null,l.push.bind(l));var o=n.x;n.x=()=>(n.x=o||(e=>{}),(t=s)())})(),n.x()})(); +//# sourceMappingURL=main-50df94adac52a08a7035.js.map \ No newline at end of file diff --git a/dist/main-50df94adac52a08a7035.js.map b/dist/main-50df94adac52a08a7035.js.map new file mode 100644 index 0000000..df5e7d5 --- /dev/null +++ b/dist/main-50df94adac52a08a7035.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/constants.js","webpack:///./src/utils.js","webpack:///./src/export.js","webpack:///./src/orbit-controls-utils.js","webpack:///./src/game.js","webpack:///./src/snapshots.js","webpack:///./src/assets.js","webpack:///./src/index.js","webpack:///webpack/bootstrap","webpack:///webpack/runtime/define property getters","webpack:///webpack/runtime/hasOwnProperty shorthand","webpack:///webpack/runtime/jsonp chunk loading","webpack:///webpack/startup"],"names":["findChild","candidates","predicate","length","candidate","shift","concat","children","findChildByName","root","name","o","findChildren","results","push","findChildrenByType","type","traverseWithDepth","object3D","depth","callback","result","i","describe","prefix","indentation","description","JSON","stringify","userData","firstBone","repeat","skeleton","bones","uuid","boneId","describeObject3D","join","loadGLTF","loader","GLTFLoader","url","Promise","resolve","reject","load","gltf","xhr","error","console","log","ensureHubsComponents","gltfExtensions","MOZ_hubs_components","exportGLTF","exporter","GLTFExporter","binary","animations","parse","blob","Blob","el","document","createElement","style","display","href","URL","createObjectURL","download","click","remove","addNonDuplicateAnimationClips","clone","scene","clipsToAdd","clip","findIndex","clonedAnimation","snapTo","controls","target","position","zoom","copy","object","updateProjectionMatrix","dispatchEvent","update","state","DOMContentLoaded","shouldResize","didInit","camera","renderer","envMap","avatarNodes","avatarConfig","newAvatarConfig","shouldApplyNewAvatarConfig","shouldExportAvatar","shouldResetView","shouldSaveView","shouldGoNextView","shouldGoPreviousView","snapshots","x","y","z","viewIndex","async","loadIntoGroup","category","part","group","value","startsWith","clear","add","traverse","obj","fn","material","isMeshStandardMaterial","needsUpdate","Array","isArray","forEach","window","gameState","addEventListener","onresize","constants","e","detail","shouldDeleteView","key","toLowerCase","CustomEvent","requestAnimationFrame","tick","time","THREE","fog","background","innerWidth","innerHeight","set","ambientLight","canvas","getElementById","antialias","sky","Sky","scale","setScalar","uniforms","theta","Math","PI","phi","sun","cos","sin","createSky","skyScene","pmremGenerator","renderTarget","fromScene","dispose","texture","generateEnvironmentMap","floor","rotation","OrbitControls","domElement","saveState","avatarGroup","init","width","parentNode","clientWidth","height","clientHeight","setSize","aspect","categories","Set","Object","keys","avatar","clonedScene","scenes","map","filter","avatarRoots","clonedAvatarRoot","avatarRoot","a","b","assign","clonedSkinnedMeshes","clonedSkeleton","skinnedMesh","boneClones","Map","bone","get","child","cloneSkeleton","bind","cloneIntoAvatar","exportAvatar","reset","createSnapshot","splice","render","AvatarPartSelector","onPartSelected","parts","selected","onChange","selectedOptions","getAttribute","displayName","App","assets","setAssets","useState","initialAssets","generateRandomConfig","newConfig","categoryAssets","excludeFromRandomize","randomIndex","random","initialAvatarConfig","setAvatarConfig","updateAvatarConfig","useEffect","className","selection","onClick","file","files","filename","substring","indexOf","lastIndexOf","id","accept","ReactDOM","__webpack_module_cache__","__webpack_require__","moduleId","exports","module","__webpack_modules__","m","d","definition","defineProperty","enumerable","prop","prototype","hasOwnProperty","call","installedChunks","179","deferredModules","checkDeferredModules","webpackJsonpCallback","parentChunkLoadingFunction","data","chunkId","chunkIds","moreModules","runtime","executeModules","resolves","apply","chunkLoadingGlobal","self","checkDeferredModulesImpl","deferredModule","fulfilled","j","depId","s","startup"],"mappings":"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","file":"main-50df94adac52a08a7035.js","sourcesContent":["export default {\n avatarConfigChanged: \"avatarConfigChanged\",\n exportAvatar: \"exportAvatar\",\n resetView: \"resetView\",\n saveView: \"saveView\",\n deleteView: \"deleteView\",\n goNextView: \"goNextView\",\n goPreviousView: \"goPreviousView\",\n};\n","import * as THREE from \"three\";\nimport { GLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader\";\nimport { Sky } from \"three/examples/jsm/objects/Sky\";\n\nfunction findChild({ candidates, predicate }) {\n if (!candidates.length) {\n return null;\n }\n\n const candidate = candidates.shift();\n if (predicate(candidate)) return candidate;\n\n candidates = candidates.concat(candidate.children);\n return findChild({ candidates, predicate });\n}\n\nexport function findChildByName(root, name) {\n return findChild({\n candidates: [root],\n predicate: (o) => o.name === name,\n });\n}\n\nfunction findChildren({ candidates, predicate, results = [] }) {\n if (!candidates.length) {\n return results;\n }\n\n const candidate = candidates.shift();\n if (predicate(candidate)) {\n results.push(candidate);\n }\n\n candidates = candidates.concat(candidate.children);\n return findChildren({ candidates, predicate, results });\n}\n\nexport function findChildrenByType(root, type) {\n return findChildren({\n candidates: [root],\n predicate: (o) => o.type === type,\n });\n}\n\nfunction traverseWithDepth({ object3D, depth = 0, callback, result }) {\n result.push(callback(object3D, depth));\n const children = object3D.children;\n for (let i = 0; i < children.length; i++) {\n traverseWithDepth({ object3D: children[i], depth: depth + 1, callback, result });\n }\n return result;\n}\n\nconst describe = (function () {\n const prefix = \" \";\n return function describe(object3D, indentation) {\n const description = `${object3D.type} | ${object3D.name} | ${JSON.stringify(object3D.userData)}`;\n let firstBone = \"\";\n if (object3D.type === \"SkinnedMesh\") {\n firstBone = \"\\n\"\n .concat(prefix.repeat(indentation))\n .concat(\"First bone id: \")\n .concat(object3D.skeleton.bones[0].uuid);\n }\n let boneId = \"\";\n if (object3D.type === \"Bone\") {\n boneId = \"\\n\".concat(prefix.repeat(indentation)).concat(\"Bone id: \").concat(object3D.uuid);\n }\n\n return prefix.repeat(indentation).concat(description).concat(firstBone).concat(boneId);\n };\n})();\n\nexport function describeObject3D(root) {\n return traverseWithDepth({ object3D: root, callback: describe, result: [] }).join(\"\\n\");\n}\n\nexport const loadGLTF = (function () {\n const loader = new GLTFLoader();\n return function loadGLTF(url) {\n return new Promise(function (resolve, reject) {\n loader.load(\n url,\n function (gltf) {\n resolve(gltf);\n // gltf.animations; // Array\n // gltf.scene; // THREE.Group\n // gltf.scenes; // Array\n // gltf.cameras; // Array\n // gltf.asset; // Object\n },\n function (xhr) {\n // console.log((xhr.loaded / xhr.total) * 100 + \"% loaded\");\n },\n function (error) {\n console.log(\"An error happened\");\n reject(error);\n }\n );\n });\n };\n})();\n\nexport function forEachMaterial(object3D, fn) {\n if (!object3D.material) return;\n\n if (Array.isArray(object3D.material)) {\n object3D.material.forEach(fn);\n } else {\n fn(object3D.material);\n }\n}\n\nexport function generateEnvironmentMap(sky, renderer) {\n const skyScene = new THREE.Scene();\n skyScene.add(sky);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const renderTarget = pmremGenerator.fromScene(skyScene);\n pmremGenerator.dispose();\n\n skyScene.remove(sky);\n\n return renderTarget.texture;\n}\n\nexport function createSky() {\n const sky = new Sky();\n sky.scale.setScalar(450000);\n\n const uniforms = sky.material.uniforms;\n uniforms[\"turbidity\"].value = 10;\n uniforms[\"rayleigh\"].value = 3;\n uniforms[\"mieCoefficient\"].value = 0.005;\n uniforms[\"mieDirectionalG\"].value = 0.7;\n\n const inclination = 0.70;\n const azimuth = 0.55;\n const theta = Math.PI * (inclination - 0.5);\n const phi = 2 * Math.PI * (azimuth - 0.5);\n\n const sun = new THREE.Vector3();\n sun.x = Math.cos(phi);\n sun.y = Math.sin(phi) * Math.sin(theta);\n sun.z = Math.sin(phi) * Math.cos(theta);\n\n uniforms[\"sunPosition\"].value.copy(sun);\n\n return sky;\n}\n","import * as THREE from \"three\";\nimport { GLTFExporter } from \"three/examples/jsm/exporters/GLTFExporter\";\nimport { findChildrenByType, findChildByName, describeObject3D } from \"./utils\";\n\nfunction cloneSkeleton(skinnedMesh) {\n const boneClones = new Map();\n\n for (const bone of skinnedMesh.skeleton.bones) {\n const clone = bone.clone(false);\n boneClones.set(bone, clone);\n }\n\n // Preserve original bone structure\n // Assume bones[0] is root bone\n skinnedMesh.skeleton.bones[0].traverse((o) => {\n if (o.type !== \"Bone\") return;\n const clone = boneClones.get(o);\n for (const child of o.children) {\n clone.add(boneClones.get(child));\n }\n });\n\n return new THREE.Skeleton(skinnedMesh.skeleton.bones.map((b) => boneClones.get(b)));\n}\n\nfunction ensureHubsComponents(userData) {\n if (!userData.gltfExtensions) {\n userData.gltfExtensions = {};\n }\n if (!userData.gltfExtensions.MOZ_hubs_components) {\n userData.gltfExtensions.MOZ_hubs_components = {};\n }\n return userData;\n}\n\nexport function combineHubsComponents(a, b) {\n ensureHubsComponents(a);\n ensureHubsComponents(b);\n if (a.gltfExtensions.MOZ_hubs_components)\n // TODO: Deep merge\n a.gltfExtensions.MOZ_hubs_components = Object.assign(\n a.gltfExtensions.MOZ_hubs_components,\n b.gltfExtensions.MOZ_hubs_components\n );\n\n return a;\n}\n\nexport const exportGLTF = (function () {\n const exporter = new GLTFExporter();\n return function exportGLTF(object3D, { binary, animations }) {\n exporter.parse(\n object3D,\n (gltf) => {\n if (binary) {\n const blob = new Blob([gltf], { type: \"application/octet-stream\" });\n const el = document.createElement(\"a\");\n el.style.display = \"none\";\n el.href = URL.createObjectURL(blob);\n el.download = \"custom_avatar.glb\";\n el.click();\n el.remove();\n } else {\n console.log(gltf);\n }\n },\n { binary, animations }\n );\n };\n})();\n\nfunction addNonDuplicateAnimationClips(clone, scene) {\n const clipsToAdd = [];\n\n for (const clip of scene.animations) {\n const index = clone.animations.findIndex((clonedAnimation) => {\n return clonedAnimation.name === clip.name;\n });\n if (index === -1) {\n clipsToAdd.push(clip);\n }\n }\n\n for (const clip of clipsToAdd) {\n clone.animations.push(clip);\n }\n}\n\nfunction cloneIntoAvatar(avatarGroup) {\n const clonedScene = new THREE.Group();\n clonedScene.name = \"Scene\";\n\n // Combine the root \"Scene\" nodes\n const scenes = avatarGroup.children\n .map((o) => {\n return findChildByName(o, \"Scene\");\n })\n .filter((o) => !!o);\n for (const scene of scenes) {\n addNonDuplicateAnimationClips(clonedScene, scene);\n }\n\n // Combine the \"AvatarRoot\" nodes\n const avatarRoots = avatarGroup.children\n .map((o) => {\n return findChildByName(o, \"AvatarRoot\");\n })\n .filter((o) => !!o);\n const clonedAvatarRoot = avatarRoots[0].clone(false);\n for (const avatarRoot of avatarRoots) {\n clonedAvatarRoot.userData = combineHubsComponents(clonedAvatarRoot.userData, avatarRoot.userData);\n }\n\n // Clone skinned meshes, bind them to a new skeleton\n const clonedSkinnedMeshes = findChildrenByType(avatarGroup, \"SkinnedMesh\").map((o) => {\n return o.clone(false);\n });\n const clonedSkeleton = cloneSkeleton(clonedSkinnedMeshes[0]);\n for (const skinnedMesh of clonedSkinnedMeshes) {\n skinnedMesh.bind(clonedSkeleton);\n }\n\n // Combine clones\n clonedScene.add(clonedAvatarRoot);\n clonedAvatarRoot.add(clonedSkeleton.bones[0]); // Assume bones[0] is root bone\n for (const skinnedMesh of clonedSkinnedMeshes) {\n clonedAvatarRoot.add(skinnedMesh);\n }\n return clonedScene;\n}\n\nexport function exportAvatar(avatarGroup) {\n const avatar = cloneIntoAvatar(avatarGroup);\n console.log(describeObject3D(avatar));\n console.log(avatar);\n exportGLTF(avatar, { binary: false, animations: avatar.animations });\n exportGLTF(avatar, { binary: true, animations: avatar.animations });\n}\n","// Helper function that I wish was on OrbitControls\nexport function createSnapshot(controls) {\n return {\n target: controls.target.clone(),\n position: controls.object.position.clone(),\n zoom: controls.object.zoom,\n };\n}\n\n// Helper function that I wish was on OrbitControls\nexport function snapTo(controls, { target, position, zoom = 1 }) {\n controls.target.copy(target);\n controls.object.position.copy(position);\n controls.object.zoom = zoom;\n\n controls.object.updateProjectionMatrix();\n controls.dispatchEvent({ type: \"change\" });\n\n controls.update();\n}\n","import * as THREE from \"three\";\nimport { OrbitControls } from \"three/examples/jsm/controls/OrbitControls\";\nimport { GLTFExporter } from \"three/examples/jsm/exporters/GLTFExporter\";\nimport constants from \"./constants\";\nimport { exportAvatar } from \"./export\";\nimport { loadGLTF, forEachMaterial, generateEnvironmentMap, createSky } from \"./utils\";\nimport { createSnapshot, snapTo } from \"./orbit-controls-utils\";\nimport initialSnapshots from \"./snapshots\";\n\n// TODO: Don't do this\nfunction urlFor(value) {\n if (value.startsWith(\"blob\")) {\n return value;\n } else {\n return `assets/${value}.glb`;\n }\n}\n\nconst state = {\n DOMContentLoaded: false,\n shouldResize: true,\n didInit: false,\n scene: null,\n camera: null,\n renderer: null,\n controls: null,\n envMap: null,\n avatarNodes: {},\n avatarConfig: {},\n newAvatarConfig: {},\n shouldApplyNewAvatarConfig: false,\n shouldExportAvatar: false,\n shouldResetView: false,\n shouldSaveView: false,\n shouldGoNextView: false,\n shouldGoPreviousView: false,\n snapshots: initialSnapshots,\n viewIndex: 0,\n};\nwindow.gameState = state;\n\nwindow.addEventListener(\"DOMContentLoaded\", () => {\n state.DOMContentLoaded = true;\n});\nwindow.onresize = () => {\n state.shouldResize = true;\n};\ndocument.addEventListener(constants.avatarConfigChanged, (e) => {\n state.newAvatarConfig = e.detail.avatarConfig;\n state.shouldApplyNewAvatarConfig = true;\n});\ndocument.addEventListener(constants.exportAvatar, () => {\n state.shouldExportAvatar = true;\n});\ndocument.addEventListener(constants.resetView, () => {\n state.shouldResetView = true;\n});\ndocument.addEventListener(constants.saveView, () => {\n state.shouldSaveView = true;\n});\ndocument.addEventListener(constants.deleteView, () => {\n state.shouldDeleteView = true;\n});\ndocument.addEventListener(constants.goNextView, () => {\n state.shouldGoNextView = true;\n});\ndocument.addEventListener(constants.goPreviousView, () => {\n state.shouldGoPreviousView = true;\n});\ndocument.addEventListener(\"keydown\", (e) => {\n switch (e.key.toLowerCase()) {\n case \"s\":\n document.dispatchEvent(new CustomEvent(constants.saveView));\n break;\n case \"d\":\n document.dispatchEvent(new CustomEvent(constants.deleteView));\n break;\n case \"k\":\n document.dispatchEvent(new CustomEvent(constants.goPreviousView));\n break;\n case \"j\":\n document.dispatchEvent(new CustomEvent(constants.goNextView));\n break;\n }\n});\n\nfunction resetView() {\n state.controls.reset();\n}\n\nfunction init() {\n THREE.Cache.enabled = true;\n\n const scene = new THREE.Scene();\n scene.fog = new THREE.FogExp2(0x8b8b8a, 0.2);\n scene.background = new THREE.Color(0x8b8b8a);\n state.scene = scene;\n\n const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);\n camera.position.set(0, 0.25, 1.5);\n state.camera = camera;\n\n const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);\n scene.add(ambientLight);\n\n // TODO: Square this with react\n const renderer = new THREE.WebGLRenderer({ canvas: document.getElementById(\"scene\"), antialias: true });\n state.renderer = renderer;\n\n const sky = createSky();\n state.envMap = generateEnvironmentMap(sky, renderer);\n\n const floor = new THREE.Mesh(new THREE.PlaneBufferGeometry(100, 100), new THREE.MeshStandardMaterial());\n floor.position.y = -0.2;\n floor.rotation.x = -Math.PI / 2;\n scene.add(floor);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.target = new THREE.Vector3(0, 0.5, 0);\n controls.update();\n controls.saveState();\n state.controls = controls;\n\n state.avatarGroup = new THREE.Group();\n scene.add(state.avatarGroup);\n}\n\nasync function loadIntoGroup(category, part, group) {\n const gltf = await loadGLTF(urlFor(part));\n if (state.avatarConfig[category] !== part) return;\n\n // TODO: Multiple of these might be in flight at any given time.\n gltf.scene.animations = gltf.animations;\n group.clear();\n group.add(gltf.scene);\n\n gltf.scene.traverse((obj) => {\n forEachMaterial(obj, (material) => {\n if (material.isMeshStandardMaterial) {\n material.envMap = state.envMap;\n material.needsUpdate = true;\n }\n });\n });\n}\n\nfunction tick(time) {\n {\n if (state.DOMContentLoaded && !state.didInit) {\n state.didInit = true;\n init();\n }\n if (!state.didInit) {\n requestAnimationFrame(tick);\n return;\n }\n }\n\n {\n if (state.shouldResize) {\n state.shouldResize = false;\n const { renderer, camera } = state;\n\n const width = renderer.domElement.parentNode.clientWidth;\n const height = renderer.domElement.parentNode.clientHeight;\n renderer.setSize(width, height, false);\n camera.aspect = width / height;\n camera.updateProjectionMatrix();\n }\n }\n\n {\n if (state.shouldApplyNewAvatarConfig) {\n state.shouldApplyNewAvatarConfig = false;\n\n const categories = new Set(Object.keys(state.newAvatarConfig).concat(Object.keys(state.avatarConfig)));\n\n for (const category of categories) {\n if (!state.avatarNodes[category]) {\n state.avatarNodes[category] = new THREE.Group();\n state.avatarGroup.add(state.avatarNodes[category]);\n }\n\n if (state.newAvatarConfig[category] !== state.avatarConfig[category]) {\n if (state.newAvatarConfig[category] !== null) {\n loadIntoGroup(category, state.newAvatarConfig[category], state.avatarNodes[category]);\n } else {\n state.avatarNodes[category].clear();\n }\n state.avatarConfig[category] = state.newAvatarConfig[category];\n }\n }\n }\n }\n\n {\n if (state.shouldExportAvatar) {\n state.shouldExportAvatar = false;\n exportAvatar(state.avatarGroup);\n }\n }\n\n {\n if (state.shouldResetView) {\n state.shouldResetView = false;\n resetView();\n }\n }\n\n if (state.shouldSaveView) {\n state.shouldSaveView = false;\n const { snapshots, controls } = state;\n snapshots.push(createSnapshot(controls));\n state.viewIndex = snapshots.length - 1;\n }\n if (state.shouldDeleteView) {\n state.shouldDeleteView = false;\n const { snapshots, controls } = state;\n if (snapshots.length && state.viewIndex < snapshots.length) {\n snapshots.splice(state.viewIndex, 1);\n state.shouldGoPreviousView = true;\n }\n }\n\n if (state.shouldGoNextView) {\n state.shouldGoNextView = false;\n const { snapshots, controls } = state;\n if (snapshots.length) {\n state.viewIndex = (state.viewIndex + 1) % snapshots.length;\n snapTo(controls, snapshots[state.viewIndex]);\n }\n }\n if (state.shouldGoPreviousView) {\n state.shouldGoPreviousView = false;\n const { snapshots, controls } = state;\n if (snapshots.length) {\n state.viewIndex = (state.viewIndex + snapshots.length - 1) % snapshots.length;\n snapTo(controls, snapshots[state.viewIndex]);\n }\n }\n\n {\n const { renderer, scene, camera } = state;\n renderer.render(scene, camera);\n }\n\n {\n window.requestAnimationFrame(tick);\n }\n}\n\nwindow.requestAnimationFrame(tick);\n","export default [\n { target: { x: 0, y: 0.5, z: 0 }, position: { x: 0, y: 0.25, z: 1.5 }, zoom: 1 },\n {\n target: { x: 0.02307116018084527, y: 0.6334402516427525, z: 0.022240041940458772 },\n position: { x: 0.02307116018084527, y: 0.5176174441028143, z: 0.7171768871800882 },\n zoom: 1,\n },\n {\n target: { x: 0.09387002157314916, y: 0.546635562471844, z: 0.08014199094868098 },\n position: { x: -0.3879717518873724, y: 0.4947348350813956, z: 0.5914999491959408 },\n zoom: 1,\n },\n {\n target: { x: -0.09493661261301585, y: 0.5639529591055843, z: 0.1055502022610856 },\n position: { x: -0.671104818392942, y: 1.0921215489830267, z: -0.6936061291504049 },\n zoom: 1,\n },\n {\n target: { x: -0.008422856623338703, y: 0.4941459483505538, z: 0.10198716075212154 },\n position: { x: -0.011493544628165472, y: 0.5417760987144405, z: -0.9057404120118234 },\n zoom: 1,\n },\n {\n target: { x: -0.008422856623338703, y: 0.4941459483505538, z: 0.10198716075212154 },\n position: { x: 0.9967533644672771, y: 0.5785843629152699, z: 0.1188347112272661 },\n zoom: 1,\n },\n {\n target: { x: 0.04413113687842558, y: 0.49809272819211714, z: 0.06414813223383779 },\n position: { x: 0.42686384587556403, y: 0.5905893343933903, z: 0.6053669965717776 },\n zoom: 1,\n },\n {\n target: { x: 0.41859185291264084, y: 0.31485181426204567, z: -0.08600123811976045 },\n position: { x: 0.6482708508647577, y: 0.4157154496534844, z: 0.22650580642214352 },\n zoom: 1,\n },\n {\n target: { x: 0.018173720594482693, y: 0.44480533951578716, z: -0.15500048584516604 },\n position: { x: 0.001957996317477624, y: 0.8078606430954935, z: 0.7318399779720074 },\n zoom: 1,\n },\n { target: { x: 0, y: 0.5, z: 0 }, position: { x: 0, y: 0.35779997693088517, z: 0.8532001384146891 }, zoom: 1 },\n];\n","export default {\n \"Accessory\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"accessory_duck-floaty\",\n \"displayName\": \"Duck Floaty\"\n },\n {\n \"value\": \"accessory_face-mask-1-animated\",\n \"displayName\": \"Face Mask 1 Animated\"\n },\n {\n \"value\": \"accessory_headband-cat-ears-1\",\n \"displayName\": \"Headband Cat Ears 1\"\n },\n {\n \"value\": \"accessory_headphones-1-black\",\n \"displayName\": \"Headphones 1 Black\"\n },\n {\n \"value\": \"accessory_pool-mask-1\",\n \"displayName\": \"Pool Mask 1\"\n }\n ],\n \"Earring\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"earring_hoop-high-left-silver\",\n \"displayName\": \"Hoop High Left Silver\"\n },\n {\n \"value\": \"earring_hoop-high-right-silver\",\n \"displayName\": \"Hoop High Right Silver\"\n },\n {\n \"value\": \"earring_hoop-large-both-gold\",\n \"displayName\": \"Hoop Large Both Gold\"\n },\n {\n \"value\": \"earring_hoop-small-both-gold\",\n \"displayName\": \"Hoop Small Both Gold\"\n }\n ],\n \"Eyebrows\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"eyebrows_brown\",\n \"displayName\": \"Brown\"\n }\n ],\n \"Eyes\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"eyes_style-1-blue\",\n \"displayName\": \"Style 1 Blue\"\n },\n {\n \"value\": \"eyes_style-1-brown\",\n \"displayName\": \"Style 1 Brown\"\n },\n {\n \"value\": \"eyes_style-11-blue\",\n \"displayName\": \"Style 11 Blue\"\n },\n {\n \"value\": \"eyes_style-11-brown\",\n \"displayName\": \"Style 11 Brown\"\n },\n {\n \"value\": \"eyes_style-12-blue\",\n \"displayName\": \"Style 12 Blue\"\n },\n {\n \"value\": \"eyes_style-12-brown\",\n \"displayName\": \"Style 12 Brown\"\n },\n {\n \"value\": \"eyes_style-12-green\",\n \"displayName\": \"Style 12 Green\"\n },\n {\n \"value\": \"eyes_style-13-blue\",\n \"displayName\": \"Style 13 Blue\"\n },\n {\n \"value\": \"eyes_style-13-brown\",\n \"displayName\": \"Style 13 Brown\"\n },\n {\n \"value\": \"eyes_style-14-blue\",\n \"displayName\": \"Style 14 Blue\"\n },\n {\n \"value\": \"eyes_style-14-brown\",\n \"displayName\": \"Style 14 Brown\"\n }\n ],\n \"Eyewear\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"eyewear_arnette\",\n \"displayName\": \"Arnette\"\n },\n {\n \"value\": \"eyewear_aviators1\",\n \"displayName\": \"Aviators1\"\n },\n {\n \"value\": \"eyewear_glam-2\",\n \"displayName\": \"Glam 2\"\n },\n {\n \"value\": \"eyewear_heart-1-pink\",\n \"displayName\": \"Heart 1 Pink\"\n },\n {\n \"value\": \"eyewear_metal-1\",\n \"displayName\": \"Metal 1\"\n },\n {\n \"value\": \"eyewear_oakleys-red\",\n \"displayName\": \"Oakleys Red\"\n },\n {\n \"value\": \"eyewear_punk-2\",\n \"displayName\": \"Punk 2\"\n },\n {\n \"value\": \"eyewear_wire-frame-1-gold\",\n \"displayName\": \"Wire Frame 1 Gold\"\n }\n ],\n \"Facial Hair\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"facial-hair_beard-full-1-dark\",\n \"displayName\": \"Beard Full 1 Dark\"\n },\n {\n \"value\": \"facial-hair_beard-full-2-brown\",\n \"displayName\": \"Beard Full 2 Brown\"\n },\n {\n \"value\": \"facial-hair_goatee-1-brown\",\n \"displayName\": \"Goatee 1 Brown\"\n },\n {\n \"value\": \"facial-hair_goatee-2\",\n \"displayName\": \"Goatee 2\"\n },\n {\n \"value\": \"facial-hair_goatee-3\",\n \"displayName\": \"Goatee 3\"\n },\n {\n \"value\": \"facial-hair_goatee-4\",\n \"displayName\": \"Goatee 4\"\n },\n {\n \"value\": \"facial-hair_goatee-5\",\n \"displayName\": \"Goatee 5\"\n },\n {\n \"value\": \"facial-hair_mustache-1\",\n \"displayName\": \"Mustache 1\"\n },\n {\n \"value\": \"facial-hair_mustache-2\",\n \"displayName\": \"Mustache 2\"\n }\n ],\n \"Hair\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"hair_aLine-asym\",\n \"displayName\": \"ALine Asym\"\n },\n {\n \"value\": \"hair_afro-1\",\n \"displayName\": \"Afro 1\"\n },\n {\n \"value\": \"hair_afro-2\",\n \"displayName\": \"Afro 2\"\n },\n {\n \"value\": \"hair_bob-1-dark\",\n \"displayName\": \"Bob 1 Dark\"\n },\n {\n \"value\": \"hair_bob-1-light\",\n \"displayName\": \"Bob 1 Light\"\n },\n {\n \"value\": \"hair_bob-1-red\",\n \"displayName\": \"Bob 1 Red\"\n },\n {\n \"value\": \"hair_braided-bun\",\n \"displayName\": \"Braided Bun\"\n },\n {\n \"value\": \"hair_eraser-top\",\n \"displayName\": \"Eraser Top\"\n },\n {\n \"value\": \"hair_fauxhawk-1\",\n \"displayName\": \"Fauxhawk 1\"\n },\n {\n \"value\": \"hair_flat-top-1\",\n \"displayName\": \"Flat Top 1\"\n },\n {\n \"value\": \"hair_french-braid-buns\",\n \"displayName\": \"French Braid Buns\"\n },\n {\n \"value\": \"hair_french-braids-double\",\n \"displayName\": \"French Braids Double\"\n },\n {\n \"value\": \"hair_male_taperAfro1\",\n \"displayName\": \"Male\"\n },\n {\n \"value\": \"hair_mohawk-1-blue\",\n \"displayName\": \"Mohawk 1 Blue\"\n },\n {\n \"value\": \"hair_mullet-1-dark\",\n \"displayName\": \"Mullet 1 Dark\"\n },\n {\n \"value\": \"hair_parted-1-brown\",\n \"displayName\": \"Parted 1 Brown\"\n },\n {\n \"value\": \"hair_parted-1-gray\",\n \"displayName\": \"Parted 1 Gray\"\n },\n {\n \"value\": \"hair_parted-long-1\",\n \"displayName\": \"Parted Long 1\"\n },\n {\n \"value\": \"hair_pigtails-1-blue\",\n \"displayName\": \"Pigtails 1 Blue\"\n },\n {\n \"value\": \"hair_pigtails-1-pink\",\n \"displayName\": \"Pigtails 1 Pink\"\n },\n {\n \"value\": \"hair_pony-tail-1\",\n \"displayName\": \"Pony Tail 1\"\n },\n {\n \"value\": \"hair_pony-tail-2\",\n \"displayName\": \"Pony Tail 2\"\n },\n {\n \"value\": \"hair_pony-tail-3\",\n \"displayName\": \"Pony Tail 3\"\n },\n {\n \"value\": \"hair_spikey-1\",\n \"displayName\": \"Spikey 1\"\n },\n {\n \"value\": \"hair_starter-locs-red\",\n \"displayName\": \"Starter Locs Red\"\n }\n ],\n \"Hands\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"hands_skin-1\",\n \"displayName\": \"Skin 1\"\n },\n {\n \"value\": \"hands_skin-2\",\n \"displayName\": \"Skin 2\"\n },\n {\n \"value\": \"hands_skin-3\",\n \"displayName\": \"Skin 3\"\n },\n {\n \"value\": \"hands_skin-4\",\n \"displayName\": \"Skin 4\"\n },\n {\n \"value\": \"hands_skin-5\",\n \"displayName\": \"Skin 5\"\n },\n {\n \"value\": \"hands_skin-6\",\n \"displayName\": \"Skin 6\"\n },\n {\n \"value\": \"hands_skin-7\",\n \"displayName\": \"Skin 7\"\n },\n {\n \"value\": \"hands_skin-8\",\n \"displayName\": \"Skin 8\"\n },\n {\n \"value\": \"hands_skin-a\",\n \"displayName\": \"Skin A\"\n },\n {\n \"value\": \"hands_skin-b\",\n \"displayName\": \"Skin B\"\n },\n {\n \"value\": \"hands_skin-c\",\n \"displayName\": \"Skin C\"\n },\n {\n \"value\": \"hands_skin-d\",\n \"displayName\": \"Skin D\"\n },\n {\n \"value\": \"hands_skin-e\",\n \"displayName\": \"Skin E\"\n },\n {\n \"value\": \"hands_skin-f\",\n \"displayName\": \"Skin F\"\n },\n {\n \"value\": \"hands_skin-g\",\n \"displayName\": \"Skin G\"\n },\n {\n \"value\": \"hands_skin-h\",\n \"displayName\": \"Skin H\"\n }\n ],\n \"Hat\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"hat_baseball-giants\",\n \"displayName\": \"Baseball Giants\"\n },\n {\n \"value\": \"hat_beach-umbrella\",\n \"displayName\": \"Beach Umbrella\"\n },\n {\n \"value\": \"hat_beanie-1-red\",\n \"displayName\": \"Beanie 1 Red\"\n },\n {\n \"value\": \"hat_spokemon\",\n \"displayName\": \"Spokemon\"\n },\n {\n \"value\": \"hat_top-hat-1\",\n \"displayName\": \"Top Hat 1\"\n }\n ],\n \"Head\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"head_skin-1\",\n \"displayName\": \"Skin 1\"\n },\n {\n \"value\": \"head_skin-2\",\n \"displayName\": \"Skin 2\"\n },\n {\n \"value\": \"head_skin-3\",\n \"displayName\": \"Skin 3\"\n },\n {\n \"value\": \"head_skin-4\",\n \"displayName\": \"Skin 4\"\n },\n {\n \"value\": \"head_skin-5\",\n \"displayName\": \"Skin 5\"\n },\n {\n \"value\": \"head_skin-6\",\n \"displayName\": \"Skin 6\"\n },\n {\n \"value\": \"head_skin-7\",\n \"displayName\": \"Skin 7\"\n },\n {\n \"value\": \"head_skin-8\",\n \"displayName\": \"Skin 8\"\n },\n {\n \"value\": \"head_skin-a\",\n \"displayName\": \"Skin A\"\n },\n {\n \"value\": \"head_skin-b\",\n \"displayName\": \"Skin B\"\n },\n {\n \"value\": \"head_skin-c\",\n \"displayName\": \"Skin C\"\n },\n {\n \"value\": \"head_skin-d\",\n \"displayName\": \"Skin D\"\n },\n {\n \"value\": \"head_skin-e\",\n \"displayName\": \"Skin E\"\n },\n {\n \"value\": \"head_skin-f\",\n \"displayName\": \"Skin F\"\n },\n {\n \"value\": \"head_skin-g\",\n \"displayName\": \"Skin G\"\n },\n {\n \"value\": \"head_skin-h\",\n \"displayName\": \"Skin H\"\n }\n ],\n \"Mouth\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"mouth_neutral-skin-1\",\n \"displayName\": \"Neutral Skin 1\"\n },\n {\n \"value\": \"mouth_neutral-skin-2\",\n \"displayName\": \"Neutral Skin 2\"\n },\n {\n \"value\": \"mouth_neutral-skin-3\",\n \"displayName\": \"Neutral Skin 3\"\n },\n {\n \"value\": \"mouth_neutral-skin-4\",\n \"displayName\": \"Neutral Skin 4\"\n },\n {\n \"value\": \"mouth_neutral-skin-5\",\n \"displayName\": \"Neutral Skin 5\"\n },\n {\n \"value\": \"mouth_neutral-skin-7\",\n \"displayName\": \"Neutral Skin 7\"\n },\n {\n \"value\": \"mouth_neutral-skin-8\",\n \"displayName\": \"Neutral Skin 8\"\n },\n {\n \"value\": \"mouth_neutral-skin-a\",\n \"displayName\": \"Neutral Skin A\"\n },\n {\n \"value\": \"mouth_neutral-skin-b\",\n \"displayName\": \"Neutral Skin B\"\n },\n {\n \"value\": \"mouth_neutral-skin-c\",\n \"displayName\": \"Neutral Skin C\"\n },\n {\n \"value\": \"mouth_neutral-skin-d\",\n \"displayName\": \"Neutral Skin D\"\n },\n {\n \"value\": \"mouth_neutral-skin-e\",\n \"displayName\": \"Neutral Skin E\"\n },\n {\n \"value\": \"mouth_neutral-skin-f\",\n \"displayName\": \"Neutral Skin F\"\n },\n {\n \"value\": \"mouth_neutral-skin-g\",\n \"displayName\": \"Neutral Skin G\"\n },\n {\n \"value\": \"mouth_neutral-skin-h\",\n \"displayName\": \"Neutral Skin H\"\n },\n {\n \"value\": \"mouth_smirk-skin-1\",\n \"displayName\": \"Smirk Skin 1\"\n },\n {\n \"value\": \"mouth_smirk-skin-2\",\n \"displayName\": \"Smirk Skin 2\"\n },\n {\n \"value\": \"mouth_smirk-skin-3\",\n \"displayName\": \"Smirk Skin 3\"\n },\n {\n \"value\": \"mouth_smirk-skin-4\",\n \"displayName\": \"Smirk Skin 4\"\n },\n {\n \"value\": \"mouth_smirk-skin-5\",\n \"displayName\": \"Smirk Skin 5\"\n },\n {\n \"value\": \"mouth_smirk-skin-6\",\n \"displayName\": \"Smirk Skin 6\"\n },\n {\n \"value\": \"mouth_smirk-skin-7\",\n \"displayName\": \"Smirk Skin 7\"\n },\n {\n \"value\": \"mouth_smirk-skin-8\",\n \"displayName\": \"Smirk Skin 8\"\n },\n {\n \"value\": \"mouth_smirk-skin-a\",\n \"displayName\": \"Smirk Skin A\"\n },\n {\n \"value\": \"mouth_smirk-skin-b\",\n \"displayName\": \"Smirk Skin B\"\n },\n {\n \"value\": \"mouth_smirk-skin-c\",\n \"displayName\": \"Smirk Skin C\"\n },\n {\n \"value\": \"mouth_smirk-skin-d\",\n \"displayName\": \"Smirk Skin D\"\n },\n {\n \"value\": \"mouth_smirk-skin-e\",\n \"displayName\": \"Smirk Skin E\"\n },\n {\n \"value\": \"mouth_smirk-skin-f\",\n \"displayName\": \"Smirk Skin F\"\n },\n {\n \"value\": \"mouth_smirk-skin-g\",\n \"displayName\": \"Smirk Skin G\"\n },\n {\n \"value\": \"mouth_smirk-skin-h\",\n \"displayName\": \"Smirk Skin H\"\n }\n ],\n \"Torso Jacket\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"torso-jacket_style-1-punk-leather-1-black\",\n \"displayName\": \"Style 1 Punk Leather 1 Black\"\n }\n ],\n \"Torso\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"torso_style-1-baseball-giants\",\n \"displayName\": \"Style 1 Baseball Giants\"\n },\n {\n \"value\": \"torso_style-1-bowling-shirt-1-red\",\n \"displayName\": \"Style 1 Bowling Shirt 1 Red\"\n },\n {\n \"value\": \"torso_style-1-combat-vest-red\",\n \"displayName\": \"Style 1 Combat Vest Red\"\n },\n {\n \"value\": \"torso_style-1-ketchum\",\n \"displayName\": \"Style 1 Ketchum\"\n },\n {\n \"value\": \"torso_style-1-sport-coat-1-dark\",\n \"displayName\": \"Style 1 Sport Coat 1 Dark\"\n },\n {\n \"value\": \"torso_style-1-sport-coat-1-gray\",\n \"displayName\": \"Style 1 Sport Coat 1 Gray\"\n },\n {\n \"value\": \"torso_style-1-tshirt-moz\",\n \"displayName\": \"Style 1 Tshirt Moz\"\n },\n {\n \"value\": \"torso_style-1-tshirt-union-jack\",\n \"displayName\": \"Style 1 Tshirt Union Jack\"\n },\n {\n \"value\": \"torso_style-1-tshirt1-reactor\",\n \"displayName\": \"Style 1 Tshirt1 Reactor\"\n },\n {\n \"value\": \"torso_style-1-ugly-christmas-1\",\n \"displayName\": \"Style 1 Ugly Christmas 1\"\n },\n {\n \"value\": \"torso_style-2-hoodie-1-gray\",\n \"displayName\": \"Style 2 Hoodie 1 Gray\"\n },\n {\n \"value\": \"torso_style-2-hoodie-2-purple\",\n \"displayName\": \"Style 2 Hoodie 2 Purple\"\n },\n {\n \"value\": \"torso_style-2-tshirt-1-baby-unicorn\",\n \"displayName\": \"Style 2 Tshirt 1 Baby Unicorn\"\n },\n {\n \"value\": \"torso_style-2-tshirt-1-heart-animated\",\n \"displayName\": \"Style 2 Tshirt 1 Heart Animated\"\n },\n {\n \"value\": \"torso_style-2-tshirt-1-heart\",\n \"displayName\": \"Style 2 Tshirt 1 Heart\"\n },\n {\n \"value\": \"torso_style-2-tshirt-1-moz\",\n \"displayName\": \"Style 2 Tshirt 1 Moz\"\n }\n ]\n};","import React, { useState, useEffect } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport \"./game\";\nimport constants from \"./constants\";\nimport initialAssets from \"./assets\";\n\nfunction AvatarPartSelector({ onPartSelected, parts, selected }) {\n return (\n {\n onPartSelected(e.target.selectedOptions[0].getAttribute(\"value\"));\n }}\n value={selected || \"\"}\n >\n {parts.map((part, i) => (\n \n ))}\n \n );\n}\n\nfunction App() {\n const [assets, setAssets] = useState(initialAssets);\n\n const categories = Object.keys(assets);\n\n function generateRandomConfig() {\n const newConfig = {};\n for (const category of categories) {\n const categoryAssets = assets[category].filter(part => !part.excludeFromRandomize);\n if (categoryAssets.length === 0) continue;\n const randomIndex = Math.floor(Math.random() * categoryAssets.length);\n newConfig[category] = categoryAssets[randomIndex].value;\n }\n return newConfig;\n }\n\n const initialAvatarConfig = generateRandomConfig();\n const [avatarConfig, setAvatarConfig] = useState(initialAvatarConfig);\n\n function onGLBUploaded(e) {\n const file = e.target.files[0];\n const filename = file.name;\n const category = filename.substring(0, filename.indexOf(\"_\")) || \"custom\";\n const displayName = filename.substring(filename.indexOf(\"_\") + 1, filename.lastIndexOf(\".\"));\n const url = URL.createObjectURL(file);\n\n const clone = { ...assets };\n clone[category] = clone[category] || [\n {\n displayName: \"none\",\n value: null,\n },\n ];\n clone[category].push({\n displayName,\n value: url,\n });\n setAssets(clone);\n\n updateAvatarConfig({ [category]: url });\n }\n\n useEffect(() => {\n document.dispatchEvent(new CustomEvent(constants.avatarConfigChanged, { detail: { avatarConfig } }));\n });\n\n function updateAvatarConfig(newConfig) {\n setAvatarConfig({ ...avatarConfig, ...newConfig });\n }\n\n function randomizeConfig() {\n setAvatarConfig(generateRandomConfig());\n }\n\n function dispatchExport() {\n document.dispatchEvent(new CustomEvent(constants.exportAvatar));\n }\n\n function dispatchResetView() {\n document.dispatchEvent(new CustomEvent(constants.resetView));\n }\n\n return (\n <>\n {categories.map((category) => (\n
\n {category}: \n {\n updateAvatarConfig({ [category]: selection });\n }}\n parts={assets[category]}\n />\n
\n ))}\n \n \n \n \n \n );\n}\n\nReactDOM.render(, document.getElementById(\"root\"));\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tif(__webpack_module_cache__[moduleId]) {\n\t\treturn __webpack_module_cache__[moduleId].exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n// the startup function\n// It's empty as some runtime module handles the default behavior\n__webpack_require__.x = x => {}\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// Promise = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t179: 0\n};\n\nvar deferredModules = [\n\t[498,536]\n];\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\nvar checkDeferredModules = x => {};\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime, executeModules] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0, resolves = [];\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tresolves.push(installedChunks[chunkId][0]);\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\tfor(moduleId in moreModules) {\n\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t}\n\t}\n\tif(runtime) runtime(__webpack_require__);\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\twhile(resolves.length) {\n\t\tresolves.shift()();\n\t}\n\n\t// add entry modules from loaded chunk to deferred list\n\tif(executeModules) deferredModules.push.apply(deferredModules, executeModules);\n\n\t// run deferred modules when all chunks ready\n\treturn checkDeferredModules();\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunk\"] = self[\"webpackChunk\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));\n\nfunction checkDeferredModulesImpl() {\n\tvar result;\n\tfor(var i = 0; i < deferredModules.length; i++) {\n\t\tvar deferredModule = deferredModules[i];\n\t\tvar fulfilled = true;\n\t\tfor(var j = 1; j < deferredModule.length; j++) {\n\t\t\tvar depId = deferredModule[j];\n\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferredModules.splice(i--, 1);\n\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n\t\t}\n\t}\n\tif(deferredModules.length === 0) {\n\t\t__webpack_require__.x();\n\t\t__webpack_require__.x = x => {};\n\t}\n\treturn result;\n}\nvar startup = __webpack_require__.x;\n__webpack_require__.x = () => {\n\t// reset startup function so it can be called again when more startup code is added\n\t__webpack_require__.x = startup || (x => {});\n\treturn (checkDeferredModules = checkDeferredModulesImpl)();\n};","// run startup\n__webpack_require__.x();\n"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/main-94aa61a7cab659448779.js b/dist/main-94aa61a7cab659448779.js deleted file mode 100644 index 97f0cdc..0000000 --- a/dist/main-94aa61a7cab659448779.js +++ /dev/null @@ -1,2 +0,0 @@ -(()=>{"use strict";var e={810:(e,a,n)=>{var t=n(294),l=n(935),i=n(212),s=n(886),o=n(509);const r="avatarConfigChanged",u="exportAvatar",d="resetView";var m=n(47),c=n(895);function y({candidates:e,predicate:a}){if(!e.length)return null;const n=e.shift();return a(n)?n:y({candidates:e=e.concat(n.children),predicate:a})}function p(e,a){return y({candidates:[e],predicate:e=>e.name===a})}function h({candidates:e,predicate:a,results:n=[]}){if(!e.length)return n;const t=e.shift();return a(t)&&n.push(t),h({candidates:e=e.concat(t.children),predicate:a,results:n})}function v(e,a){return h({candidates:[e],predicate:e=>e.type===a})}function k({object3D:e,depth:a=0,callback:n,result:t}){t.push(n(e,a));const l=e.children;for(let e=0;e{if(n){const a=new Blob([e],{type:"application/octet-stream"}),n=document.createElement("a");n.style.display="none",n.href=URL.createObjectURL(a),n.download="custom_avatar.glb",n.click(),n.remove()}else console.log(e)}),{binary:n,animations:t})}}();function g(e,a){const n=[];for(const t of a.animations)-1===e.animations.findIndex((e=>e.name===t.name))&&n.push(t);for(const a of n)e.animations.push(a)}const w={DOMContentLoaded:!1,shouldResize:!0,didInit:!1,scene:null,camera:null,renderer:null,controls:null,envMap:null,avatarNodes:{},avatarConfig:{},newAvatarConfig:{},shouldApplyNewAvatarConfig:!1,shouldExportAvatar:!1,shouldResetView:!1};async function E(e,a,n){const t=await f((l=a,l.startsWith("blob")?l:`assets/${l}.glb`));var l;w.avatarConfig[e]===a&&(t.scene.animations=t.animations,n.clear(),n.add(t.scene),t.scene.traverse((e=>{var a,n;n=e=>{e.isMeshStandardMaterial&&(e.envMap=w.envMap,e.needsUpdate=!0)},(a=e).material&&(Array.isArray(a.material)?a.material.forEach(n):n(a.material))})))}window.gameState=w,window.addEventListener("DOMContentLoaded",(()=>{w.DOMContentLoaded=!0})),window.onresize=()=>{w.shouldResize=!0},document.addEventListener(r,(e=>{w.newAvatarConfig=e.detail.avatarConfig,w.shouldApplyNewAvatarConfig=!0})),document.addEventListener(u,(()=>{w.shouldExportAvatar=!0})),document.addEventListener(d,(()=>{w.shouldResetView=!0})),window.requestAnimationFrame((function e(a){if(w.DOMContentLoaded&&!w.didInit&&(w.didInit=!0,function(){i.CtF.enabled=!0;const e=new i.xsS;e.fog=new i.yo9(9145226,.2),e.background=new i.Ilk(9145226),w.scene=e;const a=new i.cPb(75,window.innerWidth/window.innerHeight,.1,1e3);a.position.set(0,.25,1.5),w.camera=a;const n=new i.Mig(16777215,.4);e.add(n);const t=new i.CP7({canvas:document.getElementById("scene"),antialias:!0});w.renderer=t;const l=function(){const e=new c.q;e.scale.setScalar(45e4);const a=e.material.uniforms;a.turbidity.value=10,a.rayleigh.value=3,a.mieCoefficient.value=.005,a.mieDirectionalG.value=.7;const n=Math.PI*(.7-.5),t=2*Math.PI*(.55-.5),l=new i.Pa4;return l.x=Math.cos(t),l.y=Math.sin(t)*Math.sin(n),l.z=Math.sin(t)*Math.cos(n),a.sunPosition.value.copy(l),e}();w.envMap=function(e,a){const n=new i.xsS;n.add(e);const t=new i.anP(a),l=t.fromScene(n);return t.dispose(),n.remove(e),l.texture}(l,t);const o=new i.Kj0(new i.BKK(100,100),new i.Wid);o.position.y=-.2,o.rotation.x=-Math.PI/2,e.add(o);const r=new s.z(a,t.domElement);r.target=new i.Pa4(0,.5,0),r.update(),r.saveState(),w.controls=r,w.avatarGroup=new i.ZAu,e.add(w.avatarGroup)}()),w.didInit){if(w.shouldResize){w.shouldResize=!1;const{renderer:e,camera:a}=w,n=e.domElement.parentNode.clientWidth,t=e.domElement.parentNode.clientHeight;e.setSize(n,t,!1),a.aspect=n/t,a.updateProjectionMatrix()}{const{renderer:e,scene:a,camera:n}=w;e.render(a,n)}if(w.shouldApplyNewAvatarConfig){w.shouldApplyNewAvatarConfig=!1;const e=new Set(Object.keys(w.newAvatarConfig).concat(Object.keys(w.avatarConfig)));for(const a of e)w.avatarNodes[a]||(w.avatarNodes[a]=new i.ZAu,w.avatarGroup.add(w.avatarNodes[a])),w.newAvatarConfig[a]!==w.avatarConfig[a]&&(null!==w.newAvatarConfig[a]?E(a,w.newAvatarConfig[a],w.avatarNodes[a]):w.avatarNodes[a].clear(),w.avatarConfig[a]=w.newAvatarConfig[a])}w.shouldExportAvatar&&(w.shouldExportAvatar=!1,function(e){const a=function(e){const a=new i.ZAu;a.name="Scene";const n=e.children.map((e=>p(e,"Scene"))).filter((e=>!!e));for(const e of n)g(a,e);const t=e.children.map((e=>p(e,"AvatarRoot"))).filter((e=>!!e)),l=t[0].clone(!1);for(const e of t)l.userData=(s=l.userData,o=e.userData,S(s),S(o),s.gltfExtensions.MOZ_hubs_components&&(s.gltfExtensions.MOZ_hubs_components=Object.assign(s.gltfExtensions.MOZ_hubs_components,o.gltfExtensions.MOZ_hubs_components)),s);var s,o;const r=v(e,"SkinnedMesh").map((e=>e.clone(!1))),u=function(e){const a=new Map;for(const n of e.skeleton.bones){const e=n.clone(!1);a.set(n,e)}return e.skeleton.bones[0].traverse((e=>{if("Bone"!==e.type)return;const n=a.get(e);for(const t of e.children)n.add(a.get(t))})),new i.OdW(e.skeleton.bones.map((e=>a.get(e))))}(r[0]);for(const e of r)e.bind(u);a.add(l),l.add(u.bones[0]);for(const e of r)l.add(e);return a}(e);console.log(_(a)),console.log(a),b(a,{binary:!1,animations:a.animations}),b(a,{binary:!0,animations:a.animations})}(w.avatarGroup)),w.shouldResetView&&(w.shouldResetView=!1,w.controls.reset()),window.requestAnimationFrame(e)}else requestAnimationFrame(e)}));const x={Accessory:[{value:null,displayName:"none",excludeFromRandomize:!1},{value:"accessory_duck-floaty",displayName:"Duck Floaty"},{value:"accessory_face-mask-1-animated",displayName:"Face Mask 1 Animated"},{value:"accessory_headband-cat-ears-1",displayName:"Headband Cat Ears 1"},{value:"accessory_headphones-1-black",displayName:"Headphones 1 Black"},{value:"accessory_pool-mask-1",displayName:"Pool Mask 1"}],Earring:[{value:null,displayName:"none",excludeFromRandomize:!1},{value:"earring_hoop-high-left-silver",displayName:"Hoop High Left Silver"},{value:"earring_hoop-high-right-silver",displayName:"Hoop High Right Silver"},{value:"earring_hoop-large-both-gold",displayName:"Hoop Large Both Gold"},{value:"earring_hoop-small-both-gold",displayName:"Hoop Small Both Gold"}],Eyebrows:[{value:null,displayName:"none",excludeFromRandomize:!0},{value:"eyebrows_brown",displayName:"Brown"}],Eyes:[{value:null,displayName:"none",excludeFromRandomize:!0},{value:"eyes_style-1-blue",displayName:"Style 1 Blue"},{value:"eyes_style-1-brown",displayName:"Style 1 Brown"},{value:"eyes_style-11-blue",displayName:"Style 11 Blue"},{value:"eyes_style-11-brown",displayName:"Style 11 Brown"},{value:"eyes_style-12-blue",displayName:"Style 12 Blue"},{value:"eyes_style-12-brown",displayName:"Style 12 Brown"},{value:"eyes_style-12-green",displayName:"Style 12 Green"},{value:"eyes_style-13-blue",displayName:"Style 13 Blue"},{value:"eyes_style-13-brown",displayName:"Style 13 Brown"},{value:"eyes_style-14-blue",displayName:"Style 14 Blue"},{value:"eyes_style-14-brown",displayName:"Style 14 Brown"}],Eyewear:[{value:null,displayName:"none",excludeFromRandomize:!1},{value:"eyewear_arnette",displayName:"Arnette"},{value:"eyewear_aviators1",displayName:"Aviators1"},{value:"eyewear_glam-2",displayName:"Glam 2"},{value:"eyewear_heart-1-pink",displayName:"Heart 1 Pink"},{value:"eyewear_metal-1",displayName:"Metal 1"},{value:"eyewear_oakleys-red",displayName:"Oakleys Red"},{value:"eyewear_punk-2",displayName:"Punk 2"},{value:"eyewear_wire-frame-1-gold",displayName:"Wire Frame 1 Gold"}],"Facial Hair":[{value:null,displayName:"none",excludeFromRandomize:!1},{value:"facial-hair_beard-full-1-dark",displayName:"Beard Full 1 Dark"},{value:"facial-hair_beard-full-2-brown",displayName:"Beard Full 2 Brown"},{value:"facial-hair_goatee-1-brown",displayName:"Goatee 1 Brown"},{value:"facial-hair_goatee-2",displayName:"Goatee 2"},{value:"facial-hair_goatee-3",displayName:"Goatee 3"},{value:"facial-hair_goatee-4",displayName:"Goatee 4"},{value:"facial-hair_goatee-5",displayName:"Goatee 5"},{value:"facial-hair_mustache-1",displayName:"Mustache 1"},{value:"facial-hair_mustache-2",displayName:"Mustache 2"}],Hair:[{value:null,displayName:"none",excludeFromRandomize:!1},{value:"hair_aLine-asym",displayName:"ALine Asym"},{value:"hair_afro-1",displayName:"Afro 1"},{value:"hair_afro-2",displayName:"Afro 2"},{value:"hair_bob-1-dark",displayName:"Bob 1 Dark"},{value:"hair_bob-1-light",displayName:"Bob 1 Light"},{value:"hair_bob-1-red",displayName:"Bob 1 Red"},{value:"hair_braided-bun",displayName:"Braided Bun"},{value:"hair_eraser-top",displayName:"Eraser Top"},{value:"hair_fauxhawk-1",displayName:"Fauxhawk 1"},{value:"hair_flat-top-1",displayName:"Flat Top 1"},{value:"hair_french-braid-buns",displayName:"French Braid Buns"},{value:"hair_french-braids-double",displayName:"French Braids Double"},{value:"hair_male_taperAfro1",displayName:"Male"},{value:"hair_mohawk-1-blue",displayName:"Mohawk 1 Blue"},{value:"hair_mullet-1-dark",displayName:"Mullet 1 Dark"},{value:"hair_parted-1-brown",displayName:"Parted 1 Brown"},{value:"hair_parted-1-gray",displayName:"Parted 1 Gray"},{value:"hair_parted-long-1",displayName:"Parted Long 1"},{value:"hair_pigtails-1-blue",displayName:"Pigtails 1 Blue"},{value:"hair_pigtails-1-pink",displayName:"Pigtails 1 Pink"},{value:"hair_pony-tail-1",displayName:"Pony Tail 1"},{value:"hair_pony-tail-2",displayName:"Pony Tail 2"},{value:"hair_pony-tail-3",displayName:"Pony Tail 3"},{value:"hair_spikey-1",displayName:"Spikey 1"},{value:"hair_starter-locs-red",displayName:"Starter Locs Red"}],Hands:[{value:null,displayName:"none",excludeFromRandomize:!0},{value:"hands_skin-1",displayName:"Skin 1"},{value:"hands_skin-2",displayName:"Skin 2"},{value:"hands_skin-3",displayName:"Skin 3"},{value:"hands_skin-4",displayName:"Skin 4"},{value:"hands_skin-5",displayName:"Skin 5"},{value:"hands_skin-6",displayName:"Skin 6"},{value:"hands_skin-7",displayName:"Skin 7"},{value:"hands_skin-8",displayName:"Skin 8"},{value:"hands_skin-a",displayName:"Skin A"},{value:"hands_skin-b",displayName:"Skin B"},{value:"hands_skin-c",displayName:"Skin C"},{value:"hands_skin-d",displayName:"Skin D"},{value:"hands_skin-e",displayName:"Skin E"},{value:"hands_skin-f",displayName:"Skin F"},{value:"hands_skin-g",displayName:"Skin G"},{value:"hands_skin-h",displayName:"Skin H"}],Hat:[{value:null,displayName:"none",excludeFromRandomize:!1},{value:"hat_baseball-giants",displayName:"Baseball Giants"},{value:"hat_beach-umbrella",displayName:"Beach Umbrella"},{value:"hat_beanie-1-red",displayName:"Beanie 1 Red"},{value:"hat_spokemon",displayName:"Spokemon"},{value:"hat_top-hat-1",displayName:"Top Hat 1"}],Head:[{value:null,displayName:"none",excludeFromRandomize:!0},{value:"head_skin-1",displayName:"Skin 1"},{value:"head_skin-2",displayName:"Skin 2"},{value:"head_skin-3",displayName:"Skin 3"},{value:"head_skin-4",displayName:"Skin 4"},{value:"head_skin-5",displayName:"Skin 5"},{value:"head_skin-6",displayName:"Skin 6"},{value:"head_skin-7",displayName:"Skin 7"},{value:"head_skin-8",displayName:"Skin 8"},{value:"head_skin-a",displayName:"Skin A"},{value:"head_skin-b",displayName:"Skin B"},{value:"head_skin-c",displayName:"Skin C"},{value:"head_skin-d",displayName:"Skin D"},{value:"head_skin-e",displayName:"Skin E"},{value:"head_skin-f",displayName:"Skin F"},{value:"head_skin-g",displayName:"Skin G"},{value:"head_skin-h",displayName:"Skin H"}],Mouth:[{value:null,displayName:"none",excludeFromRandomize:!0},{value:"mouth_neutral-skin-1",displayName:"Neutral Skin 1"},{value:"mouth_neutral-skin-2",displayName:"Neutral Skin 2"},{value:"mouth_neutral-skin-3",displayName:"Neutral Skin 3"},{value:"mouth_neutral-skin-4",displayName:"Neutral Skin 4"},{value:"mouth_neutral-skin-5",displayName:"Neutral Skin 5"},{value:"mouth_neutral-skin-7",displayName:"Neutral Skin 7"},{value:"mouth_neutral-skin-8",displayName:"Neutral Skin 8"},{value:"mouth_neutral-skin-a",displayName:"Neutral Skin A"},{value:"mouth_neutral-skin-b",displayName:"Neutral Skin B"},{value:"mouth_neutral-skin-c",displayName:"Neutral Skin C"},{value:"mouth_neutral-skin-d",displayName:"Neutral Skin D"},{value:"mouth_neutral-skin-e",displayName:"Neutral Skin E"},{value:"mouth_neutral-skin-f",displayName:"Neutral Skin F"},{value:"mouth_neutral-skin-g",displayName:"Neutral Skin G"},{value:"mouth_neutral-skin-h",displayName:"Neutral Skin H"},{value:"mouth_smirk-skin-1",displayName:"Smirk Skin 1"},{value:"mouth_smirk-skin-2",displayName:"Smirk Skin 2"},{value:"mouth_smirk-skin-3",displayName:"Smirk Skin 3"},{value:"mouth_smirk-skin-4",displayName:"Smirk Skin 4"},{value:"mouth_smirk-skin-5",displayName:"Smirk Skin 5"},{value:"mouth_smirk-skin-6",displayName:"Smirk Skin 6"},{value:"mouth_smirk-skin-7",displayName:"Smirk Skin 7"},{value:"mouth_smirk-skin-8",displayName:"Smirk Skin 8"},{value:"mouth_smirk-skin-a",displayName:"Smirk Skin A"},{value:"mouth_smirk-skin-b",displayName:"Smirk Skin B"},{value:"mouth_smirk-skin-c",displayName:"Smirk Skin C"},{value:"mouth_smirk-skin-d",displayName:"Smirk Skin D"},{value:"mouth_smirk-skin-e",displayName:"Smirk Skin E"},{value:"mouth_smirk-skin-f",displayName:"Smirk Skin F"},{value:"mouth_smirk-skin-g",displayName:"Smirk Skin G"},{value:"mouth_smirk-skin-h",displayName:"Smirk Skin H"}],"Torso Jacket":[{value:null,displayName:"none",excludeFromRandomize:!1},{value:"torso-jacket_style-1-punk-leather-1-black",displayName:"Style 1 Punk Leather 1 Black"}],Torso:[{value:null,displayName:"none",excludeFromRandomize:!0},{value:"torso_style-1-baseball-giants",displayName:"Style 1 Baseball Giants"},{value:"torso_style-1-bowling-shirt-1-red",displayName:"Style 1 Bowling Shirt 1 Red"},{value:"torso_style-1-combat-vest-red",displayName:"Style 1 Combat Vest Red"},{value:"torso_style-1-ketchum",displayName:"Style 1 Ketchum"},{value:"torso_style-1-sport-coat-1-dark",displayName:"Style 1 Sport Coat 1 Dark"},{value:"torso_style-1-sport-coat-1-gray",displayName:"Style 1 Sport Coat 1 Gray"},{value:"torso_style-1-tshirt-moz",displayName:"Style 1 Tshirt Moz"},{value:"torso_style-1-tshirt-union-jack",displayName:"Style 1 Tshirt Union Jack"},{value:"torso_style-1-tshirt1-reactor",displayName:"Style 1 Tshirt1 Reactor"},{value:"torso_style-1-ugly-christmas-1",displayName:"Style 1 Ugly Christmas 1"},{value:"torso_style-2-hoodie-1-gray",displayName:"Style 2 Hoodie 1 Gray"},{value:"torso_style-2-hoodie-2-purple",displayName:"Style 2 Hoodie 2 Purple"},{value:"torso_style-2-tshirt-1-baby-unicorn",displayName:"Style 2 Tshirt 1 Baby Unicorn"},{value:"torso_style-2-tshirt-1-heart-animated",displayName:"Style 2 Tshirt 1 Heart Animated"},{value:"torso_style-2-tshirt-1-heart",displayName:"Style 2 Tshirt 1 Heart"},{value:"torso_style-2-tshirt-1-moz",displayName:"Style 2 Tshirt 1 Moz"}]};function B({onPartSelected:e,parts:a,selected:n}){return t.createElement("select",{onChange:a=>{e(a.target.selectedOptions[0].getAttribute("value"))},value:n||""},a.map(((e,a)=>t.createElement("option",{key:a,value:e.value},e.displayName))))}function C(){const[e,a]=(0,t.useState)(x),n=Object.keys(e);function l(){const a={};for(const t of n){const n=e[t].filter((e=>!e.excludeFromRandomize));if(0===n.length)continue;const l=Math.floor(Math.random()*n.length);a[t]=n[l].value}return a}const i=l(),[s,o]=(0,t.useState)(i);function m(e){o({...s,...e})}return(0,t.useEffect)((()=>{document.dispatchEvent(new CustomEvent(r,{detail:{avatarConfig:s}}))})),t.createElement(t.Fragment,null,n.map((a=>t.createElement("div",{key:a,className:"category"},t.createElement("span",null,a,": "),t.createElement(B,{selected:s[a],onPartSelected:e=>{m({[a]:e})},parts:e[a]})))),t.createElement("button",{onClick:function(){o(l())}},"Randomize avatar"),t.createElement("button",{onClick:function(){document.dispatchEvent(new CustomEvent(u))}},"Export avatar"),t.createElement("button",{onClick:function(){document.dispatchEvent(new CustomEvent(d))}},"Reset camera view"),t.createElement("label",null,"Upload custom part:",t.createElement("input",{onChange:function(n){const t=n.target.files[0],l=t.name,i=l.substring(0,l.indexOf("_"))||"custom",s=l.substring(l.indexOf("_")+1,l.lastIndexOf(".")),o=URL.createObjectURL(t),r={...e};r[i]=r[i]||[{displayName:"none",value:null}],r[i].push({displayName:s,value:o}),a(r),m({[i]:o})},type:"file",id:"input",accept:"model/gltf-binary,.glb"})))}l.render(t.createElement(C,null),document.getElementById("root"))}},a={};function n(t){if(a[t])return a[t].exports;var l=a[t]={exports:{}};return e[t](l,l.exports,n),l.exports}n.m=e,n.x=e=>{},n.d=(e,a)=>{for(var t in a)n.o(a,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},n.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),(()=>{var e={179:0},a=[[810,536]],t=e=>{},l=(l,i)=>{for(var s,o,[r,u,d,m]=i,c=0,y=[];c{}),t}i.forEach(l.bind(null,0)),i.push=l.bind(null,i.push.bind(i));var o=n.x;n.x=()=>(n.x=o||(e=>{}),(t=s)())})(),n.x()})(); -//# sourceMappingURL=main-94aa61a7cab659448779.js.map \ No newline at end of file diff --git a/dist/main-94aa61a7cab659448779.js.map b/dist/main-94aa61a7cab659448779.js.map deleted file mode 100644 index 1828464..0000000 --- a/dist/main-94aa61a7cab659448779.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///./src/constants.js","webpack:///./src/utils.js","webpack:///./src/export.js","webpack:///./src/game.js","webpack:///./src/assets.js","webpack:///./src/index.js","webpack:///webpack/bootstrap","webpack:///webpack/runtime/define property getters","webpack:///webpack/runtime/hasOwnProperty shorthand","webpack:///webpack/runtime/jsonp chunk loading","webpack:///webpack/startup"],"names":["findChild","candidates","predicate","length","candidate","shift","concat","children","findChildByName","root","name","o","findChildren","results","push","findChildrenByType","type","traverseWithDepth","object3D","depth","callback","result","i","describe","prefix","indentation","description","JSON","stringify","userData","firstBone","repeat","skeleton","bones","uuid","boneId","describeObject3D","join","loadGLTF","loader","GLTFLoader","url","Promise","resolve","reject","load","gltf","xhr","error","console","log","ensureHubsComponents","gltfExtensions","MOZ_hubs_components","exportGLTF","exporter","GLTFExporter","binary","animations","parse","blob","Blob","el","document","createElement","style","display","href","URL","createObjectURL","download","click","remove","addNonDuplicateAnimationClips","clone","scene","clipsToAdd","clip","findIndex","clonedAnimation","state","DOMContentLoaded","shouldResize","didInit","camera","renderer","controls","envMap","avatarNodes","avatarConfig","newAvatarConfig","shouldApplyNewAvatarConfig","shouldExportAvatar","shouldResetView","async","loadIntoGroup","category","part","group","value","startsWith","clear","add","traverse","obj","fn","material","isMeshStandardMaterial","needsUpdate","Array","isArray","forEach","window","gameState","addEventListener","onresize","constants","e","detail","requestAnimationFrame","tick","time","THREE","fog","background","innerWidth","innerHeight","position","set","ambientLight","canvas","getElementById","antialias","sky","Sky","scale","setScalar","uniforms","theta","Math","PI","phi","sun","x","cos","y","sin","z","copy","createSky","skyScene","pmremGenerator","renderTarget","fromScene","dispose","texture","generateEnvironmentMap","floor","rotation","OrbitControls","domElement","target","update","saveState","avatarGroup","init","width","parentNode","clientWidth","height","clientHeight","setSize","aspect","updateProjectionMatrix","render","categories","Set","Object","keys","avatar","clonedScene","scenes","map","filter","avatarRoots","clonedAvatarRoot","avatarRoot","a","b","assign","clonedSkinnedMeshes","clonedSkeleton","skinnedMesh","boneClones","Map","bone","get","child","cloneSkeleton","bind","cloneIntoAvatar","exportAvatar","reset","AvatarPartSelector","onPartSelected","parts","selected","onChange","selectedOptions","getAttribute","key","displayName","App","assets","setAssets","useState","initialAssets","generateRandomConfig","newConfig","categoryAssets","excludeFromRandomize","randomIndex","random","initialAvatarConfig","setAvatarConfig","updateAvatarConfig","useEffect","dispatchEvent","CustomEvent","className","selection","onClick","file","files","filename","substring","indexOf","lastIndexOf","id","accept","ReactDOM","__webpack_module_cache__","__webpack_require__","moduleId","exports","module","__webpack_modules__","m","d","definition","defineProperty","enumerable","prop","prototype","hasOwnProperty","call","installedChunks","179","deferredModules","checkDeferredModules","webpackJsonpCallback","parentChunkLoadingFunction","data","chunkId","chunkIds","moreModules","runtime","executeModules","resolves","apply","chunkLoadingGlobal","self","checkDeferredModulesImpl","deferredModule","fulfilled","j","depId","splice","s","startup"],"mappings":"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","file":"main-94aa61a7cab659448779.js","sourcesContent":["export default {\n avatarConfigChanged: \"avatarConfigChanged\",\n exportAvatar: \"exportAvatar\",\n resetView: \"resetView\",\n};\n","import * as THREE from \"three\";\nimport { GLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader\";\nimport { Sky } from \"three/examples/jsm/objects/Sky\";\n\nfunction findChild({ candidates, predicate }) {\n if (!candidates.length) {\n return null;\n }\n\n const candidate = candidates.shift();\n if (predicate(candidate)) return candidate;\n\n candidates = candidates.concat(candidate.children);\n return findChild({ candidates, predicate });\n}\n\nexport function findChildByName(root, name) {\n return findChild({\n candidates: [root],\n predicate: (o) => o.name === name,\n });\n}\n\nfunction findChildren({ candidates, predicate, results = [] }) {\n if (!candidates.length) {\n return results;\n }\n\n const candidate = candidates.shift();\n if (predicate(candidate)) {\n results.push(candidate);\n }\n\n candidates = candidates.concat(candidate.children);\n return findChildren({ candidates, predicate, results });\n}\n\nexport function findChildrenByType(root, type) {\n return findChildren({\n candidates: [root],\n predicate: (o) => o.type === type,\n });\n}\n\nfunction traverseWithDepth({ object3D, depth = 0, callback, result }) {\n result.push(callback(object3D, depth));\n const children = object3D.children;\n for (let i = 0; i < children.length; i++) {\n traverseWithDepth({ object3D: children[i], depth: depth + 1, callback, result });\n }\n return result;\n}\n\nconst describe = (function () {\n const prefix = \" \";\n return function describe(object3D, indentation) {\n const description = `${object3D.type} | ${object3D.name} | ${JSON.stringify(object3D.userData)}`;\n let firstBone = \"\";\n if (object3D.type === \"SkinnedMesh\") {\n firstBone = \"\\n\"\n .concat(prefix.repeat(indentation))\n .concat(\"First bone id: \")\n .concat(object3D.skeleton.bones[0].uuid);\n }\n let boneId = \"\";\n if (object3D.type === \"Bone\") {\n boneId = \"\\n\".concat(prefix.repeat(indentation)).concat(\"Bone id: \").concat(object3D.uuid);\n }\n\n return prefix.repeat(indentation).concat(description).concat(firstBone).concat(boneId);\n };\n})();\n\nexport function describeObject3D(root) {\n return traverseWithDepth({ object3D: root, callback: describe, result: [] }).join(\"\\n\");\n}\n\nexport const loadGLTF = (function () {\n const loader = new GLTFLoader();\n return function loadGLTF(url) {\n return new Promise(function (resolve, reject) {\n loader.load(\n url,\n function (gltf) {\n resolve(gltf);\n // gltf.animations; // Array\n // gltf.scene; // THREE.Group\n // gltf.scenes; // Array\n // gltf.cameras; // Array\n // gltf.asset; // Object\n },\n function (xhr) {\n // console.log((xhr.loaded / xhr.total) * 100 + \"% loaded\");\n },\n function (error) {\n console.log(\"An error happened\");\n reject(error);\n }\n );\n });\n };\n})();\n\nexport function forEachMaterial(object3D, fn) {\n if (!object3D.material) return;\n\n if (Array.isArray(object3D.material)) {\n object3D.material.forEach(fn);\n } else {\n fn(object3D.material);\n }\n}\n\nexport function generateEnvironmentMap(sky, renderer) {\n const skyScene = new THREE.Scene();\n skyScene.add(sky);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const renderTarget = pmremGenerator.fromScene(skyScene);\n pmremGenerator.dispose();\n\n skyScene.remove(sky);\n\n return renderTarget.texture;\n}\n\nexport function createSky() {\n const sky = new Sky();\n sky.scale.setScalar(450000);\n\n const uniforms = sky.material.uniforms;\n uniforms[\"turbidity\"].value = 10;\n uniforms[\"rayleigh\"].value = 3;\n uniforms[\"mieCoefficient\"].value = 0.005;\n uniforms[\"mieDirectionalG\"].value = 0.7;\n\n const inclination = 0.70;\n const azimuth = 0.55;\n const theta = Math.PI * (inclination - 0.5);\n const phi = 2 * Math.PI * (azimuth - 0.5);\n\n const sun = new THREE.Vector3();\n sun.x = Math.cos(phi);\n sun.y = Math.sin(phi) * Math.sin(theta);\n sun.z = Math.sin(phi) * Math.cos(theta);\n\n uniforms[\"sunPosition\"].value.copy(sun);\n\n return sky;\n}\n","import * as THREE from \"three\";\nimport { GLTFExporter } from \"three/examples/jsm/exporters/GLTFExporter\";\nimport { findChildrenByType, findChildByName, describeObject3D } from \"./utils\";\n\nfunction cloneSkeleton(skinnedMesh) {\n const boneClones = new Map();\n\n for (const bone of skinnedMesh.skeleton.bones) {\n const clone = bone.clone(false);\n boneClones.set(bone, clone);\n }\n\n // Preserve original bone structure\n // Assume bones[0] is root bone\n skinnedMesh.skeleton.bones[0].traverse((o) => {\n if (o.type !== \"Bone\") return;\n const clone = boneClones.get(o);\n for (const child of o.children) {\n clone.add(boneClones.get(child));\n }\n });\n\n return new THREE.Skeleton(skinnedMesh.skeleton.bones.map((b) => boneClones.get(b)));\n}\n\nfunction ensureHubsComponents(userData) {\n if (!userData.gltfExtensions) {\n userData.gltfExtensions = {};\n }\n if (!userData.gltfExtensions.MOZ_hubs_components) {\n userData.gltfExtensions.MOZ_hubs_components = {};\n }\n return userData;\n}\n\nexport function combineHubsComponents(a, b) {\n ensureHubsComponents(a);\n ensureHubsComponents(b);\n if (a.gltfExtensions.MOZ_hubs_components)\n // TODO: Deep merge\n a.gltfExtensions.MOZ_hubs_components = Object.assign(\n a.gltfExtensions.MOZ_hubs_components,\n b.gltfExtensions.MOZ_hubs_components\n );\n\n return a;\n}\n\nexport const exportGLTF = (function () {\n const exporter = new GLTFExporter();\n return function exportGLTF(object3D, { binary, animations }) {\n exporter.parse(\n object3D,\n (gltf) => {\n if (binary) {\n const blob = new Blob([gltf], { type: \"application/octet-stream\" });\n const el = document.createElement(\"a\");\n el.style.display = \"none\";\n el.href = URL.createObjectURL(blob);\n el.download = \"custom_avatar.glb\";\n el.click();\n el.remove();\n } else {\n console.log(gltf);\n }\n },\n { binary, animations }\n );\n };\n})();\n\nfunction addNonDuplicateAnimationClips(clone, scene) {\n const clipsToAdd = [];\n\n for (const clip of scene.animations) {\n const index = clone.animations.findIndex((clonedAnimation) => {\n return clonedAnimation.name === clip.name;\n });\n if (index === -1) {\n clipsToAdd.push(clip);\n }\n }\n\n for (const clip of clipsToAdd) {\n clone.animations.push(clip);\n }\n}\n\nfunction cloneIntoAvatar(avatarGroup) {\n const clonedScene = new THREE.Group();\n clonedScene.name = \"Scene\";\n\n // Combine the root \"Scene\" nodes\n const scenes = avatarGroup.children\n .map((o) => {\n return findChildByName(o, \"Scene\");\n })\n .filter((o) => !!o);\n for (const scene of scenes) {\n addNonDuplicateAnimationClips(clonedScene, scene);\n }\n\n // Combine the \"AvatarRoot\" nodes\n const avatarRoots = avatarGroup.children\n .map((o) => {\n return findChildByName(o, \"AvatarRoot\");\n })\n .filter((o) => !!o);\n const clonedAvatarRoot = avatarRoots[0].clone(false);\n for (const avatarRoot of avatarRoots) {\n clonedAvatarRoot.userData = combineHubsComponents(clonedAvatarRoot.userData, avatarRoot.userData);\n }\n\n // Clone skinned meshes, bind them to a new skeleton\n const clonedSkinnedMeshes = findChildrenByType(avatarGroup, \"SkinnedMesh\").map((o) => {\n return o.clone(false);\n });\n const clonedSkeleton = cloneSkeleton(clonedSkinnedMeshes[0]);\n for (const skinnedMesh of clonedSkinnedMeshes) {\n skinnedMesh.bind(clonedSkeleton);\n }\n\n // Combine clones\n clonedScene.add(clonedAvatarRoot);\n clonedAvatarRoot.add(clonedSkeleton.bones[0]); // Assume bones[0] is root bone\n for (const skinnedMesh of clonedSkinnedMeshes) {\n clonedAvatarRoot.add(skinnedMesh);\n }\n return clonedScene;\n}\n\nexport function exportAvatar(avatarGroup) {\n const avatar = cloneIntoAvatar(avatarGroup);\n console.log(describeObject3D(avatar));\n console.log(avatar);\n exportGLTF(avatar, { binary: false, animations: avatar.animations });\n exportGLTF(avatar, { binary: true, animations: avatar.animations });\n}\n","import * as THREE from \"three\";\nimport { OrbitControls } from \"three/examples/jsm/controls/OrbitControls\";\nimport { GLTFExporter } from \"three/examples/jsm/exporters/GLTFExporter\";\nimport constants from \"./constants\";\nimport { exportAvatar } from \"./export\";\nimport { loadGLTF, forEachMaterial, generateEnvironmentMap, createSky } from \"./utils\";\n\n// TODO: Don't do this\nfunction urlFor(value) {\n if (value.startsWith(\"blob\")) {\n return value;\n } else {\n return `assets/${value}.glb`;\n }\n}\n\nconst state = {\n DOMContentLoaded: false,\n shouldResize: true,\n didInit: false,\n scene: null,\n camera: null,\n renderer: null,\n controls: null,\n envMap: null,\n avatarNodes: {},\n avatarConfig: {},\n newAvatarConfig: {},\n shouldApplyNewAvatarConfig: false,\n shouldExportAvatar: false,\n shouldResetView: false,\n};\nwindow.gameState = state;\n\nwindow.addEventListener(\"DOMContentLoaded\", () => {\n state.DOMContentLoaded = true;\n});\nwindow.onresize = () => {\n state.shouldResize = true;\n};\ndocument.addEventListener(constants.avatarConfigChanged, (e) => {\n state.newAvatarConfig = e.detail.avatarConfig;\n state.shouldApplyNewAvatarConfig = true;\n});\ndocument.addEventListener(constants.exportAvatar, () => {\n state.shouldExportAvatar = true;\n});\ndocument.addEventListener(constants.resetView, () => {\n state.shouldResetView = true;\n});\n\nfunction resetView() {\n state.controls.reset();\n}\n\nfunction init() {\n THREE.Cache.enabled = true;\n\n const scene = new THREE.Scene();\n scene.fog = new THREE.FogExp2(0x8b8b8a, 0.2);\n scene.background = new THREE.Color(0x8b8b8a);\n state.scene = scene;\n\n const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);\n camera.position.set(0, 0.25, 1.5);\n state.camera = camera;\n\n const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);\n scene.add(ambientLight);\n\n // TODO: Square this with react\n const renderer = new THREE.WebGLRenderer({ canvas: document.getElementById(\"scene\"), antialias: true });\n state.renderer = renderer;\n\n const sky = createSky();\n state.envMap = generateEnvironmentMap(sky, renderer);\n\n const floor = new THREE.Mesh(new THREE.PlaneBufferGeometry(100, 100), new THREE.MeshStandardMaterial());\n floor.position.y = -0.2;\n floor.rotation.x = -Math.PI / 2;\n scene.add(floor);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.target = new THREE.Vector3(0, 0.5, 0);\n controls.update();\n controls.saveState();\n state.controls = controls;\n\n state.avatarGroup = new THREE.Group();\n scene.add(state.avatarGroup);\n}\n\nasync function loadIntoGroup(category, part, group) {\n const gltf = await loadGLTF(urlFor(part));\n if (state.avatarConfig[category] !== part) return;\n\n // TODO: Multiple of these might be in flight at any given time.\n gltf.scene.animations = gltf.animations;\n group.clear();\n group.add(gltf.scene);\n\n gltf.scene.traverse((obj) => {\n forEachMaterial(obj, (material) => {\n if (material.isMeshStandardMaterial) {\n material.envMap = state.envMap;\n material.needsUpdate = true;\n }\n });\n });\n}\n\nfunction tick(time) {\n {\n if (state.DOMContentLoaded && !state.didInit) {\n state.didInit = true;\n init();\n }\n if (!state.didInit) {\n requestAnimationFrame(tick);\n return;\n }\n }\n\n {\n if (state.shouldResize) {\n state.shouldResize = false;\n const { renderer, camera } = state;\n\n const width = renderer.domElement.parentNode.clientWidth;\n const height = renderer.domElement.parentNode.clientHeight;\n renderer.setSize(width, height, false);\n camera.aspect = width / height;\n camera.updateProjectionMatrix();\n }\n }\n\n {\n const { renderer, scene, camera } = state;\n renderer.render(scene, camera);\n }\n\n {\n if (state.shouldApplyNewAvatarConfig) {\n state.shouldApplyNewAvatarConfig = false;\n\n const categories = new Set(Object.keys(state.newAvatarConfig).concat(Object.keys(state.avatarConfig)));\n\n for (const category of categories) {\n if (!state.avatarNodes[category]) {\n state.avatarNodes[category] = new THREE.Group();\n state.avatarGroup.add(state.avatarNodes[category]);\n }\n\n if (state.newAvatarConfig[category] !== state.avatarConfig[category]) {\n if (state.newAvatarConfig[category] !== null) {\n loadIntoGroup(category, state.newAvatarConfig[category], state.avatarNodes[category]);\n } else {\n state.avatarNodes[category].clear();\n }\n state.avatarConfig[category] = state.newAvatarConfig[category];\n }\n }\n }\n }\n\n {\n if (state.shouldExportAvatar) {\n state.shouldExportAvatar = false;\n exportAvatar(state.avatarGroup);\n }\n }\n\n {\n if (state.shouldResetView) {\n state.shouldResetView = false;\n resetView();\n }\n }\n\n {\n window.requestAnimationFrame(tick);\n }\n}\n\nwindow.requestAnimationFrame(tick);\n","export default {\n \"Accessory\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"accessory_duck-floaty\",\n \"displayName\": \"Duck Floaty\"\n },\n {\n \"value\": \"accessory_face-mask-1-animated\",\n \"displayName\": \"Face Mask 1 Animated\"\n },\n {\n \"value\": \"accessory_headband-cat-ears-1\",\n \"displayName\": \"Headband Cat Ears 1\"\n },\n {\n \"value\": \"accessory_headphones-1-black\",\n \"displayName\": \"Headphones 1 Black\"\n },\n {\n \"value\": \"accessory_pool-mask-1\",\n \"displayName\": \"Pool Mask 1\"\n }\n ],\n \"Earring\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"earring_hoop-high-left-silver\",\n \"displayName\": \"Hoop High Left Silver\"\n },\n {\n \"value\": \"earring_hoop-high-right-silver\",\n \"displayName\": \"Hoop High Right Silver\"\n },\n {\n \"value\": \"earring_hoop-large-both-gold\",\n \"displayName\": \"Hoop Large Both Gold\"\n },\n {\n \"value\": \"earring_hoop-small-both-gold\",\n \"displayName\": \"Hoop Small Both Gold\"\n }\n ],\n \"Eyebrows\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"eyebrows_brown\",\n \"displayName\": \"Brown\"\n }\n ],\n \"Eyes\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"eyes_style-1-blue\",\n \"displayName\": \"Style 1 Blue\"\n },\n {\n \"value\": \"eyes_style-1-brown\",\n \"displayName\": \"Style 1 Brown\"\n },\n {\n \"value\": \"eyes_style-11-blue\",\n \"displayName\": \"Style 11 Blue\"\n },\n {\n \"value\": \"eyes_style-11-brown\",\n \"displayName\": \"Style 11 Brown\"\n },\n {\n \"value\": \"eyes_style-12-blue\",\n \"displayName\": \"Style 12 Blue\"\n },\n {\n \"value\": \"eyes_style-12-brown\",\n \"displayName\": \"Style 12 Brown\"\n },\n {\n \"value\": \"eyes_style-12-green\",\n \"displayName\": \"Style 12 Green\"\n },\n {\n \"value\": \"eyes_style-13-blue\",\n \"displayName\": \"Style 13 Blue\"\n },\n {\n \"value\": \"eyes_style-13-brown\",\n \"displayName\": \"Style 13 Brown\"\n },\n {\n \"value\": \"eyes_style-14-blue\",\n \"displayName\": \"Style 14 Blue\"\n },\n {\n \"value\": \"eyes_style-14-brown\",\n \"displayName\": \"Style 14 Brown\"\n }\n ],\n \"Eyewear\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"eyewear_arnette\",\n \"displayName\": \"Arnette\"\n },\n {\n \"value\": \"eyewear_aviators1\",\n \"displayName\": \"Aviators1\"\n },\n {\n \"value\": \"eyewear_glam-2\",\n \"displayName\": \"Glam 2\"\n },\n {\n \"value\": \"eyewear_heart-1-pink\",\n \"displayName\": \"Heart 1 Pink\"\n },\n {\n \"value\": \"eyewear_metal-1\",\n \"displayName\": \"Metal 1\"\n },\n {\n \"value\": \"eyewear_oakleys-red\",\n \"displayName\": \"Oakleys Red\"\n },\n {\n \"value\": \"eyewear_punk-2\",\n \"displayName\": \"Punk 2\"\n },\n {\n \"value\": \"eyewear_wire-frame-1-gold\",\n \"displayName\": \"Wire Frame 1 Gold\"\n }\n ],\n \"Facial Hair\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"facial-hair_beard-full-1-dark\",\n \"displayName\": \"Beard Full 1 Dark\"\n },\n {\n \"value\": \"facial-hair_beard-full-2-brown\",\n \"displayName\": \"Beard Full 2 Brown\"\n },\n {\n \"value\": \"facial-hair_goatee-1-brown\",\n \"displayName\": \"Goatee 1 Brown\"\n },\n {\n \"value\": \"facial-hair_goatee-2\",\n \"displayName\": \"Goatee 2\"\n },\n {\n \"value\": \"facial-hair_goatee-3\",\n \"displayName\": \"Goatee 3\"\n },\n {\n \"value\": \"facial-hair_goatee-4\",\n \"displayName\": \"Goatee 4\"\n },\n {\n \"value\": \"facial-hair_goatee-5\",\n \"displayName\": \"Goatee 5\"\n },\n {\n \"value\": \"facial-hair_mustache-1\",\n \"displayName\": \"Mustache 1\"\n },\n {\n \"value\": \"facial-hair_mustache-2\",\n \"displayName\": \"Mustache 2\"\n }\n ],\n \"Hair\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"hair_aLine-asym\",\n \"displayName\": \"ALine Asym\"\n },\n {\n \"value\": \"hair_afro-1\",\n \"displayName\": \"Afro 1\"\n },\n {\n \"value\": \"hair_afro-2\",\n \"displayName\": \"Afro 2\"\n },\n {\n \"value\": \"hair_bob-1-dark\",\n \"displayName\": \"Bob 1 Dark\"\n },\n {\n \"value\": \"hair_bob-1-light\",\n \"displayName\": \"Bob 1 Light\"\n },\n {\n \"value\": \"hair_bob-1-red\",\n \"displayName\": \"Bob 1 Red\"\n },\n {\n \"value\": \"hair_braided-bun\",\n \"displayName\": \"Braided Bun\"\n },\n {\n \"value\": \"hair_eraser-top\",\n \"displayName\": \"Eraser Top\"\n },\n {\n \"value\": \"hair_fauxhawk-1\",\n \"displayName\": \"Fauxhawk 1\"\n },\n {\n \"value\": \"hair_flat-top-1\",\n \"displayName\": \"Flat Top 1\"\n },\n {\n \"value\": \"hair_french-braid-buns\",\n \"displayName\": \"French Braid Buns\"\n },\n {\n \"value\": \"hair_french-braids-double\",\n \"displayName\": \"French Braids Double\"\n },\n {\n \"value\": \"hair_male_taperAfro1\",\n \"displayName\": \"Male\"\n },\n {\n \"value\": \"hair_mohawk-1-blue\",\n \"displayName\": \"Mohawk 1 Blue\"\n },\n {\n \"value\": \"hair_mullet-1-dark\",\n \"displayName\": \"Mullet 1 Dark\"\n },\n {\n \"value\": \"hair_parted-1-brown\",\n \"displayName\": \"Parted 1 Brown\"\n },\n {\n \"value\": \"hair_parted-1-gray\",\n \"displayName\": \"Parted 1 Gray\"\n },\n {\n \"value\": \"hair_parted-long-1\",\n \"displayName\": \"Parted Long 1\"\n },\n {\n \"value\": \"hair_pigtails-1-blue\",\n \"displayName\": \"Pigtails 1 Blue\"\n },\n {\n \"value\": \"hair_pigtails-1-pink\",\n \"displayName\": \"Pigtails 1 Pink\"\n },\n {\n \"value\": \"hair_pony-tail-1\",\n \"displayName\": \"Pony Tail 1\"\n },\n {\n \"value\": \"hair_pony-tail-2\",\n \"displayName\": \"Pony Tail 2\"\n },\n {\n \"value\": \"hair_pony-tail-3\",\n \"displayName\": \"Pony Tail 3\"\n },\n {\n \"value\": \"hair_spikey-1\",\n \"displayName\": \"Spikey 1\"\n },\n {\n \"value\": \"hair_starter-locs-red\",\n \"displayName\": \"Starter Locs Red\"\n }\n ],\n \"Hands\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"hands_skin-1\",\n \"displayName\": \"Skin 1\"\n },\n {\n \"value\": \"hands_skin-2\",\n \"displayName\": \"Skin 2\"\n },\n {\n \"value\": \"hands_skin-3\",\n \"displayName\": \"Skin 3\"\n },\n {\n \"value\": \"hands_skin-4\",\n \"displayName\": \"Skin 4\"\n },\n {\n \"value\": \"hands_skin-5\",\n \"displayName\": \"Skin 5\"\n },\n {\n \"value\": \"hands_skin-6\",\n \"displayName\": \"Skin 6\"\n },\n {\n \"value\": \"hands_skin-7\",\n \"displayName\": \"Skin 7\"\n },\n {\n \"value\": \"hands_skin-8\",\n \"displayName\": \"Skin 8\"\n },\n {\n \"value\": \"hands_skin-a\",\n \"displayName\": \"Skin A\"\n },\n {\n \"value\": \"hands_skin-b\",\n \"displayName\": \"Skin B\"\n },\n {\n \"value\": \"hands_skin-c\",\n \"displayName\": \"Skin C\"\n },\n {\n \"value\": \"hands_skin-d\",\n \"displayName\": \"Skin D\"\n },\n {\n \"value\": \"hands_skin-e\",\n \"displayName\": \"Skin E\"\n },\n {\n \"value\": \"hands_skin-f\",\n \"displayName\": \"Skin F\"\n },\n {\n \"value\": \"hands_skin-g\",\n \"displayName\": \"Skin G\"\n },\n {\n \"value\": \"hands_skin-h\",\n \"displayName\": \"Skin H\"\n }\n ],\n \"Hat\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"hat_baseball-giants\",\n \"displayName\": \"Baseball Giants\"\n },\n {\n \"value\": \"hat_beach-umbrella\",\n \"displayName\": \"Beach Umbrella\"\n },\n {\n \"value\": \"hat_beanie-1-red\",\n \"displayName\": \"Beanie 1 Red\"\n },\n {\n \"value\": \"hat_spokemon\",\n \"displayName\": \"Spokemon\"\n },\n {\n \"value\": \"hat_top-hat-1\",\n \"displayName\": \"Top Hat 1\"\n }\n ],\n \"Head\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"head_skin-1\",\n \"displayName\": \"Skin 1\"\n },\n {\n \"value\": \"head_skin-2\",\n \"displayName\": \"Skin 2\"\n },\n {\n \"value\": \"head_skin-3\",\n \"displayName\": \"Skin 3\"\n },\n {\n \"value\": \"head_skin-4\",\n \"displayName\": \"Skin 4\"\n },\n {\n \"value\": \"head_skin-5\",\n \"displayName\": \"Skin 5\"\n },\n {\n \"value\": \"head_skin-6\",\n \"displayName\": \"Skin 6\"\n },\n {\n \"value\": \"head_skin-7\",\n \"displayName\": \"Skin 7\"\n },\n {\n \"value\": \"head_skin-8\",\n \"displayName\": \"Skin 8\"\n },\n {\n \"value\": \"head_skin-a\",\n \"displayName\": \"Skin A\"\n },\n {\n \"value\": \"head_skin-b\",\n \"displayName\": \"Skin B\"\n },\n {\n \"value\": \"head_skin-c\",\n \"displayName\": \"Skin C\"\n },\n {\n \"value\": \"head_skin-d\",\n \"displayName\": \"Skin D\"\n },\n {\n \"value\": \"head_skin-e\",\n \"displayName\": \"Skin E\"\n },\n {\n \"value\": \"head_skin-f\",\n \"displayName\": \"Skin F\"\n },\n {\n \"value\": \"head_skin-g\",\n \"displayName\": \"Skin G\"\n },\n {\n \"value\": \"head_skin-h\",\n \"displayName\": \"Skin H\"\n }\n ],\n \"Mouth\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"mouth_neutral-skin-1\",\n \"displayName\": \"Neutral Skin 1\"\n },\n {\n \"value\": \"mouth_neutral-skin-2\",\n \"displayName\": \"Neutral Skin 2\"\n },\n {\n \"value\": \"mouth_neutral-skin-3\",\n \"displayName\": \"Neutral Skin 3\"\n },\n {\n \"value\": \"mouth_neutral-skin-4\",\n \"displayName\": \"Neutral Skin 4\"\n },\n {\n \"value\": \"mouth_neutral-skin-5\",\n \"displayName\": \"Neutral Skin 5\"\n },\n {\n \"value\": \"mouth_neutral-skin-7\",\n \"displayName\": \"Neutral Skin 7\"\n },\n {\n \"value\": \"mouth_neutral-skin-8\",\n \"displayName\": \"Neutral Skin 8\"\n },\n {\n \"value\": \"mouth_neutral-skin-a\",\n \"displayName\": \"Neutral Skin A\"\n },\n {\n \"value\": \"mouth_neutral-skin-b\",\n \"displayName\": \"Neutral Skin B\"\n },\n {\n \"value\": \"mouth_neutral-skin-c\",\n \"displayName\": \"Neutral Skin C\"\n },\n {\n \"value\": \"mouth_neutral-skin-d\",\n \"displayName\": \"Neutral Skin D\"\n },\n {\n \"value\": \"mouth_neutral-skin-e\",\n \"displayName\": \"Neutral Skin E\"\n },\n {\n \"value\": \"mouth_neutral-skin-f\",\n \"displayName\": \"Neutral Skin F\"\n },\n {\n \"value\": \"mouth_neutral-skin-g\",\n \"displayName\": \"Neutral Skin G\"\n },\n {\n \"value\": \"mouth_neutral-skin-h\",\n \"displayName\": \"Neutral Skin H\"\n },\n {\n \"value\": \"mouth_smirk-skin-1\",\n \"displayName\": \"Smirk Skin 1\"\n },\n {\n \"value\": \"mouth_smirk-skin-2\",\n \"displayName\": \"Smirk Skin 2\"\n },\n {\n \"value\": \"mouth_smirk-skin-3\",\n \"displayName\": \"Smirk Skin 3\"\n },\n {\n \"value\": \"mouth_smirk-skin-4\",\n \"displayName\": \"Smirk Skin 4\"\n },\n {\n \"value\": \"mouth_smirk-skin-5\",\n \"displayName\": \"Smirk Skin 5\"\n },\n {\n \"value\": \"mouth_smirk-skin-6\",\n \"displayName\": \"Smirk Skin 6\"\n },\n {\n \"value\": \"mouth_smirk-skin-7\",\n \"displayName\": \"Smirk Skin 7\"\n },\n {\n \"value\": \"mouth_smirk-skin-8\",\n \"displayName\": \"Smirk Skin 8\"\n },\n {\n \"value\": \"mouth_smirk-skin-a\",\n \"displayName\": \"Smirk Skin A\"\n },\n {\n \"value\": \"mouth_smirk-skin-b\",\n \"displayName\": \"Smirk Skin B\"\n },\n {\n \"value\": \"mouth_smirk-skin-c\",\n \"displayName\": \"Smirk Skin C\"\n },\n {\n \"value\": \"mouth_smirk-skin-d\",\n \"displayName\": \"Smirk Skin D\"\n },\n {\n \"value\": \"mouth_smirk-skin-e\",\n \"displayName\": \"Smirk Skin E\"\n },\n {\n \"value\": \"mouth_smirk-skin-f\",\n \"displayName\": \"Smirk Skin F\"\n },\n {\n \"value\": \"mouth_smirk-skin-g\",\n \"displayName\": \"Smirk Skin G\"\n },\n {\n \"value\": \"mouth_smirk-skin-h\",\n \"displayName\": \"Smirk Skin H\"\n }\n ],\n \"Torso Jacket\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": false\n },\n {\n \"value\": \"torso-jacket_style-1-punk-leather-1-black\",\n \"displayName\": \"Style 1 Punk Leather 1 Black\"\n }\n ],\n \"Torso\": [\n {\n \"value\": null,\n \"displayName\": \"none\",\n \"excludeFromRandomize\": true\n },\n {\n \"value\": \"torso_style-1-baseball-giants\",\n \"displayName\": \"Style 1 Baseball Giants\"\n },\n {\n \"value\": \"torso_style-1-bowling-shirt-1-red\",\n \"displayName\": \"Style 1 Bowling Shirt 1 Red\"\n },\n {\n \"value\": \"torso_style-1-combat-vest-red\",\n \"displayName\": \"Style 1 Combat Vest Red\"\n },\n {\n \"value\": \"torso_style-1-ketchum\",\n \"displayName\": \"Style 1 Ketchum\"\n },\n {\n \"value\": \"torso_style-1-sport-coat-1-dark\",\n \"displayName\": \"Style 1 Sport Coat 1 Dark\"\n },\n {\n \"value\": \"torso_style-1-sport-coat-1-gray\",\n \"displayName\": \"Style 1 Sport Coat 1 Gray\"\n },\n {\n \"value\": \"torso_style-1-tshirt-moz\",\n \"displayName\": \"Style 1 Tshirt Moz\"\n },\n {\n \"value\": \"torso_style-1-tshirt-union-jack\",\n \"displayName\": \"Style 1 Tshirt Union Jack\"\n },\n {\n \"value\": \"torso_style-1-tshirt1-reactor\",\n \"displayName\": \"Style 1 Tshirt1 Reactor\"\n },\n {\n \"value\": \"torso_style-1-ugly-christmas-1\",\n \"displayName\": \"Style 1 Ugly Christmas 1\"\n },\n {\n \"value\": \"torso_style-2-hoodie-1-gray\",\n \"displayName\": \"Style 2 Hoodie 1 Gray\"\n },\n {\n \"value\": \"torso_style-2-hoodie-2-purple\",\n \"displayName\": \"Style 2 Hoodie 2 Purple\"\n },\n {\n \"value\": \"torso_style-2-tshirt-1-baby-unicorn\",\n \"displayName\": \"Style 2 Tshirt 1 Baby Unicorn\"\n },\n {\n \"value\": \"torso_style-2-tshirt-1-heart-animated\",\n \"displayName\": \"Style 2 Tshirt 1 Heart Animated\"\n },\n {\n \"value\": \"torso_style-2-tshirt-1-heart\",\n \"displayName\": \"Style 2 Tshirt 1 Heart\"\n },\n {\n \"value\": \"torso_style-2-tshirt-1-moz\",\n \"displayName\": \"Style 2 Tshirt 1 Moz\"\n }\n ]\n};","import React, { useState, useEffect } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport \"./game\";\nimport constants from \"./constants\";\nimport initialAssets from \"./assets\";\n\nfunction AvatarPartSelector({ onPartSelected, parts, selected }) {\n return (\n {\n onPartSelected(e.target.selectedOptions[0].getAttribute(\"value\"));\n }}\n value={selected || \"\"}\n >\n {parts.map((part, i) => (\n \n ))}\n \n );\n}\n\nfunction App() {\n const [assets, setAssets] = useState(initialAssets);\n\n const categories = Object.keys(assets);\n\n function generateRandomConfig() {\n const newConfig = {};\n for (const category of categories) {\n const categoryAssets = assets[category].filter(part => !part.excludeFromRandomize);\n if (categoryAssets.length === 0) continue;\n const randomIndex = Math.floor(Math.random() * categoryAssets.length);\n newConfig[category] = categoryAssets[randomIndex].value;\n }\n return newConfig;\n }\n\n const initialAvatarConfig = generateRandomConfig();\n const [avatarConfig, setAvatarConfig] = useState(initialAvatarConfig);\n\n function onGLBUploaded(e) {\n const file = e.target.files[0];\n const filename = file.name;\n const category = filename.substring(0, filename.indexOf(\"_\")) || \"custom\";\n const displayName = filename.substring(filename.indexOf(\"_\") + 1, filename.lastIndexOf(\".\"));\n const url = URL.createObjectURL(file);\n\n const clone = { ...assets };\n clone[category] = clone[category] || [\n {\n displayName: \"none\",\n value: null,\n },\n ];\n clone[category].push({\n displayName,\n value: url,\n });\n setAssets(clone);\n\n updateAvatarConfig({ [category]: url });\n }\n\n useEffect(() => {\n document.dispatchEvent(new CustomEvent(constants.avatarConfigChanged, { detail: { avatarConfig } }));\n });\n\n function updateAvatarConfig(newConfig) {\n setAvatarConfig({ ...avatarConfig, ...newConfig });\n }\n\n function randomizeConfig() {\n setAvatarConfig(generateRandomConfig());\n }\n\n function dispatchExport() {\n document.dispatchEvent(new CustomEvent(constants.exportAvatar));\n }\n\n function dispatchResetView() {\n document.dispatchEvent(new CustomEvent(constants.resetView));\n }\n\n return (\n <>\n {categories.map((category) => (\n
\n {category}: \n {\n updateAvatarConfig({ [category]: selection });\n }}\n parts={assets[category]}\n />\n
\n ))}\n \n \n \n \n \n );\n}\n\nReactDOM.render(, document.getElementById(\"root\"));\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tif(__webpack_module_cache__[moduleId]) {\n\t\treturn __webpack_module_cache__[moduleId].exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n// the startup function\n// It's empty as some runtime module handles the default behavior\n__webpack_require__.x = x => {}\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// Promise = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t179: 0\n};\n\nvar deferredModules = [\n\t[810,536]\n];\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\nvar checkDeferredModules = x => {};\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime, executeModules] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0, resolves = [];\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tresolves.push(installedChunks[chunkId][0]);\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\tfor(moduleId in moreModules) {\n\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t}\n\t}\n\tif(runtime) runtime(__webpack_require__);\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\twhile(resolves.length) {\n\t\tresolves.shift()();\n\t}\n\n\t// add entry modules from loaded chunk to deferred list\n\tif(executeModules) deferredModules.push.apply(deferredModules, executeModules);\n\n\t// run deferred modules when all chunks ready\n\treturn checkDeferredModules();\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunk\"] = self[\"webpackChunk\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));\n\nfunction checkDeferredModulesImpl() {\n\tvar result;\n\tfor(var i = 0; i < deferredModules.length; i++) {\n\t\tvar deferredModule = deferredModules[i];\n\t\tvar fulfilled = true;\n\t\tfor(var j = 1; j < deferredModule.length; j++) {\n\t\t\tvar depId = deferredModule[j];\n\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferredModules.splice(i--, 1);\n\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n\t\t}\n\t}\n\tif(deferredModules.length === 0) {\n\t\t__webpack_require__.x();\n\t\t__webpack_require__.x = x => {};\n\t}\n\treturn result;\n}\nvar startup = __webpack_require__.x;\n__webpack_require__.x = () => {\n\t// reset startup function so it can be called again when more startup code is added\n\t__webpack_require__.x = startup || (x => {});\n\treturn (checkDeferredModules = checkDeferredModulesImpl)();\n};","// run startup\n__webpack_require__.x();\n"],"sourceRoot":""} \ No newline at end of file diff --git a/index.html b/index.html index acfacee..23a3c87 100644 --- a/index.html +++ b/index.html @@ -45,4 +45,4 @@ label { display: block; - }
\ No newline at end of file + }
\ No newline at end of file diff --git a/src/constants.js b/src/constants.js index af0f0b7..34a2600 100644 --- a/src/constants.js +++ b/src/constants.js @@ -2,4 +2,8 @@ export default { avatarConfigChanged: "avatarConfigChanged", exportAvatar: "exportAvatar", resetView: "resetView", + saveView: "saveView", + deleteView: "deleteView", + goNextView: "goNextView", + goPreviousView: "goPreviousView", }; diff --git a/src/game.js b/src/game.js index da0fa52..21d2ef5 100644 --- a/src/game.js +++ b/src/game.js @@ -4,6 +4,8 @@ import { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter"; import constants from "./constants"; import { exportAvatar } from "./export"; import { loadGLTF, forEachMaterial, generateEnvironmentMap, createSky } from "./utils"; +import { createSnapshot, snapTo } from "./orbit-controls-utils"; +import initialSnapshots from "./snapshots"; // TODO: Don't do this function urlFor(value) { @@ -29,6 +31,11 @@ const state = { shouldApplyNewAvatarConfig: false, shouldExportAvatar: false, shouldResetView: false, + shouldSaveView: false, + shouldGoNextView: false, + shouldGoPreviousView: false, + snapshots: initialSnapshots, + viewIndex: 0, }; window.gameState = state; @@ -48,6 +55,34 @@ document.addEventListener(constants.exportAvatar, () => { document.addEventListener(constants.resetView, () => { state.shouldResetView = true; }); +document.addEventListener(constants.saveView, () => { + state.shouldSaveView = true; +}); +document.addEventListener(constants.deleteView, () => { + state.shouldDeleteView = true; +}); +document.addEventListener(constants.goNextView, () => { + state.shouldGoNextView = true; +}); +document.addEventListener(constants.goPreviousView, () => { + state.shouldGoPreviousView = true; +}); +document.addEventListener("keydown", (e) => { + switch (e.key.toLowerCase()) { + case "s": + document.dispatchEvent(new CustomEvent(constants.saveView)); + break; + case "d": + document.dispatchEvent(new CustomEvent(constants.deleteView)); + break; + case "k": + document.dispatchEvent(new CustomEvent(constants.goPreviousView)); + break; + case "j": + document.dispatchEvent(new CustomEvent(constants.goNextView)); + break; + } +}); function resetView() { state.controls.reset(); @@ -134,11 +169,6 @@ function tick(time) { } } - { - const { renderer, scene, camera } = state; - renderer.render(scene, camera); - } - { if (state.shouldApplyNewAvatarConfig) { state.shouldApplyNewAvatarConfig = false; @@ -177,6 +207,43 @@ function tick(time) { } } + if (state.shouldSaveView) { + state.shouldSaveView = false; + const { snapshots, controls } = state; + snapshots.push(createSnapshot(controls)); + state.viewIndex = snapshots.length - 1; + } + if (state.shouldDeleteView) { + state.shouldDeleteView = false; + const { snapshots, controls } = state; + if (snapshots.length && state.viewIndex < snapshots.length) { + snapshots.splice(state.viewIndex, 1); + state.shouldGoPreviousView = true; + } + } + + if (state.shouldGoNextView) { + state.shouldGoNextView = false; + const { snapshots, controls } = state; + if (snapshots.length) { + state.viewIndex = (state.viewIndex + 1) % snapshots.length; + snapTo(controls, snapshots[state.viewIndex]); + } + } + if (state.shouldGoPreviousView) { + state.shouldGoPreviousView = false; + const { snapshots, controls } = state; + if (snapshots.length) { + state.viewIndex = (state.viewIndex + snapshots.length - 1) % snapshots.length; + snapTo(controls, snapshots[state.viewIndex]); + } + } + + { + const { renderer, scene, camera } = state; + renderer.render(scene, camera); + } + { window.requestAnimationFrame(tick); } diff --git a/src/snapshots.js b/src/snapshots.js new file mode 100644 index 0000000..6325e48 --- /dev/null +++ b/src/snapshots.js @@ -0,0 +1,44 @@ +export default [ + { target: { x: 0, y: 0.5, z: 0 }, position: { x: 0, y: 0.25, z: 1.5 }, zoom: 1 }, + { + target: { x: 0.02307116018084527, y: 0.6334402516427525, z: 0.022240041940458772 }, + position: { x: 0.02307116018084527, y: 0.5176174441028143, z: 0.7171768871800882 }, + zoom: 1, + }, + { + target: { x: 0.09387002157314916, y: 0.546635562471844, z: 0.08014199094868098 }, + position: { x: -0.3879717518873724, y: 0.4947348350813956, z: 0.5914999491959408 }, + zoom: 1, + }, + { + target: { x: -0.09493661261301585, y: 0.5639529591055843, z: 0.1055502022610856 }, + position: { x: -0.671104818392942, y: 1.0921215489830267, z: -0.6936061291504049 }, + zoom: 1, + }, + { + target: { x: -0.008422856623338703, y: 0.4941459483505538, z: 0.10198716075212154 }, + position: { x: -0.011493544628165472, y: 0.5417760987144405, z: -0.9057404120118234 }, + zoom: 1, + }, + { + target: { x: -0.008422856623338703, y: 0.4941459483505538, z: 0.10198716075212154 }, + position: { x: 0.9967533644672771, y: 0.5785843629152699, z: 0.1188347112272661 }, + zoom: 1, + }, + { + target: { x: 0.04413113687842558, y: 0.49809272819211714, z: 0.06414813223383779 }, + position: { x: 0.42686384587556403, y: 0.5905893343933903, z: 0.6053669965717776 }, + zoom: 1, + }, + { + target: { x: 0.41859185291264084, y: 0.31485181426204567, z: -0.08600123811976045 }, + position: { x: 0.6482708508647577, y: 0.4157154496534844, z: 0.22650580642214352 }, + zoom: 1, + }, + { + target: { x: 0.018173720594482693, y: 0.44480533951578716, z: -0.15500048584516604 }, + position: { x: 0.001957996317477624, y: 0.8078606430954935, z: 0.7318399779720074 }, + zoom: 1, + }, + { target: { x: 0, y: 0.5, z: 0 }, position: { x: 0, y: 0.35779997693088517, z: 0.8532001384146891 }, zoom: 1 }, +];