From e198b4470a4fff96d9bad39bbf0d6918d7d03d67 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Thu, 28 Jan 2021 21:34:13 -0800 Subject: [PATCH 1/3] Use models, images, and videos as links --- src/editor/nodes/ImageNode.js | 16 ++++++ src/editor/nodes/ModelNode.js | 81 ++++++++++++++++++++-------- src/editor/nodes/VideoNode.js | 16 ++++++ src/ui/properties/ImageNodeEditor.js | 5 ++ src/ui/properties/ModelNodeEditor.js | 8 +++ src/ui/properties/VideoNodeEditor.js | 5 ++ 6 files changed, 109 insertions(+), 22 deletions(-) diff --git a/src/editor/nodes/ImageNode.js b/src/editor/nodes/ImageNode.js index 7593ec7c8..ad1fee3ae 100644 --- a/src/editor/nodes/ImageNode.js +++ b/src/editor/nodes/ImageNode.js @@ -32,6 +32,12 @@ export default class ImageNode extends EditorNodeMixin(Image) { })() ); + const linkComponent = json.components.find(c => c.name === "link"); + + if (linkComponent) { + node.href = linkComponent.props.href; + } + return node; } @@ -39,6 +45,7 @@ export default class ImageNode extends EditorNodeMixin(Image) { super(editor); this._canonicalUrl = ""; + this.href = ""; this.controls = true; this.billboard = false; } @@ -119,6 +126,7 @@ export default class ImageNode extends EditorNodeMixin(Image) { this.alphaMode = source.alphaMode; this.alphaCutoff = source.alphaCutoff; this._canonicalUrl = source._canonicalUrl; + this.href = source.href; return this; } @@ -138,6 +146,10 @@ export default class ImageNode extends EditorNodeMixin(Image) { components.billboard = {}; } + if (this.href) { + components.link = { href: this.href }; + } + return super.serialize(components); } @@ -165,6 +177,10 @@ export default class ImageNode extends EditorNodeMixin(Image) { this.addGLTFComponent("billboard", {}); } + if (this.href && this.projection === "flat") { + this.addGLTFComponent("link", { href: this.href }); + } + this.replaceObject(); } diff --git a/src/editor/nodes/ModelNode.js b/src/editor/nodes/ModelNode.js index 5e72bfbd5..6f64f621e 100644 --- a/src/editor/nodes/ModelNode.js +++ b/src/editor/nodes/ModelNode.js @@ -79,6 +79,12 @@ export default class ModelNode extends EditorNodeMixin(Model) { if (json.components.find(c => c.name === "billboard")) { node.billboard = true; } + + const linkComponent = json.components.find(c => c.name === "link"); + + if (linkComponent) { + node.href = linkComponent.props.href; + } })() ); @@ -98,6 +104,7 @@ export default class ModelNode extends EditorNodeMixin(Model) { this.stats = defaultStats; this.gltfJson = null; this._billboard = false; + this._href = ""; } // Overrides Model's src property and stores the original (non-resolved) url. @@ -119,6 +126,15 @@ export default class ModelNode extends EditorNodeMixin(Model) { this.updateStaticModes(); } + get href() { + return this._href; + } + + set href(value) { + this._href = value; + this.updateStaticModes(); + } + // Overrides Model's loadGLTF method and uses the Editor's gltf cache. async loadGLTF(src) { const loader = this.editor.gltfCache.getLoader(src); @@ -335,7 +351,7 @@ export default class ModelNode extends EditorNodeMixin(Model) { } } - if (this.billboard) { + if (this.billboard || this.href) { setStaticMode(this.model, StaticModes.Dynamic); } } @@ -374,6 +390,10 @@ export default class ModelNode extends EditorNodeMixin(Model) { components.billboard = {}; } + if (this.href) { + components.link = { href: this.href }; + } + return super.serialize(components); } @@ -384,7 +404,6 @@ export default class ModelNode extends EditorNodeMixin(Model) { this.initialScale = source.initialScale; this.load(source.src); } else { - this.updateStaticModes(); this.stats = JSON.parse(JSON.stringify(source.stats)); this.gltfJson = source.gltfJson; this._canonicalUrl = source._canonicalUrl; @@ -394,38 +413,56 @@ export default class ModelNode extends EditorNodeMixin(Model) { this.collidable = source.collidable; this.walkable = source.walkable; this.combine = source.combine; - this.billboard = source.billboard; + this._billboard = source._billboard; + this._href = source._href; + + this.updateStaticModes(); return this; } prepareForExport(ctx) { super.prepareForExport(); - this.addGLTFComponent("shadow", { - cast: this.castShadow, - receive: this.receiveShadow - }); - const clipIndices = this.activeClipIndices.map(index => { - return ctx.animations.indexOf(this.model.animations[index]); - }); + if (this.billboard) { + this.addGLTFComponent("billboard", {}); + } - this.model.traverse(child => { - const components = getComponents(child); + if (this.href) { + this.addGLTFComponent("networked", { + id: this.uuid + }); - if (components && components["loop-animation"]) { - delete components["loop-animation"]; - } - }); + this.addGLTFComponent("link", { href: this.href }); - if (clipIndices.length > 0) { - this.addGLTFComponent("loop-animation", { - activeClipIndices: clipIndices + this.addGLTFComponent("model", { + src: this._canonicalUrl }); - } - if (this.billboard) { - this.addGLTFComponent("billboard", {}); + this.replaceObject(); + } else { + this.addGLTFComponent("shadow", { + cast: this.castShadow, + receive: this.receiveShadow + }); + + const clipIndices = this.activeClipIndices.map(index => { + return ctx.animations.indexOf(this.model.animations[index]); + }); + + this.model.traverse(child => { + const components = getComponents(child); + + if (components && components["loop-animation"]) { + delete components["loop-animation"]; + } + }); + + if (clipIndices.length > 0) { + this.addGLTFComponent("loop-animation", { + activeClipIndices: clipIndices + }); + } } } } diff --git a/src/editor/nodes/VideoNode.js b/src/editor/nodes/VideoNode.js index 14f26ff67..11dcc4351 100644 --- a/src/editor/nodes/VideoNode.js +++ b/src/editor/nodes/VideoNode.js @@ -39,6 +39,12 @@ export default class VideoNode extends EditorNodeMixin(Video) { node.billboard = true; } + const linkComponent = json.components.find(c => c.name === "link"); + + if (linkComponent) { + node.href = linkComponent.props.href; + } + loadAsync( (async () => { await node.load(src, onError); @@ -69,6 +75,7 @@ export default class VideoNode extends EditorNodeMixin(Video) { this.volume = 0.5; this.controls = true; this.billboard = false; + this.href = ""; } get src() { @@ -182,6 +189,7 @@ export default class VideoNode extends EditorNodeMixin(Video) { this.controls = source.controls; this.billboard = source.billboard; this._canonicalUrl = source._canonicalUrl; + this.href = source.href; return this; } @@ -210,6 +218,10 @@ export default class VideoNode extends EditorNodeMixin(Video) { components.billboard = {}; } + if (this.href) { + components.link = { href: this.href }; + } + return super.serialize(components); } @@ -241,6 +253,10 @@ export default class VideoNode extends EditorNodeMixin(Video) { this.addGLTFComponent("billboard", {}); } + if (this.href && this.projection === "flat") { + this.addGLTFComponent("link", { href: this.href }); + } + this.replaceObject(); } diff --git a/src/ui/properties/ImageNodeEditor.js b/src/ui/properties/ImageNodeEditor.js index d99244d4d..efb6bbf12 100644 --- a/src/ui/properties/ImageNodeEditor.js +++ b/src/ui/properties/ImageNodeEditor.js @@ -2,6 +2,7 @@ import React from "react"; import PropTypes from "prop-types"; import NodeEditor from "./NodeEditor"; import InputGroup from "../inputs/InputGroup"; +import StringInput from "../inputs/StringInput"; import SelectInput from "../inputs/SelectInput"; import BooleanInput from "../inputs/BooleanInput"; import NumericInputGroup from "../inputs/NumericInputGroup"; @@ -23,6 +24,7 @@ export default function ImageNodeEditor(props) { const onChangeProjection = useSetPropertySelected(editor, "projection"); const onChangeTransparencyMode = useSetPropertySelected(editor, "alphaMode"); const onChangeAlphaCutoff = useSetPropertySelected(editor, "alphaCutoff"); + const onChangeHref = useSetPropertySelected(editor, "href"); return ( @@ -38,6 +40,9 @@ export default function ImageNodeEditor(props) { + + + { + this.props.editor.setPropertySelected("href", href); + }; + isAnimationPropertyDisabled() { const { multiEdit, editor, node } = this.props; @@ -99,6 +104,9 @@ export default class ModelNodeEditor extends Component { + + + {node.model && } diff --git a/src/ui/properties/VideoNodeEditor.js b/src/ui/properties/VideoNodeEditor.js index 1ce17136b..6a26e1e8e 100644 --- a/src/ui/properties/VideoNodeEditor.js +++ b/src/ui/properties/VideoNodeEditor.js @@ -4,6 +4,7 @@ import NodeEditor from "./NodeEditor"; import InputGroup from "../inputs/InputGroup"; import SelectInput from "../inputs/SelectInput"; import BooleanInput from "../inputs/BooleanInput"; +import StringInput from "../inputs/StringInput"; import { VideoProjection } from "../../editor/objects/Video"; import VideoInput from "../inputs/VideoInput"; import { Video } from "styled-icons/fa-solid/Video"; @@ -18,6 +19,7 @@ export default function VideoNodeEditor(props) { const onChangeSrc = useSetPropertySelected(editor, "src"); const onChangeProjection = useSetPropertySelected(editor, "projection"); const onChangeBillboard = useSetPropertySelected(editor, "billboard"); + const onChangeHref = useSetPropertySelected(editor, "href"); return ( @@ -27,6 +29,9 @@ export default function VideoNodeEditor(props) { + + + From 83b9cd3a7eea81422e37dc58706f0f3e527a1006 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Thu, 11 Feb 2021 17:21:13 -0800 Subject: [PATCH 2/3] Remove support for models as links --- src/editor/nodes/ModelNode.js | 75 ++++++++-------------------- src/ui/properties/ModelNodeEditor.js | 8 --- 2 files changed, 20 insertions(+), 63 deletions(-) diff --git a/src/editor/nodes/ModelNode.js b/src/editor/nodes/ModelNode.js index 6f64f621e..e0623f916 100644 --- a/src/editor/nodes/ModelNode.js +++ b/src/editor/nodes/ModelNode.js @@ -79,12 +79,6 @@ export default class ModelNode extends EditorNodeMixin(Model) { if (json.components.find(c => c.name === "billboard")) { node.billboard = true; } - - const linkComponent = json.components.find(c => c.name === "link"); - - if (linkComponent) { - node.href = linkComponent.props.href; - } })() ); @@ -104,7 +98,6 @@ export default class ModelNode extends EditorNodeMixin(Model) { this.stats = defaultStats; this.gltfJson = null; this._billboard = false; - this._href = ""; } // Overrides Model's src property and stores the original (non-resolved) url. @@ -126,15 +119,6 @@ export default class ModelNode extends EditorNodeMixin(Model) { this.updateStaticModes(); } - get href() { - return this._href; - } - - set href(value) { - this._href = value; - this.updateStaticModes(); - } - // Overrides Model's loadGLTF method and uses the Editor's gltf cache. async loadGLTF(src) { const loader = this.editor.gltfCache.getLoader(src); @@ -351,7 +335,7 @@ export default class ModelNode extends EditorNodeMixin(Model) { } } - if (this.billboard || this.href) { + if (this.billboard) { setStaticMode(this.model, StaticModes.Dynamic); } } @@ -390,10 +374,6 @@ export default class ModelNode extends EditorNodeMixin(Model) { components.billboard = {}; } - if (this.href) { - components.link = { href: this.href }; - } - return super.serialize(components); } @@ -414,7 +394,6 @@ export default class ModelNode extends EditorNodeMixin(Model) { this.walkable = source.walkable; this.combine = source.combine; this._billboard = source._billboard; - this._href = source._href; this.updateStaticModes(); @@ -424,45 +403,31 @@ export default class ModelNode extends EditorNodeMixin(Model) { prepareForExport(ctx) { super.prepareForExport(); - if (this.billboard) { - this.addGLTFComponent("billboard", {}); - } + this.addGLTFComponent("shadow", { + cast: this.castShadow, + receive: this.receiveShadow + }); - if (this.href) { - this.addGLTFComponent("networked", { - id: this.uuid - }); + const clipIndices = this.activeClipIndices.map(index => { + return ctx.animations.indexOf(this.model.animations[index]); + }); - this.addGLTFComponent("link", { href: this.href }); + this.model.traverse(child => { + const components = getComponents(child); - this.addGLTFComponent("model", { - src: this._canonicalUrl - }); - - this.replaceObject(); - } else { - this.addGLTFComponent("shadow", { - cast: this.castShadow, - receive: this.receiveShadow - }); - - const clipIndices = this.activeClipIndices.map(index => { - return ctx.animations.indexOf(this.model.animations[index]); - }); - - this.model.traverse(child => { - const components = getComponents(child); + if (components && components["loop-animation"]) { + delete components["loop-animation"]; + } + }); - if (components && components["loop-animation"]) { - delete components["loop-animation"]; - } + if (clipIndices.length > 0) { + this.addGLTFComponent("loop-animation", { + activeClipIndices: clipIndices }); + } - if (clipIndices.length > 0) { - this.addGLTFComponent("loop-animation", { - activeClipIndices: clipIndices - }); - } + if (this.billboard) { + this.addGLTFComponent("billboard", {}); } } } diff --git a/src/ui/properties/ModelNodeEditor.js b/src/ui/properties/ModelNodeEditor.js index 763a3d605..0e9a53ed7 100644 --- a/src/ui/properties/ModelNodeEditor.js +++ b/src/ui/properties/ModelNodeEditor.js @@ -3,7 +3,6 @@ import PropTypes from "prop-types"; import NodeEditor from "./NodeEditor"; import SelectInput from "../inputs/SelectInput"; import InputGroup from "../inputs/InputGroup"; -import StringInput from "../inputs/StringInput"; import BooleanInput from "../inputs/BooleanInput"; import ModelInput from "../inputs/ModelInput"; import { Cube } from "styled-icons/fa-solid/Cube"; @@ -53,10 +52,6 @@ export default class ModelNodeEditor extends Component { this.props.editor.setPropertySelected("billboard", billboard); }; - onChangeHref = href => { - this.props.editor.setPropertySelected("href", href); - }; - isAnimationPropertyDisabled() { const { multiEdit, editor, node } = this.props; @@ -104,9 +99,6 @@ export default class ModelNodeEditor extends Component { - - - {node.model && } From 67b191c1ec1c26ea7a764de131289970bff644ec Mon Sep 17 00:00:00 2001 From: Robert Long Date: Tue, 16 Feb 2021 14:24:23 -0800 Subject: [PATCH 3/3] Only show link field when flat projection --- src/ui/properties/ImageNodeEditor.js | 8 +++++--- src/ui/properties/VideoNodeEditor.js | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ui/properties/ImageNodeEditor.js b/src/ui/properties/ImageNodeEditor.js index efb6bbf12..7ba164ae7 100644 --- a/src/ui/properties/ImageNodeEditor.js +++ b/src/ui/properties/ImageNodeEditor.js @@ -40,9 +40,11 @@ export default function ImageNodeEditor(props) { - - - + {node.projection === ImageProjection.Flat && ( + + + + )} - - - + {node.projection === VideoProjection.Flat && ( + + + + )}