diff --git a/src/assets/environments/cliff_meeting_space/bundle.json.tpl b/src/assets/environments/cliff_meeting_space/bundle.json.tpl index 9a4eca63f5628750106b5d10693cc6ee6ea4856c..cdd4383273753f504146c39f1d50088168606f0a 100644 --- a/src/assets/environments/cliff_meeting_space/bundle.json.tpl +++ b/src/assets/environments/cliff_meeting_space/bundle.json.tpl @@ -1,30 +1,25 @@ { "name": "cliff_meeting_space", "version": "0.1.0", - "layers": [ + "meta": { + "title": "Cliffside Meeting Space", + "description": "Enjoy a beautiful vista view while collaborating in Mixed Reality", + "images": [ + { "type": "preview-thumbnail", "srcset": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/Big_Buck_Bunny_4K.webm/310px-seek%3D116-Big_Buck_Bunny_4K.webm.jpg" } + ] + }, + "assets": [ { - "name": "space-geometry", - "assets": [ - { "name": "meeting-space", "src": "<%= require("./MeetingSpace1_mesh.glb") %>" } - ] + "name": "space-geometry", "src": "<%= require("./MeetingSpace1_mesh.glb") %>" }, { - "name": "outdoor-geometry", - "assets": [ - { "name": "outdoor-facade", "src": "<%= require("./OutdoorFacade_mesh.glb") %>" } - ] + "name": "outdoor-geometry", "src": "<%= require("./OutdoorFacade_mesh.glb") %>" }, { - "name": "collision", - "assets": [ - { "name": "floor-nav", "src": "<%= require("./FloorNav_mesh.glb") %>" } - ] + "name": "collision", "src": "<%= require("./FloorNav_mesh.glb") %>" }, { - "name": "cliff-geometry", - "assets": [ - { "name": "cliff-vista", "src": "<%= require("./CliffVista_mesh.glb") %>" } - ] + "name": "cliff-geometry", "src": "<%= require("./CliffVista_mesh.glb") %>" } ] } diff --git a/src/assets/translations.data.json b/src/assets/translations.data.json index e10a95ae40bb533716f17b93f15d0f196a6de13e..e3a8fe318eb93e0c8824fe4dbb142a675a7759c0 100644 --- a/src/assets/translations.data.json +++ b/src/assets/translations.data.json @@ -30,6 +30,9 @@ "autoexit.title": "Auto-ending session in ", "autoexit.title_units": " seconds", "autoexit.subtitle": "You have started another session.", - "autoexit.cancel": "CANCEL" + "autoexit.cancel": "CANCEL", + "home.create_header": "Name your Hub", + "home.create_name.validation_warning": "Invalid name, limited to 4 to 64 characters and limited symbols.", + "home.create_button": "Create" } } diff --git a/src/components/gltf-bundle.js b/src/components/gltf-bundle.js index 57ed05a6cdc2f354f55f2733e6136740ac2c9fd4..55646540a198c3a379d829102562d5b86d381771 100644 --- a/src/components/gltf-bundle.js +++ b/src/components/gltf-bundle.js @@ -14,15 +14,9 @@ AFRAME.registerComponent("gltf-bundle", { _addGltfEntitiesForBundleJson: function(bundleJson) { const loaded = []; - for (let i = 0; i < bundleJson.layers.length; i++) { - const layer = bundleJson.layers[i]; - - // TODO choose a proper asset based upon quality settings, etc. For now just take the first. - if (layer.assets.length > 1) { - throw `Unable to inflate bundle ${this.data.src} because multiple assets defined for layer ${layer.name}`; - } - - const src = layer.assets[0].src; + for (let i = 0; i < bundleJson.assets.length; i++) { + const asset = bundleJson.assets[i]; + const src = asset.src; const gltfEl = document.createElement("a-gltf-entity"); gltfEl.setAttribute("src", src); gltfEl.setAttribute("position", "0 0 0"); diff --git a/src/react-components/home-root.js b/src/react-components/home-root.js index 90c314494258df7e505d18e36a93f8c36c761b12..80d540f2e4c1fd4e9f3967e1579dfea8402af540 100644 --- a/src/react-components/home-root.js +++ b/src/react-components/home-root.js @@ -2,9 +2,11 @@ import React, { Component } from "react"; import PropTypes from "prop-types"; import classNames from "classnames"; import queryString from "query-string"; -import { IntlProvider, FormattedMessage, addLocaleData } from "react-intl"; +import { IntlProvider, injectIntl, FormattedMessage, addLocaleData } from "react-intl"; import en from "react-intl/locale-data/en"; +import HubCreatePanel from "./hub-create-panel.js"; + const navigatorLang = (navigator.languages && navigator.languages[0]) || navigator.language || navigator.userLanguage; const lang = navigatorLang.toLowerCase().split(/[_-]+/)[0]; @@ -14,15 +16,46 @@ addLocaleData([...en]); const messages = localeData[lang] || localeData.en; +const ENVIRONMENT_URLS = [ + `${document.location.protocol}//${document.location.host}/assets/environments/cliff_meeting_space/bundle.json` +]; + class HomeRoot extends Component { - static propTypes = {}; + static propTypes = { + intl: PropTypes.object + }; + + state = { + environments: [] + }; + + componentDidMount() { + this.loadEnvironments(); + } + + loadEnvironments = () => { + const environments = []; - state = {}; + const environmentLoads = ENVIRONMENT_URLS.map( + src => + new Promise(async resolve => { + const res = await fetch(src); + const data = await res.json(); + data.bundle_url = src; + environments.push(data); + resolve(); + }) + ); - componentDidMount() {} + Promise.all(environmentLoads).then(() => this.setState({ environments })); + }; render() { - return <div>Hello</div>; + return ( + <IntlProvider locale={lang} messages={messages}> + <div>{this.state.environments.length > 0 && <HubCreatePanel environments={this.state.environments} />}</div> + </IntlProvider> + ); } } diff --git a/src/react-components/hub-create-panel.js b/src/react-components/hub-create-panel.js new file mode 100644 index 0000000000000000000000000000000000000000..1964285726770885c31d04e304e7de26141adee4 --- /dev/null +++ b/src/react-components/hub-create-panel.js @@ -0,0 +1,85 @@ +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import { injectIntl, FormattedMessage } from "react-intl"; +import { SCHEMA } from "../storage/store"; +import { generateHubName } from "../utils/name-generation"; + +class HubCreatePanel extends Component { + static propTypes = { + intl: PropTypes.object, + environments: PropTypes.array + }; + + state = { + name: generateHubName(), + environmentBundleUrl: "" + }; + + componentDidMount() { + this.setState({ environmentBundleUrl: this.props.environments[0].bundle_url }); + } + + createHub = async e => { + e.preventDefault(); + + const payload = { + hub: { name: this.state.name, default_environment_gltf_bundle_url: this.state.environmentBundleUrl } + }; + + const res = await fetch("/api/v1/hubs", { + body: JSON.stringify(payload), + headers: { "content-type": "application/json" }, + method: "POST" + }); + + const hub = await res.json(); + document.location = hub.url; + }; + + render() { + const { formatMessage } = this.props.intl; + + if (this.props.environments.length == 0) { + return <div />; + } + + const environmentChoices = this.props.environments.map(e => ( + <option key={e.bundle_url} value={e.bundle_url}> + {e.meta.title} + </option> + )); + + return ( + <form onSubmit={this.createHub}> + <div className="create-panel"> + <div className="create-panel__header"> + <FormattedMessage id="home.create_header" /> + </div> + <div className="create-panel__form"> + <input + className="create-panel__form__name" + value={this.state.name} + onChange={e => this.setState({ name: e.target.value })} + onFocus={e => e.target.select()} + required + pattern={"^[A-Za-z0-9-'\":!@#$%^&*(),.?~ ]{4,64}$"} + title={formatMessage({ id: "home.create_name.validation_warning" })} + /> + <select value={this.state.environmentBundleUrl}>{environmentChoices}</select> + <button + onClick={e => { + e.preventDefault(); + this.setState({ name: generateHubName() }); + }} + > + Rotate + </button> + <input type="submit" value={formatMessage({ id: "home.create_button" })} /> + </div> + </div> + </form> + ); + } +} + +export default injectIntl(HubCreatePanel); diff --git a/src/utils/name-generation.js b/src/utils/name-generation.js new file mode 100644 index 0000000000000000000000000000000000000000..cdedd157240ef4a34acd534d8c5e7d36b0ca55fc --- /dev/null +++ b/src/utils/name-generation.js @@ -0,0 +1,672 @@ +const adjectives = [ + "able", + "absolute", + "acceptable", + "acclaimed", + "accomplished", + "accurate", + "aching", + "acrobatic", + "adorable", + "adventurous", + "basic", + "belated", + "beloved", + "calm", + "candid", + "capital", + "carefree", + "caring", + "cautious", + "celebrated", + "charming", + "daring", + "darling", + "dearest", + "each", + "eager", + "early", + "earnest", + "easy", + "easygoing", + "ecstatic", + "edible", + "fabulous", + "fair", + "faithful", + "familiar", + "famous", + "fancy", + "fantastic", + "far", + "generous", + "gentle", + "genuine", + "giant", + "handmade", + "handsome", + "handy", + "happy", + "icy", + "ideal", + "identical", + "keen", + "lasting", + "lavish", + "magnificent", + "majestic", + "mammoth", + "marvelous", + "natural", + "obedient", + "palatable", + "parched", + "passionate", + "pastel", + "peaceful", + "perfect", + "perfumed", + "quaint", + "qualified", + "radiant", + "rapid", + "rare", + "safe", + "sandy", + "satisfied", + "scaly", + "scarce", + "scared", + "scary", + "scented", + "scientific", + "secret", + "sentimental", + "talkative", + "tangible", + "tart", + "tasty", + "tattered", + "teeming", + "ultimate", + "uncommon", + "unconscious", + "understated", + "warm", + "active", + "adept", + "admirable", + "admired", + "adorable", + "adored", + "advanced", + "affectionate", + "beneficial", + "best", + "better", + "big", + "cheerful", + "cheery", + "chief", + "chilly", + "classic", + "clean", + "clear", + "clever", + "decent", + "decisive", + "deep", + "defiant", + "definitive", + "delectable", + "delicious", + "elaborate", + "elastic", + "elated", + "elegant", + "elementary", + "elliptical", + "fast", + "favorable", + "favorite", + "fearless", + "gifted", + "glamorous", + "gleaming", + "glittering", + "harmonious", + "imaginative", + "immense", + "jealous", + "kind", + "leafy", + "legal", + "mature", + "mean", + "meaty", + "nautical", + "neat", + "necessary", + "needy", + "oddball", + "offbeat", + "periodic", + "perky", + "personal", + "pertinent", + "petty", + "quarterly", + "ready", + "real", + "realistic", + "reasonable", + "regal", + "serene", + "shabby", + "sharp", + "shiny", + "showy", + "shy", + "silky", + "tempting", + "tense", + "terrific", + "testy", + "thankful", + "uniform", + "unique", + "vast", + "weary", + "wee", + "welcome", + "agile", + "alarmed", + "alert", + "alive", + "bleak", + "blissful", + "blushing", + "coarse", + "colorful", + "colossal", + "comfortable", + "compassionate", + "complete", + "delightful", + "dense", + "dependable", + "dependent", + "descriptive", + "detailed", + "determined", + "devoted", + "different", + "eminent", + "emotional", + "enchanted", + "enchanting", + "energetic", + "enormous", + "fine", + "finished", + "firm", + "firsthand", + "fixed", + "flashy", + "flawless", + "glorious", + "glossy", + "golden", + "good", + "gorgeous", + "graceful", + "healthy", + "heartfelt", + "hearty", + "helpful", + "impartial", + "impressive", + "jolly", + "jovial", + "lighthearted", + "likable", + "lined", + "mellow", + "melodic", + "memorable", + "mild", + "new", + "opulent", + "playful", + "pleasant", + "pleasing", + "plump", + "plush", + "polished", + "polite", + "reliable", + "relieved", + "remarkable", + "remote", + "respectful", + "responsible", + "simple", + "simplistic", + "sizzling", + "sleepy", + "slight", + "slim", + "smart", + "smooth", + "snappy", + "snoopy", + "thirsty", + "this", + "thorough", + "those", + "thoughtful", + "united", + "vibrant", + "vicious", + "wellmade", + "whimsical", + "whirlwind", + "zesty", + "amazing", + "ambitious", + "ample", + "amused", + "amusing", + "ancient", + "angelic", + "antique", + "bold", + "bossy", + "both", + "bouncy", + "bountiful", + "complex", + "conscious", + "considerate", + "constant", + "content", + "conventional", + "cooked", + "cool", + "cooperative", + "diligent", + "dimwitted", + "direct", + "discrete", + "envious", + "essential", + "ethical", + "euphoric", + "flippant", + "fluffy", + "fluid", + "flustered", + "focused", + "fond", + "gracious", + "grand", + "grandiose", + "granular", + "grateful", + "grave", + "great", + "hidden", + "high", + "hilarious", + "homely", + "incomparable", + "incredible", + "infamous", + "joyful", + "lively", + "loathsome", + "lonely", + "long", + "milky", + "mindless", + "miniature", + "minor", + "misty", + "next", + "nice", + "nifty", + "nimble", + "orderly", + "organic", + "ornate", + "popular", + "posh", + "positive", + "potable", + "powerful", + "powerless", + "precious", + "present", + "prestigious", + "quick", + "rewarding", + "rich", + "right", + "sociable", + "soft", + "solid", + "some", + "sophisticated", + "soulful", + "sparkling", + "spectacular", + "speedy", + "spicy", + "spiffy", + "spirited", + "spiteful", + "splendid", + "spotless", + "spry", + "thrifty", + "tidy", + "tight", + "timely", + "tinted", + "unruly", + "untimely", + "violet", + "wicked", + "wide", + "wild", + "willing", + "winding", + "windy", + "zigzag", + "apprehensive", + "appropriate", + "artistic", + "assured", + "astonishing", + "bright", + "brilliant", + "bronze", + "coordinated", + "courageous", + "courteous", + "crafty", + "crazy", + "creamy", + "creative", + "crisp", + "distant", + "distinct", + "downright", + "evergreen", + "everlasting", + "every", + "evil", + "excellent", + "excitable", + "exemplary", + "exhausted", + "forthright", + "fortunate", + "fragrant", + "frank", + "free", + "frequent", + "fresh", + "friendly", + "frightened", + "frigid", + "gripping", + "grounded", + "honest", + "honorable", + "honored", + "hopeful", + "hospitable", + "hot", + "huge", + "infatuated", + "infinite", + "informal", + "insistent", + "instructive", + "juicy", + "jumbo", + "knowing", + "knowledgeable", + "longterm", + "loud", + "lovable", + "loving", + "modern", + "modest", + "moist", + "monumental", + "normal", + "notable", + "outgoing", + "precious", + "pretty", + "prickly", + "primary", + "pristine", + "private", + "prize", + "productive", + "profitable", + "quiet", + "quintessential", + "roasted", + "robust", + "square", + "squiggly", + "stable", + "staid", + "starry", + "steel", + "stimulating", + "striking", + "striped", + "strong", + "studious", + "stunning", + "tough", + "trained", + "treasured", + "tremendous", + "triangular", + "tricky", + "unused", + "unusual", + "upbeat", + "virtual", + "witty", + "wonderful", + "wooden", + "worldly", + "youthful", + "attached", + "attentive", + "attractive", + "austere", + "authentic", + "automatic", + "aware", + "awesome", + "bubbly", + "bustling", + "busy", + "buttery", + "cuddly", + "cultured", + "curly", + "curvy", + "cute", + "cylindrical", + "downright", + "dramatic", + "excited", + "exciting", + "exotic", + "experienced", + "expert", + "frosty", + "fruitful", + "full", + "fumbling", + "funny", + "fussy", + "growing", + "grown", + "gummy", + "humble", + "humongous", + "hungry", + "intelligent", + "interesting", + "known", + "kooky", + "kosher", + "loyal", + "lucky", + "luminous", + "lustrous", + "luxurious", + "multicolored", + "mysterious", + "noteworthy", + "numb", + "nutritious", + "outstanding", + "overjoyed", + "proper", + "proud", + "prudent", + "punctual", + "puny", + "pure", + "puzzled", + "puzzling", + "quirky", + "stupendous", + "sturdy", + "stylish", + "subdued", + "subtle", + "sunny", + "super", + "superb", + "supportive", + "surprised", + "sweet", + "swift", + "sympathetic", + "trivial", + "trusting", + "trustworthy", + "trusty", + "truthful", + "twin", + "usable", + "used", + "useful", + "utilized", + "vital", + "vivid", + "worried", + "worthwhile", + "worthy", + "writhing", + "wry", + "yummy", + "chocolate", + "crimson", + "cyan", + "fuchsia", + "gold", + "honeydew", + "lime", + "linen", + "magenta", + "olive", + "peru", + "salmon", + "seashell", + "sienna", + "snow", + "thistle", + "tomato", + "transparent", + "turquoise", + "violet" +]; + +const nouns = [ + "space", + "land", + "world", + "universe", + "plane", + "room", + "nation", + "plaza", + "gathering", + "meetup", + "get together", + "conclave", + "party", + "powwow", + "domain", + "dominion", + "realm", + "square", + "commons", + "park", + "cosmos", + "sphere", + "terrain", + "spot", + "zone", + "area", + "tract", + "turf", + "place", + "territory", + "volume", + "camp", + "picnic", + "outing", + "vacation", + "adventure", + "exploration", + "outing", + "walkabout", + "safari", + "venture", + "roundtable", + "barbecue", + "celebration", + "festivity", + "gala", + "shindig", + "social", + "convention", + "assembly", + "congregation", + "rendezvous", + "huddle", + "meet" +]; + +export function generateHubName() { + const randItem = set => { + const s = set[Math.floor(Math.random() * set.length)]; + return s.charAt(0).toUpperCase() + s.slice(1); + }; + + return `${randItem(adjectives)} ${randItem(adjectives)} ${randItem(nouns)}`; +}