diff --git a/src/assets/stylesheets/scene-ui.scss b/src/assets/stylesheets/scene-ui.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/assets/stylesheets/scene.scss b/src/assets/stylesheets/scene.scss new file mode 100644 index 0000000000000000000000000000000000000000..44e6591aacfa994bb79a4a0354b129ae171c4741 --- /dev/null +++ b/src/assets/stylesheets/scene.scss @@ -0,0 +1,2 @@ +@import 'shared'; +@import 'loader'; diff --git a/src/react-components/scene-ui.js b/src/react-components/scene-ui.js new file mode 100644 index 0000000000000000000000000000000000000000..7164b500add1989b40242c3dc40158958a323c5c --- /dev/null +++ b/src/react-components/scene-ui.js @@ -0,0 +1,66 @@ +import React, { Component } from "react"; +import PropTypes from "prop-types"; +//import classNames from "classnames"; +import { IntlProvider, /*FormattedMessage, */ addLocaleData } from "react-intl"; +import en from "react-intl/locale-data/en"; +import styles from "../assets/stylesheets/scene-ui.scss"; + +import { lang, messages } from "../utils/i18n"; + +addLocaleData([...en]); + +class SceneUI extends Component { + static propTypes = { + store: PropTypes.object, + scene: PropTypes.object, + sceneLoaded: PropTypes.bool, + sceneId: PropTypes.string, + sceneName: PropTypes.string, + sceneDescription: PropTypes.string, + sceneAttribution: PropTypes.string + }; + + state = {}; + + constructor(props) { + super(props); + } + + componentDidMount() { + this.props.scene.addEventListener("loaded", this.onSceneLoaded); + } + + componentWillUnmount() { + this.props.scene.removeEventListener("loaded", this.onSceneLoaded); + } + + onSceneLoaded = () => { + this.setState({ sceneLoaded: true }); + }; + + render() { + if (!this.props.sceneLoaded || !this.props.sceneId) { + return ( + <IntlProvider locale={lang} messages={messages}> + <div className="loading-panel"> + <div className="loader-wrap"> + <div className="loader"> + <div className="loader-center" /> + </div> + </div> + + <img className="loading-panel__logo" src="../assets/images/logo.svg" /> + </div> + </IntlProvider> + ); + } + + return ( + <IntlProvider locale={lang} messages={messages}> + <div className={styles.ui}>hello</div> + </IntlProvider> + ); + } +} + +export default SceneUI; diff --git a/src/scene.html b/src/scene.html new file mode 100644 index 0000000000000000000000000000000000000000..6a4ebaa0f56d91acb74427387016d87a333f78a9 --- /dev/null +++ b/src/scene.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + +<head> + <!-- DO NOT REMOVE/EDIT THIS COMMENT - SCENE_META_TAGS --> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> + + <link rel="shortcut icon" type="image/png" href="/favicon.ico"> + <title>Scene | Hubs by Mozilla</title> + <link href="https://fonts.googleapis.com/css?family=Zilla+Slab:300,300i,400,400i,700" rel="stylesheet"> +</head> + +<body> + <a-scene + renderer="antialias: true; gammaOutput: true; sortObjects: true; physicallyCorrectLights: true;" + vr-mode-ui="enabled: false" + gamma-factor + > + <a-entity + id="scene-root" + static-body="shape: none;" + ></a-entity> + </a-scene> + + <div id="ui-root"></div> +</body> + +</html> diff --git a/src/scene.js b/src/scene.js new file mode 100644 index 0000000000000000000000000000000000000000..d84cb3a447c08c121966b4e247a785209acad3e6 --- /dev/null +++ b/src/scene.js @@ -0,0 +1,107 @@ +console.log(`Hubs version: ${process.env.BUILD_VERSION || "?"}`); + +import "./assets/stylesheets/scene.scss"; + +import "aframe"; +import "./utils/logging"; +import { patchWebGLRenderingContext } from "./utils/webgl"; +patchWebGLRenderingContext(); + +import "three/examples/js/loaders/GLTFLoader"; + +import "./components/skybox"; +import "./components/layers"; +import "./components/debug"; +import "./components/animation-mixer"; +import "./components/loop-animation"; +import "./components/gltf-model-plus"; +import "./components/ambient-light"; +import "./components/directional-light"; +import "./components/hemisphere-light"; +import "./components/point-light"; +import "./components/spot-light"; + +import ReactDOM from "react-dom"; +import React from "react"; +import SceneUI from "./react-components/scene-ui"; +import { disableiOSZoom } from "./utils/disable-ios-zoom"; + +import "./gltf-component-mappings"; + +import { App } from "./App"; + +window.APP = new App(); +window.APP.RENDER_ORDER = { + HUD_BACKGROUND: 1, + HUD_ICONS: 2, + CURSOR: 3 +}; +const store = window.APP.store; + +const qs = new URLSearchParams(location.search); +const isMobile = AFRAME.utils.device.isMobile(); + +window.APP.quality = qs.get("quality") || isMobile ? "low" : "high"; + +import "aframe-physics-system"; +import "aframe-physics-extras"; +import "./components/event-repeater"; +import "./components/controls-shape-offset"; + +import registerTelemetry from "./telemetry"; + +registerTelemetry(); + +disableiOSZoom(); +store.init(); + +function mountUI(scene, props = {}) { + ReactDOM.render( + <SceneUI + {...{ + scene, + store, + ...props + }} + />, + document.getElementById("ui-root") + ); +} + +const onReady = async () => { + const scene = document.querySelector("a-scene"); + window.APP.scene = scene; + + let uiProps = {}; + + mountUI(scene); + + const remountUI = props => { + uiProps = { ...uiProps, ...props }; + mountUI(scene, uiProps); + }; + + const sceneRoot = document.querySelector("#scene-root"); + const sceneModelEntity = document.createElement("a-entity"); + + sceneModelEntity.addEventListener("scene-loaded", () => { + remountUI({ sceneLoaded: true }); + }); + + sceneRoot.appendChild(sceneModelEntity); + + const sceneId = qs.get("scene_id") || document.location.pathname.substring(1).split("/")[0]; + console.log(`Scene ID: ${sceneId}`); + + const sceneUrl = ""; + console.log(`Scene URL: ${sceneUrl}`); + + const gltfEl = document.createElement("a-entity"); + gltfEl.setAttribute("gltf-model-plus", { src: sceneUrl, useCache: false, inflate: true }); + gltfEl.addEventListener("model-loaded", () => sceneModelEntity.emit("scene-loaded")); + sceneModelEntity.appendChild(gltfEl); + + //remountUI({ sceneId: scene.scene_id, sceneName: scene.name, sceneDescription: scene.description, sceneAttribution: scene.attribution }); +}; + +document.addEventListener("DOMContentLoaded", onReady); diff --git a/webpack.config.js b/webpack.config.js index 9531ceb26e70881f4bd4b5af7eb4367e2141f007..4c28ef4a04acaba07f91c52bf7d4bf804de6501d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -64,6 +64,7 @@ module.exports = (env, argv) => ({ entry: { index: path.join(__dirname, "src", "index.js"), hub: path.join(__dirname, "src", "hub.js"), + scene: path.join(__dirname, "src", "scene.js"), link: path.join(__dirname, "src", "link.js"), "avatar-selector": path.join(__dirname, "src", "avatar-selector.js") }, @@ -196,6 +197,20 @@ module.exports = (env, argv) => ({ } ] }), + new HTMLWebpackPlugin({ + filename: "scene.html", + template: path.join(__dirname, "src", "scene.html"), + chunks: ["vendor", "engine", "scene"], + inject: "head", + meta: [ + { + "http-equiv": "origin-trial", + "data-feature": "WebVR (For Chrome M62+)", + "data-expires": process.env.ORIGIN_TRIAL_EXPIRES, + content: process.env.ORIGIN_TRIAL_TOKEN + } + ] + }), new HTMLWebpackPlugin({ filename: "link.html", template: path.join(__dirname, "src", "link.html"),