/** * Funded by the Netherlands eScience Center in the context of the * [Dynamic 3D]{@link https://research-software-directory.org/projects/dynamic3d} project * and the "Paradata in 3D Scholarship" workshop {@link https://research-software-directory.org/projects/paradata-in-3d-scholarship} * * @author Carsten Schnober */ import { EShadowMapResolution } from "@ff/scene/components/CLight"; import CSunLight from "@ff/scene/components/CSunLight"; import dayjs from "dayjs"; import { ColorRGB, IDocument, ILight, INode, TLightType } from "../../schema/document"; import { ICVLight } from "./CVLight"; import NVNode from "client/nodes/NVNode"; import { Vector3 } from "three"; import CVScene from "../CVScene"; const _vec3 = new Vector3(); export default class CVSunLight extends CSunLight implements ICVLight { static readonly typeName: string = "CVSunLight"; static readonly type: TLightType = "sun"; static readonly text: string = "Sun"; static readonly icon: string = "sun"; static readonly isGraphSingleton = true; get settingProperties() { return [ this.ins.enabled, this.ins.color, this.ins.intensity, this.ins.tags, this.ins.datetime, this.ins.timezone, this.ins.latitude, this.ins.longitude, this.ins.intensityFactor, // shadow properties this.ins.shadowEnabled, this.ins.shadowSize, this.ins.shadowResolution, this.ins.shadowBlur, this.ins.shadowIntensity, ]; } get snapshotProperties() { return [ this.ins.color, this.ins.intensity, this.ins.datetime, this.ins.timezone, this.ins.latitude, this.ins.longitude, this.ins.intensityFactor, ]; } create() { super.create(); this.light.position.setScalar(0); (this.node as NVNode).transform.addTag("no_settings"); } dispose(): void { if (this.ins.shadowEnabled.value && this.light.shadow.map) { this.light.shadow.map.dispose(); } super.dispose() } update(context) { super.update(context); if(this.ins.intensity.changed) { const scene = this.getSystemComponent(CVScene); _vec3.fromArray(this.transform.ins.position.value); _vec3.normalize().multiplyScalar(scene.outs.boundingRadius.value*1.2); this.transform.ins.position.setValue(_vec3.toArray()); } return true; } fromDocument(document: IDocument, node: INode): number { if (!isFinite(node.light)) { throw new Error("light property missing in node"); } const data = document.lights[node.light]; const ins = this.ins; if (data.type !== "sun") { throw new Error("light type mismatch: not a sun light"); } ins.name.setValue(node.name); ins.copyValues({ enabled: data.enabled !== undefined ? data.enabled : ins.enabled.schema.preset, color: data.color !== undefined ? data.color : ins.color.schema.preset, intensity: data.intensity !== undefined ? data.intensity : ins.intensity.schema.preset, datetime: data.sun?.datetime !== undefined ? dayjs(data.sun.datetime).tz(data.sun.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone) : ins.datetime.schema.preset, timezone: data.sun?.timezone !== undefined ? data.sun.timezone : ins.timezone.schema.preset, latitude: data.sun?.latitude !== undefined ? data.sun.latitude : ins.latitude.schema.preset, longitude: data.sun?.longitude !== undefined ? data.sun.longitude : ins.longitude.schema.preset, intensityFactor: data.sun?.intensityFactor !== undefined ? data.sun.intensityFactor : ins.intensityFactor.schema.preset, position: ins.position.schema.preset, target: ins.target.schema.preset, shadowEnabled: data.shadowEnabled || false, shadowSize: data.shadowSize !== undefined ? data.shadowSize : ins.shadowSize.schema.preset, shadowResolution: data.shadowResolution !== undefined ? EShadowMapResolution[data.shadowResolution] || 0 : ins.shadowResolution.schema.preset, shadowBlur: data.shadowBlur !== undefined ? data.shadowBlur : ins.shadowBlur.schema.preset, shadowIntensity: data.shadowIntensity !== undefined ? data.shadowIntensity : ins.shadowIntensity.schema.preset, }); return node.light; } toDocument(document: IDocument, node: INode): number { const ins = this.ins; const data: ILight = { type: CVSunLight.type, enabled: ins.enabled.value, color: ins.color.cloneValue() as ColorRGB, intensity: ins.intensity.value, sun: { datetime: ins.datetime.value.tz(ins.timezone.value, true).format(), timezone: ins.timezone.value, latitude: ins.latitude.value, longitude: ins.longitude.value, intensityFactor: ins.intensityFactor.value, } }; if (ins.shadowEnabled.value) { data.shadowEnabled = true; if (!ins.shadowSize.isDefault()) { data.shadowSize = ins.shadowSize.value; } if (!ins.shadowBlur.isDefault()) { data.shadowBlur = ins.shadowBlur.value; } if (!ins.shadowResolution.isDefault()) { data.shadowResolution = EShadowMapResolution[ins.shadowResolution.value]; } if (!ins.shadowIntensity.isDefault()) { data.shadowIntensity = ins.shadowIntensity.value; } } document.lights = document.lights || []; const lightIndex = document.lights.length; document.lights.push(data); return lightIndex; } }