/** * 3D Foundation Project * Copyright 2025 Smithsonian Institution * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import Subscriber from "@ff/core/Subscriber"; import "@ff/ui/ButtonGroup"; import CVToolProvider from "../../components/CVToolProvider"; import CVDocument from "../../components/CVDocument"; import "../Logo"; import "./MainMenu"; import "./ToolBar"; import "./TourNavigator"; import "./TourMenu"; import "./LanguageMenu"; import "./TagCloud"; import HelpMain from "./HelpMain"; import { ITourMenuSelectEvent } from "./TourMenu"; import DocumentView, { customElement, html } from "./DocumentView"; import LanguageMenu from "./LanguageMenu"; import { EUIElements } from "client/components/CVInterface"; import CVAssetReader from "client/components/CVAssetReader"; import SplashScreen from "./SplashScreen"; //////////////////////////////////////////////////////////////////////////////// @customElement("sv-chrome-view") export default class ChromeView extends DocumentView { protected documentProps = new Subscriber("value", this.onUpdate, this); protected titleElement: HTMLDivElement; protected assetPath: string = ""; protected needsSplash: boolean = true; protected get toolProvider() { return this.system.getMainComponent(CVToolProvider); } protected get assetReader() { return this.system.getMainComponent(CVAssetReader); } protected firstConnected() { this.style.pointerEvents = "none"; this.setAttribute("pointer-events", "none"); this.classList.add("sv-chrome-view"); } protected connected() { super.connected(); this.toolProvider.ins.visible.on("value", this.onUpdate, this); this.activeDocument.setup.language.outs.activeLanguage.on("value", this.onUpdate, this); this.activeDocument.setup.audio.outs.isPlaying.on("value", this.onUpdate, this); this.activeDocument.setup.audio.outs.narrationPlaying.on("value", this.onUpdate, this); this.activeDocument.setup.audio.ins.captionsEnabled.on("value", this.onUpdate, this); this.titleElement = this.createElement("div", null); this.titleElement.classList.add("ff-ellipsis"); this.assetPath = this.assetReader.getSystemAssetUrl(""); } protected disconnected() { this.activeDocument.setup.audio.ins.captionsEnabled.off("value", this.onUpdate, this); this.activeDocument.setup.audio.outs.narrationPlaying.off("value", this.onUpdate, this); this.activeDocument.setup.audio.outs.isPlaying.off("value", this.onUpdate, this); this.activeDocument.setup.language.outs.activeLanguage.off("value", this.onUpdate, this); this.toolProvider.ins.visible.off("value", this.onUpdate, this); super.disconnected(); } protected render() { const document = this.activeDocument; const titleElement = this.titleElement; if (!document) { return html``; } const setup = document.setup; const interfaceVisible = setup.interface.ins.visible.value; const logoVisible = setup.interface.ins.logo.value && setup.interface.isShowing(EUIElements.logo); const menuVisible = setup.interface.ins.menu.value && setup.interface.isShowing(EUIElements.menu); const titleVisible = setup.interface.ins.visibleElements.value && setup.interface.isShowing(EUIElements.title); const helpVisible = setup.interface.ins.visibleElements.value && setup.interface.isShowing(EUIElements.help); const resetVisible = setup.interface.ins.visibleElements.value && setup.interface.isShowing(EUIElements.reset); const readerVisible = setup.reader.ins.enabled.value; const tours = setup.tours.tours; const toursEnabled = setup.tours.ins.enabled.value; const tourActive = setup.tours.outs.tourIndex.value >= 0; const languageManager = setup.language; const languages = languageManager.sceneLanguages; const activeLanguage = languageManager.outs.activeLanguage.value; const languagesVisible = languages.length > 1 && setup.interface.isShowing(EUIElements.language); const captionsVisible = setup.audio.outs.isPlaying.value && setup.audio.getClipCaptionUri(setup.audio.activeId); const captionsEnabled = setup.audio.ins.captionsEnabled.value; const audioVisible = setup.audio.outs.narrationPlaying.value; const isEditing = !!this.system.getComponent("CVStoryApplication", true); const toolBarAllowed = isEditing || !toursEnabled; // tag cloud is visible if annotations are enabled and there is at least one tag in the cloud const tagCloudVisible = setup.viewer.ins.annotationsVisible.value && setup.viewer.outs.tagCloud.value; const toolsVisible = !readerVisible && this.toolProvider.ins.visible.value; const showTourEndMsg = this.activeDocument.setup.tours.outs.ending.value; this.activeDocument.setup.tours.outs.ending.setValue(false); const introText = this.activeDocument.outs.intro.value; if(introText) { // TODO: Stop intro pop-up from spawning when setting property in Story if(this.needsSplash && introText.length > 0) { SplashScreen.show(this, this.activeDocument.setup.language, introText).then(() => { (this.getRootNode() as ShadowRoot).getElementById("sv-scene").focus(); }); } this.needsSplash = false; } if (!interfaceVisible) { return html``; } let title; if (toursEnabled) { if (!tourActive) { title = languageManager.getLocalizedString("Interactive Tours"); } else { title = languageManager.getLocalizedString("Tour") + ": " + setup.tours.outs.tourTitle.value; } } else { title = document.outs.title.value || "Missing Title" || document.name; } titleElement.innerHTML = title; return html`${showTourEndMsg ? html`