diff --git a/src/assets/stylesheets/profile.scss b/src/assets/stylesheets/profile.scss index 4b01331d346967f8c3c5ca538f7fe4ab332ae205..3911b025f0cdba74825dc6173cd0dff5cd76a0f4 100644 --- a/src/assets/stylesheets/profile.scss +++ b/src/assets/stylesheets/profile.scss @@ -13,6 +13,11 @@ z-index: 10; background-color: rgba(255, 255, 255, 0.95); + + a { + cursor: pointer; + } + :local(.logo) { width: 150px; position: absolute; @@ -35,6 +40,15 @@ .loading-panel { background: transparent; } + + .custom-url-link { + position: absolute; + top: 10px; + right: 30px; + z-index: 100; + text-shadow: 0px 0px 6px #202020; + color: white; + } } :local(.avatar-selector) { diff --git a/src/react-components/profile-entry-panel.js b/src/react-components/profile-entry-panel.js index e4d02c70a4bb896816c44d8018aeae2da8ea0139..18df90851d2a5d6a1d923a09a52aba934d8e4ab3 100644 --- a/src/react-components/profile-entry-panel.js +++ b/src/react-components/profile-entry-panel.js @@ -6,6 +6,7 @@ import styles from "../assets/stylesheets/profile.scss"; import classNames from "classnames"; import hubLogo from "../assets/images/hub-preview-white.png"; import { WithHoverSound } from "./wrap-with-audio"; +import { avatars } from "../assets/avatars/avatars"; class ProfileEntryPanel extends Component { static propTypes = { @@ -18,7 +19,7 @@ class ProfileEntryPanel extends Component { constructor(props) { super(props); const { displayName, avatarId } = this.props.store.state.profile; - this.state = { displayName, avatarId }; + this.state = { displayName, avatarId, customMode: avatarId && avatarId.startsWith("http") }; this.props.store.addEventListener("statechanged", this.storeUpdated); } @@ -39,7 +40,8 @@ class ProfileEntryPanel extends Component { hasChangedName: hasChangedNowOrPreviously }, profile: { - ...this.state + displayName: this.state.displayName, + avatarId: this.state.avatarId } }); this.props.finished(); @@ -94,20 +96,46 @@ class ProfileEntryPanel extends Component { title={formatMessage({ id: "profile.display_name.validation_warning" })} ref={inp => (this.nameInput = inp)} /> - <div className={styles.avatarSelectorContainer}> - <div className="loading-panel"> - <div className="loader-wrap"> - <div className="loader"> - <div className="loader-center" /> + {this.state.customMode ? ( + <div className={styles.avatarSelectorContainer}> + <label htmlFor="#custom-avatar-url" className={styles.title}> + Avatar GLTF/GLB{" "} + </label> + <input + id="custom-avatar-url" + type="url" + className={styles.formFieldText} + value={this.state.avatarId} + onChange={e => this.setState({ avatarId: e.target.value })} + /> + <div className={styles.links}> + <a onClick={() => this.setState({ customMode: false, avatarId: "botdefault" })}>cancel</a> + </div> + </div> + ) : ( + <div className={styles.avatarSelectorContainer}> + <div className="loading-panel"> + <div className="loader-wrap"> + <div className="loader"> + <div className="loader-center" /> + </div> </div> </div> + <iframe + className={styles.avatarSelector} + src={`/avatar-selector.html#avatar_id=${this.state.avatarId}`} + ref={ifr => (this.avatarSelector = ifr)} + /> + <a + className="custom-url-link" + onClick={() => + this.setState({ customMode: true, avatarId: avatars.find(a => a.id === this.state.avatarId).model }) + } + > + options + </a> </div> - <iframe - className={styles.avatarSelector} - src={`/avatar-selector.html#avatar_id=${this.state.avatarId}`} - ref={ifr => (this.avatarSelector = ifr)} - /> - </div> + )} <WithHoverSound> <input className={styles.formSubmit} type="submit" value={formatMessage({ id: "profile.save" })} /> </WithHoverSound> diff --git a/src/scene-entry-manager.js b/src/scene-entry-manager.js index 0bc3548b3df4f68962cc48c93c8856b290ac1521..9e079415207ce8dbd6be5e864c4b00ef16f72b63 100644 --- a/src/scene-entry-manager.js +++ b/src/scene-entry-manager.js @@ -137,10 +137,10 @@ export default class SceneEntryManager { }; _updatePlayerRigWithProfile = () => { - const displayName = this.store.state.profile.displayName; + const { avatarId, displayName } = this.store.state.profile; this.playerRig.setAttribute("player-info", { displayName, - avatarSrc: "#" + (this.store.state.profile.avatarId || "botdefault") + avatarSrc: avatarId && avatarId.startsWith("http") ? avatarId : `#${avatarId || "botdefault"}` }); const hudController = this.playerRig.querySelector("[hud-controller]"); hudController.setAttribute("hud-controller", { showTip: !this.store.state.activity.hasFoundFreeze });