@realsee/dnalogel
Version:
468 lines (462 loc) • 20.4 kB
JavaScript
var P = Object.defineProperty, V = Object.defineProperties;
var T = Object.getOwnPropertyDescriptors;
var k = Object.getOwnPropertySymbols;
var F = Object.prototype.hasOwnProperty, L = Object.prototype.propertyIsEnumerable;
var v = (h, e, t) => e in h ? P(h, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[e] = t, d = (h, e) => {
for (var t in e || (e = {}))
F.call(e, t) && v(h, t, e[t]);
if (k)
for (var t of k(e))
L.call(e, t) && v(h, t, e[t]);
return h;
}, p = (h, e) => V(h, T(e));
var i = (h, e, t) => (v(h, typeof e != "symbol" ? e + "" : e, t), t);
import * as n from "three";
import { logWarning as S, logError as U } from "../../shared-utils/log.js";
import { createLineGeometry as x } from "../utils/createLineGeometry.js";
import { isPanoramaLike as M, isModelLike as O } from "../../shared-utils/five/mode.js";
import "hammerjs";
import "@realsee/five";
import "../../vendor/@tweenjs/tween/dist/tween.esm.js.js";
import "../../CSS3DRenderPlugin/utils/three/CSS3DRender.js";
import "../../CSS3DRenderPlugin/utils/generateBehindFiveElement.js";
import { BetterTween as _, tweenProgress as A } from "../../shared-utils/animationFrame/BetterTween.js";
import { loadTexture as G } from "../../shared-utils/three/loadTexture.js";
import w from "../../PanoTagPlugin/controller/index.js";
import E from "../Components/Tag.js";
import { filterAdjacentDistinct as B } from "../utils/index.js";
import { objectAssignDeepExports as I } from "../../vendor/object-assign-deep/objectAssignDeep.js";
const R = (
/* glsl */
`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`
), W = (
/* glsl */
`
// 是否使用颜色
uniform int useMapColor;
// 贴图
uniform sampler2D map;
// 贴图颜色
uniform vec3 mapColor;
// 贴图透明度
uniform float mapOpacity;
// 背景颜色
uniform vec3 backgroundColor;
// 边框颜色
uniform vec3 borderColor;
// 边框透明度
uniform float borderOpacity;
// 背景透明度
uniform float backgroundOpacity;
// 整体透明度
uniform float opacity;
// 最大 U 值
uniform float maxU;
// v offset
uniform float vOffset;
// 闪烁动画值
uniform float flicker;
// 纹理坐标
varying vec2 vUv;
// 获取纹理颜色
vec4 getImage() {
vec2 uv = vUv;
uv.y = uv.y - vOffset;
// 原始贴图颜色
vec4 image = texture2D(map, uv);
// 如果使用颜色
if (useMapColor == 1) {
// 混合颜色
image = mix(image, vec4(mapColor, image.a), image.a);
}
image.a = image.a * mapOpacity;
return image;
}
// 获取线性渐变的透明度
float linearGradientOpacity() {
// 当前的 v 值
float v = vUv.y;
float gradientLength = 1.0;
if (v <= gradientLength) {
return v / gradientLength; // 在 [0, gradientLength] 范围内,透明度为 [0, 1]
} else if (v <= maxU - gradientLength) {
return 1.0; // 在 (gradientLength, maxU - gradientLength) 范围内,透明度为 1
} else {
return (maxU - v) / gradientLength; // 在 [maxU - gradientLength, maxU] 范围内,透明度为 [1, 0]
}
}
vec4 getBorder() {
float u = vUv.x;
float borderSize = 0.05;
if (u <= borderSize || u >= 1.0 - borderSize) {
return vec4(borderColor, borderOpacity);
}
return vec4(0.0, 0.0, 0.0, 0.0);
}
void main() {
vec4 image = getImage();
vec4 border = getBorder();
// 设置背景颜色
gl_FragColor = vec4(backgroundColor, backgroundOpacity);
// 混合颜色和背景
gl_FragColor = mix(gl_FragColor, image, image.a);
// 混合边框
gl_FragColor = mix(gl_FragColor, border, border.a);
// 设置整体透明度
gl_FragColor.a = gl_FragColor.a * opacity;
gl_FragColor.a = gl_FragColor.a * linearGradientOpacity();
gl_FragColor.a = gl_FragColor.a * flicker;
}
`
);
class N {
constructor(e, t) {
i(this, "name", "");
i(this, "startTagContainer");
i(this, "endTagContainer");
i(this, "path", []);
i(this, "geometryStyle", {});
i(this, "materialStyle", {});
i(this, "meshStyle", {});
i(this, "mesh");
i(this, "five");
i(this, "mode");
i(this, "_curvePath", null);
i(this, "_curvePoints", null);
i(this, "_panoGroup", []);
i(this, "skippedPositions", null);
i(this, "textureUrl", "");
i(this, "scale", 1);
i(this, "width", 0.5);
i(this, "unitLength", 0.5);
i(this, "_visibleFloorIndexes", null);
i(this, "visible", null);
/** Five Mode 是否满足 */
i(this, "modeVisible", !1);
/** 楼层是否满足展示条件 */
i(this, "floorVisible", !0);
/** 默认是否展示 */
i(this, "defaultVisible", !1);
/** 走点动画 */
i(this, "inWalkAnimation", !1);
i(this, "customVisible", null);
i(this, "parent");
i(this, "plugin");
i(this, "textureHasLoaded", !1);
i(this, "disposed", !1);
i(this, "flowAnime", new _({ progress: 0 }).to({ progress: 1 }).duration(1500).repeat(1 / 0));
i(this, "flickerAnime", A(300).yoyo(!0).repeat(5));
/** 缓存 panoGroup 中每个点距离起点的长度 */
i(this, "cacheLengths", []);
/** 为了让多条路线在高度上错开,每个路线都需要有个额外的 offset */
i(this, "heightOffset", 0);
i(this, "dispose", () => {
var e, t;
this.disposed || (this.disposed = !0, this.parent.hooks.off("show", this.updateVisible), this.parent.hooks.off("hide", this.updateVisible), this.plugin.hooks.off("show", this.updateVisible), this.plugin.hooks.off("hide", this.updateVisible), this.plugin.hooks.off("enable", this.updateVisible), this.plugin.hooks.off("disable", this.updateVisible), this.five.off("modeChange", this.onFiveModeChange), this.five.off("modelShownFloorChange", this.onFiveModelShownFloorChange), this.doHide(), (e = this.startTagContainer) == null || e.plugin.dispose(), (t = this.endTagContainer) == null || t.plugin.dispose());
});
/** 开始走点动画 */
i(this, "onWalkAnimationStart", () => {
this.inWalkAnimation = !0, this.updateVisible();
});
/** 结束走点动画 */
i(this, "onWalkAnimationEnd", () => {
this.inWalkAnimation = !1, this.updateVisible();
});
/** 模型状态变更 */
i(this, "onFiveModeChange", (e) => {
this.modeVisible = this.mode === "panorama" ? M(e) : O(e), this.updateVisible();
});
i(this, "onFiveModelShownFloorChange", (e) => {
this.floorVisible = e === null || this.visibleFloorIndexes === null || this.visibleFloorIndexes.includes(e), this.updateVisible();
});
/** 更新可见性 */
i(this, "updateVisible", () => {
const e = (() => !this.parent.visible || !this.plugin.state.enabled || !this.plugin.state.visible ? !1 : this.customVisible !== null ? this.customVisible : this.inWalkAnimation ? !0 : this.modeVisible && this.textureHasLoaded && this.defaultVisible && this.floorVisible)();
this.visible !== e && (this.visible = e, e ? this.doShow() : this.doHide());
});
i(this, "onFlowAnimeUpdate", (e) => {
const { progress: t } = e;
this.mesh.material.uniforms.vOffset.value = t, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0;
});
i(this, "onFlickerAnimeUpdate", (e) => {
var s, o, a, l;
const { progress: t } = e, r = 1 - t;
this.mesh.material.uniforms.flicker.value = r, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0, this.startTagContainer.tag && y(this.startTagContainer.tag) && ((a = this.startTagContainer.app) == null || a.$set(p(d({}, this.startTagContainer.tag.data), {
opacity: r,
name: this.name,
distance: Math.round((o = (s = this.curvePath) == null ? void 0 : s.getLength()) != null ? o : 0)
}))), this.endTagContainer.tag && y(this.endTagContainer.tag) && ((l = this.endTagContainer.app) == null || l.$set(p(d({}, this.endTagContainer.tag.data), { opacity: r })));
});
i(this, "logWarning", (e) => S("GuideLineModeItem: ", e));
i(this, "logError", (e) => U("GuideLineModeItem: ", e));
var o, a;
this.five = e, this.mode = t.mode, this.plugin = t.plugin, this.parent = t.parent, this.startTagContainer = { tag: null, plugin: new w(this.five) }, this.endTagContainer = { tag: null, plugin: new w(this.five) };
const r = new n.BufferGeometry(), s = new n.ShaderMaterial({
vertexShader: R,
fragmentShader: W,
transparent: !0,
uniforms: {
map: { value: null },
useMapColor: { value: 0 },
mapColor: { value: new n.Color() },
mapOpacity: { value: 1 },
backgroundColor: { value: new n.Color() },
backgroundOpacity: { value: 0 },
borderColor: { value: new n.Color() },
borderOpacity: { value: 0 },
opacity: { value: 1 },
flicker: { value: 1 },
maxU: { value: 0 },
vOffset: { value: 0 }
}
});
this.mesh = new n.Mesh(r, s), this.mesh.name = "GuideLineModeItem", this.mode === "panorama" && (this.parent.hooks.on("walkStart", this.onWalkAnimationStart), this.parent.hooks.on("walkEnded", this.onWalkAnimationEnd)), this.updateVisible(), this.onFiveModeChange(this.five.getCurrentState().mode), this.onFiveModelShownFloorChange((a = (o = this.five.model) == null ? void 0 : o.shownFloor) != null ? a : null), this.flowAnime.onUpdate(this.onFlowAnimeUpdate), this.flickerAnime.onUpdate(this.onFlickerAnimeUpdate), this.parent.hooks.on("show", this.updateVisible), this.parent.hooks.on("hide", this.updateVisible), this.plugin.hooks.on("show", this.updateVisible), this.plugin.hooks.on("hide", this.updateVisible), this.plugin.hooks.on("enable", this.updateVisible), this.plugin.hooks.on("disable", this.updateVisible), this.plugin.hooks.on("dispose", this.dispose), this.five.on("modeChange", this.onFiveModeChange), this.five.on("modelShownFloorChange", this.onFiveModelShownFloorChange);
}
get panoGroup() {
return this._panoGroup;
}
/** 可展示的楼层 */
get visibleFloorIndexes() {
return this._visibleFloorIndexes;
}
/** THREE Curve 路径 */
get curvePath() {
return this._curvePath;
}
/** THREE Curve 路径上的点 */
get curvePoints() {
return this._curvePoints;
}
/** 自定义展示 */
setCustomVisible(e) {
if (this.disposed)
return this.logError("disposed");
this.customVisible !== e && (this.customVisible = e, this.updateVisible());
}
/** 设置默认展示 */
setDefaultVisible(e) {
if (this.disposed)
return this.logError("disposed");
this.defaultVisible !== e && (this.defaultVisible = e, this.updateVisible());
}
/** 基础宽、长 */
setUnitSize(e, t) {
if (this.disposed)
return this.logError("disposed");
this.width = e, this.unitLength = t, this.setGeometryByPath(this.path, { width: e, unit_length: t });
}
/** 设置缩放 */
setScale(e) {
if (this.disposed)
return this.logError("disposed");
this.scale = e, this.setGeometryByPath(this.path, { scale: e });
}
/** 通过点位设置线条形状 */
setGeometryByPanoGroup(e, t) {
if (this.disposed)
return this.logError("disposed");
if (!this.five.work)
return this.logError("setPathByPanoGroup: work is not ready");
const r = B(e);
if (this._panoGroup = r, (t == null ? void 0 : t.skipPanoGroup) !== void 0) {
const o = t.skipPanoGroup ? r.map((a) => this.plugin.workUtils.getObserverStandingPosition(a)) : null;
this.skippedPositions = o;
}
const s = this.getPathFromPanoGroup(r, this.five.work, t);
this.path = s, this.setGeometryByPath(s, t);
}
/** 通过路径设置线条形状 */
setGeometryByPath(e, t) {
var c, b, C;
if (this.disposed)
return this.logError("disposed");
const r = (c = t == null ? void 0 : t.scale) != null ? c : this.scale, s = (b = t == null ? void 0 : t.width) != null ? b : this.width, o = (C = t == null ? void 0 : t.unit_length) != null ? C : this.unitLength;
this.scale = r, this.width = s, this.unitLength = o;
const { geometry: a, maxU: l, curvePath: u, curvePoints: g } = x({
path: e,
width: s * r,
unitLength: o * r,
skipPositions: this.skippedPositions
});
this._curvePath = u, this._curvePoints = g, this.mesh.geometry = a, this.mesh.material.needsUpdate = !0, this.mesh.material.uniforms.maxU.value = l, this.five.needsRender = !0;
const m = e, f = d(d({}, this.geometryStyle), t);
this.path = m, this.geometryStyle = f;
}
/** 设置线条材质 */
setMartial(e) {
var r;
if (this.disposed)
return this.logError("disposed");
(e == null ? void 0 : e.visible) !== void 0 && this.setDefaultVisible(e.visible), (e == null ? void 0 : e.color) !== void 0 && this.setColor(e.color), (e == null ? void 0 : e.opacity) !== void 0 && this.setOpacity(e.opacity), ((r = e == null ? void 0 : e.texture) == null ? void 0 : r.url) !== void 0 && this.setTextureUrl(e.texture.url), (e == null ? void 0 : e.background_color) !== void 0 && this.setBackgroundColor(e.background_color), (e == null ? void 0 : e.background_opacity) !== void 0 && this.setBackgroundOpacity(e.background_opacity), (e == null ? void 0 : e.border_color) !== void 0 && this.setBorderColor(e.border_color), (e == null ? void 0 : e.border_opacity) !== void 0 && this.setBorderOpacity(e.border_opacity);
const t = d(d({}, this.materialStyle), e);
this.materialStyle = t;
}
/** 设置模型状态 */
setMeshStyle(e) {
if (e != null && e.translate) {
const s = new n.Vector3(), o = new n.Vector3().fromArray(e.translate);
o.y += this.heightOffset, s.add(o), this.mesh.position.copy(s), r(this.startTagContainer, o), r(this.endTagContainer, o);
}
const t = d(d({}, this.meshStyle), e);
this.meshStyle = t;
function r(s, o) {
if (!s.tag)
return;
const a = new n.Vector3().fromArray(s.tag.position);
a.add(o);
const l = a.toArray();
s.plugin.changeTagById(s.tag.id, { position: l });
}
}
/** 设置 Y 轴上的偏移量,为了让多条路线在高度上错开,每个路线都需要有个额外的 offset */
setHeightOffset(e) {
const t = new n.Vector3();
this.meshStyle.translate && t.add(new n.Vector3().fromArray(this.meshStyle.translate)), t.setY(t.y + e), this.mesh.position.copy(t), this.heightOffset = e, this.five.needsRender = !0;
}
/** 设置贴图颜色 */
setColor(e) {
if (this.disposed)
return this.logError("disposed");
e && (this.mesh.material.uniforms.mapColor.value = new n.Color().set(e)), this.mesh.material.uniforms.useMapColor.value = e ? 1 : 0, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0;
}
/** 设置边框 */
setBorderColor(e) {
if (this.disposed)
return this.logError("disposed");
this.mesh.material.uniforms.borderColor.value = new n.Color().set(e), this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0;
}
/** 设置边框透明度 */
setBorderOpacity(e) {
if (this.disposed)
return this.logError("disposed");
this.mesh.material.uniforms.borderOpacity.value = e, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0;
}
/** 设置背景颜色 */
setBackgroundColor(e) {
if (this.disposed)
return this.logError("disposed");
this.mesh.material.uniforms.backgroundColor.value = new n.Color().set(e), this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0;
}
/** 设置背景透明度 */
setBackgroundOpacity(e) {
if (this.disposed)
return this.logError("disposed");
this.mesh.material.uniforms.backgroundOpacity.value = e, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0;
}
/** 设置整体透明度 */
setOpacity(e) {
if (this.disposed)
return this.logError("disposed");
this.mesh.material.uniforms.opacity.value = e, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0;
}
/** 设置贴图透明度 */
setMapOpacity(e) {
if (this.disposed)
return this.logError("disposed");
this.mesh.material.uniforms.mapOpacity.value = e, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0;
}
/** 设置贴图 */
setTextureUrl(e) {
if (this.disposed)
return this.logError("disposed");
this.textureUrl = e, G(e).then((t) => {
this.disposed || this.textureUrl === e && (t.wrapT = n.RepeatWrapping, this.textureHasLoaded = !0, this.mesh.material.uniforms.map.value = t, this.mesh.material.uniformsNeedUpdate = !0, this.mesh.material.needsUpdate = !0, this.five.needsRender = !0, this.updateVisible());
});
}
setVisibleFloorIndexes(e) {
var t, r;
if (this.disposed)
return this.logError("disposed");
this._visibleFloorIndexes = e, this.onFiveModelShownFloorChange((r = (t = this.five.model) == null ? void 0 : t.shownFloor) != null ? r : null);
}
setStartTag(e) {
this.setTag("start", e);
}
setEndTag(e) {
this.setTag("end", e);
}
/** 闪烁 */
flicker() {
if (this.disposed)
return this.logError("disposed");
this.flickerAnime.play();
}
/** 求起点到 panoIndex 曲线长度
* @param index panoIndex 在 panoGroup 中的索引
*
* @description 为什么不使用 panoIndex 作为参数?
* - panoIndex 在一个曲线中可能出现多次,无法确定是哪一个。
*/
getLengthByPanoGroupIndex(e) {
return this.disposed ? this.logError("disposed") : this.cacheLengths.length !== 0 ? this.cacheLengths[e] : (this.cacheLengths = this.getPanoGroupLengths(), this.cacheLengths[e]);
}
getPanoGroupLengths() {
var u;
if (!this.curvePoints || !this.curvePath)
return [];
const e = this.curvePoints.length, t = this.curvePath.getLength(), r = e - 1, s = t / r, o = (u = this.curvePath.getLengths(r)) != null ? u : [], a = [];
let l = 0;
for (let g = 0; g < e; g++) {
const m = this.curvePoints[g], f = this.plugin.workUtils.getObserverStandingPosition(l);
if (!f)
break;
f.clone().setY(0).distanceTo(m.clone().setY(0)) < s && (a.push(o[g]), l += 1);
}
return a;
}
setTag(e, t) {
const r = this.curvePath, s = e === "start" ? this.startTagContainer : this.endTagContainer;
if (!(t != null && t.data))
return s.plugin.clearTags();
const a = I({}, {
contentType: "Custom",
stickType: "2DPoint",
config: { visibleConfig: { visibleFiveMode: ["Floorplan", "Mapview"], followModelVisibility: !1 } },
style: { point: { enabled: !1 } },
data: {}
}, t);
s.tag = a, y(a) && (s.tag.element = (u) => {
var f, c;
(f = s.app) == null || f.$destroy();
const g = e === "start" ? p(d({}, a.data), { name: this.name, distance: Math.round((c = r.getLength()) != null ? c : 0), i18n: this.plugin.config.i18n }) : a.data, m = new E({ target: u, intro: !0, props: g });
return s.app = m, () => m.$destroy();
}), s.plugin.load({ tagList: [s.tag] });
const l = this.meshStyle.translate;
if (l && a.position) {
const u = new n.Vector3().fromArray(a.position), g = new n.Vector3().fromArray(l);
u.add(g), u.y += this.heightOffset;
const m = u.toArray();
s.plugin.changeTagById(s.tag.id, { position: m });
}
}
doShow() {
this.mode === "model" && this.flowAnime.play(), this.five.scene.add(this.mesh), this.startTagContainer.plugin.show(), this.endTagContainer.plugin.show(), this.five.needsRender = !0;
}
doHide() {
this.mode === "model" && this.flowAnime.stop(), this.five.scene.remove(this.mesh), this.startTagContainer.plugin.hide(), this.endTagContainer.plugin.hide(), this.five.needsRender = !0;
}
/** 通过 panoIndex 数组计算路径 */
getPathFromPanoGroup(e, t, r) {
if (e.length < 2)
return [];
const s = e.map((o) => this.plugin.workUtils.getObserverStandingPosition(o).toArray());
return [d({ type: "CatmullRomCurve3", points: s }, r)];
}
}
function y(h) {
return h.contentType === "Custom";
}
const se = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
GuideLineModeItem: N
}, Symbol.toStringTag, { value: "Module" }));
export {
N as GuideLineModeItem,
se as GuideLineModeItem$1
};