diff --git a/src/assets/avatars/Bot_Skinned.glb b/src/assets/avatars/Bot_Skinned.glb new file mode 100644 index 0000000000000000000000000000000000000000..57359b98846076489c5291bec596cd17e04b65c0 Binary files /dev/null and b/src/assets/avatars/Bot_Skinned.glb differ diff --git a/src/components/model-inflator.js b/src/components/model-inflator.js new file mode 100644 index 0000000000000000000000000000000000000000..bb9f85b0f9ee26999b67a3b5fdf1b08255a3be4d --- /dev/null +++ b/src/components/model-inflator.js @@ -0,0 +1,64 @@ +const inflateEntities = function(idPrefix, componentMappings, parentEl, node) { + // setObject3D mutates the node's parent, so we have to copy + const children = node.children.slice(0); + + const el = document.createElement("a-entity"); + el.id = idPrefix + node.name; + parentEl.appendChild(el); + + // // Copy over transform to the THREE.Group and reset the actual transform of the Object3D + el.setAttribute("position", { + x: node.position.x, + y: node.position.y, + z: node.position.z + }); + el.setAttribute("rotation", { + x: node.rotation.x * THREE.Math.RAD2DEG, + y: node.rotation.y * THREE.Math.RAD2DEG, + z: node.rotation.z * THREE.Math.RAD2DEG + }); + el.setAttribute("scale", { + x: node.scale.x, + y: node.scale.y, + z: node.scale.z + }); + + node.position.set(0, 0, 0); + node.rotation.set(0, 0, 0); + node.scale.set(1, 1, 1); + + el.setObject3D(node.type.toLowerCase(), node); + + if (componentMappings && componentMappings[node.name]) { + const components = componentMappings[node.name]; + for (const componentName of Object.keys(components)) { + el.setAttribute(componentName, components[componentName]); + } + } + + children.forEach(childNode => { + inflateEntities(idPrefix, componentMappings, el, childNode); + }); +}; + +AFRAME.registerComponent("model-inflator", { + schema: { + idPrefix: { type: "string" } + }, + init: function() { + const componentMappings = { + RightHand: { + spin: "speed: 1;" + } + }; + + this.el.addEventListener("model-loaded", e => { + inflateEntities( + `${this.data.idPrefix}_`, + componentMappings, + this.el, + e.detail.model + ); + }); + } +}); diff --git a/src/room.js b/src/room.js index e2c1600e9d1fe465a72f4d6bc1642d589ab50d98..29b6a6377944cc3aa58923e963f0f1b3f8806a02 100644 --- a/src/room.js +++ b/src/room.js @@ -34,6 +34,7 @@ import "./components/water"; import "./components/skybox"; import "./components/layers"; import "./components/spawn-controller"; +import "./components/model-inflator"; import "./systems/personal-space-bubble"; import { promptForName, getCookie, parseJwt } from "./utils"; diff --git a/templates/room.hbs b/templates/room.hbs index 63c3f90db866b36c6042a05e10ae0a39befa8998..b98aefa14038b6cfee9c77072666c427d8e0958d 100644 --- a/templates/room.hbs +++ b/templates/room.hbs @@ -44,6 +44,7 @@ light="defaultLightsEnabled: false"> <a-assets> + <a-asset-item id="bot-skinned-mesh" response-type="arraybuffer" src="{{asset "assets/avatars/Bot_Skinned.glb" }}"></a-asset-item> <a-asset-item id="bot-head-mesh" response-type="arraybuffer" src="{{asset "assets/avatars/Bot_Head_Mesh.glb" }}"></a-asset-item> <a-asset-item id="bot-body-mesh" response-type="arraybuffer" src="{{asset "assets/avatars/Bot_Body_Mesh.glb" }}"></a-asset-item> <a-asset-item id="bot-left-hand-mesh" response-type="arraybuffer" src="{{asset "assets/avatars/Bot_LeftHand_Mesh.glb" }}"></a-asset-item> @@ -174,6 +175,14 @@ ></a-entity> </a-entity> + <a-entity + id="bot-skinned" + cached-gltf-model="#bot-skinned-mesh" + position="0 0 0" + spin + model-inflator="idPrefix: bot;" + ></a-entity> + <!-- Environment --> <a-entity id="meeting-space"