diff --git a/src/hub.js b/src/hub.js index de5406105b7508fc5ed9291d6f47aebf669a4e68..5492dd0f84c10c13d745de1410397dde1b01fa1e 100644 --- a/src/hub.js +++ b/src/hub.js @@ -80,6 +80,7 @@ import { proxiedUrlFor } from "./utils/media-utils"; import MessageDispatch from "./message-dispatch"; import SceneEntryManager from "./scene-entry-manager"; import Subscriptions from "./subscriptions"; +import { spawnChatMessage } from "./react-components/chat-message"; import "./systems/nav"; import "./systems/personal-space-bubble"; @@ -551,4 +552,10 @@ document.addEventListener("DOMContentLoaded", async () => { }); linkChannel.setSocket(socket); + + setInterval(() => { + spawnChatMessage( + "```Hello asdjf sdkfadsfadsfadsfadf\nalkdsf dsflsafadsfadsfadfsj\n asdf dsf adf adf sdkfadsfafd\n lasdfadsfadsfldsfldsfja\n asdkf sdfjadsadsfadsf\n aldf sdjf sdkfasdf ```" + ); + }, 5000); }); diff --git a/src/react-components/chat-message.js b/src/react-components/chat-message.js index a7aa72b55cedb4a70c4905de8ffdf678797ff377..613118004656c5a7092e4f8f9e56c36f49efa9c3 100644 --- a/src/react-components/chat-message.js +++ b/src/react-components/chat-message.js @@ -6,6 +6,7 @@ import classNames from "classnames"; import Linkify from "react-linkify"; import { toArray as toEmojis } from "react-emoji-render"; import serializeElement from "../utils/serialize-element"; +import nextTick from "../utils/next-tick"; const messageCanvas = document.createElement("canvas"); const emojiRegex = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32-\ude3a]|[\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/; @@ -30,7 +31,7 @@ const messageBodyDom = body => { ); }; -export function spawnChatMessage(body) { +export function renderChatMessage(body) { if (body.length === 0) return; if (body.match(urlRegex)) { @@ -64,28 +65,64 @@ export function spawnChatMessage(body) { </div> ); - ReactDOM.render(entryDom, el, () => { - // Scale by 12x - messageCanvas.width = el.offsetWidth * 12.1; - messageCanvas.height = el.offsetHeight * 12.1; - - const xhtml = encodeURIComponent(` - <svg xmlns="http://www.w3.org/2000/svg" width="${messageCanvas.width}" height="${messageCanvas.height}"> - <foreignObject width="8.333%" height="8.333%" style="transform: scale(12.0);"> - ${serializeElement(el)} - </foreignObject> - </svg> - `); - const img = new Image(); - - img.onload = async () => { - context.drawImage(img, 0, 0); - const blob = await new Promise(resolve => messageCanvas.toBlob(resolve)); - document.querySelector("a-scene").emit("add_media", new File([blob], "message.png", { type: "image/png" })); - el.parentNode.removeChild(el); - }; - - img.src = "data:image/svg+xml," + xhtml; + return new Promise(resolve => { + ReactDOM.render(entryDom, el, () => { + // Scale by 12x + //messageCanvas.width = el.offsetWidth * 12.1; + //messageCanvas.height = el.offsetHeight * 12.1; + messageCanvas.width = el.offsetWidth * 4.1; + messageCanvas.height = el.offsetHeight * 4.1; + + const xhtml = encodeURIComponent(` + <svg xmlns="http://www.w3.org/2000/svg" width="${messageCanvas.width}" height="${messageCanvas.height}"> + <foreignObject width="25%" height="25%" style="transform: scale(4.0);"> + ${serializeElement(el)} + </foreignObject> + </svg> + `); + const img = new Image(); + + img.onload = async () => { + context.drawImage(img, 0, 0); + const blob = await new Promise(resolve => messageCanvas.toBlob(resolve)); + el.parentNode.removeChild(el); + resolve(blob); + }; + + img.src = "data:image/svg+xml," + xhtml; + }); + }); +} + +export async function spawnChatMessage(body) { + const blob = await renderChatMessage(body); + //document.querySelector("a-scene").emit("add_media", new File([blob], "message.png", { type: "image/png" })); + // + const entity = document.createElement("a-entity"); + const offset = { x: 0, y: 0, z: -1.5 }; + + entity.setAttribute("offset-relative-to", { + target: "#player-camera", + offset + }); + + document.querySelector("a-scene").appendChild(entity); + + await nextTick(); + + const textureLoader = new THREE.TextureLoader(); + const blobUrl = URL.createObjectURL(blob); + + textureLoader.load(blobUrl, texture => { + const material = new THREE.MeshBasicMaterial(); + material.side = THREE.DoubleSide; + material.transparent = true; + material.map = texture; + material.needsUpdate = true; + + const geometry = new THREE.PlaneGeometry(); + const mesh = new THREE.Mesh(geometry, material); + entity.setObject3D("mesh", mesh); }); } diff --git a/src/scene-entry-manager.js b/src/scene-entry-manager.js index 4c1875e727d5c2cb7d21696f80d371e900782a84..848e14c82457b5b1f292280fb7ed7c2e2eb70aab 100644 --- a/src/scene-entry-manager.js +++ b/src/scene-entry-manager.js @@ -53,7 +53,7 @@ export default class SceneEntryManager { if (enterInVR) { // HACK - A-Frame calls getVRDisplays at module load, we want to do it here to // force gamepads to become live. - navigator.getVRDisplays(); + //navigator.getVRDisplays(); this.scene.enterVR(); } else if (AFRAME.utils.device.isMobile()) { document.body.addEventListener("touchend", requestFullscreen);