@realsee/dnalogel
Version:
393 lines (392 loc) • 17.6 kB
JavaScript
var j = Object.defineProperty;
var v = Object.getOwnPropertySymbols;
var P = Object.prototype.hasOwnProperty, _ = Object.prototype.propertyIsEnumerable;
var A = (m, o, t) => o in m ? j(m, o, { enumerable: !0, configurable: !0, writable: !0, value: t }) : m[o] = t, u = (m, o) => {
for (var t in o || (o = {}))
P.call(o, t) && A(m, t, o[t]);
if (v)
for (var t of v(o))
_.call(o, t) && A(m, t, o[t]);
return m;
};
var d = (m, o, t) => (A(m, typeof o != "symbol" ? o + "" : o, t), t);
var c = (m, o, t) => new Promise((e, i) => {
var s = (a) => {
try {
n(t.next(a));
} catch (h) {
i(h);
}
}, r = (a) => {
try {
n(t.throw(a));
} catch (h) {
i(h);
}
}, n = (a) => a.done ? e(a.value) : Promise.resolve(a.value).then(s, r);
n((t = t.apply(m, o)).next());
});
import * as F from "three";
import { Controller as S } from "../base/BasePluginWithData.js";
import "../shared-utils/tag.js";
import "../vendor/hammerjs/hammer.js";
import "../shared-utils/three/PointSelector/index.js";
import "../shared-utils/three/CSS3DRenderer/index.js";
import "../CSS3DRenderPlugin/utils/generateBehindFiveElement.js";
import "@realsee/five/line";
import { notNil as T } from "../shared-utils/isNil.js";
import "../shared-utils/three/core/Five_LineMaterial2.js";
import "../shared-utils/three/core/Sphere.js";
import "../shared-utils/three/blink.js";
import "../vendor/@tweenjs/tween/dist/tween.esm.js.js";
import "../CSS3DRenderPlugin/utils/three/CSS3DRender.js";
import "../vendor/earcut/src/earcut.js";
import { equal as O } from "../shared-utils/equal.js";
import "../shared-utils/five/FivePuppet.js";
import { loadTexture as x } from "../shared-utils/three/loadTexture.js";
import { format as y, getPipesFromLibrary as C } from "./utils/formatData.js";
import { ObjectFlowPipe as D } from "./utils/Objects/FlowPipe.js";
import "../base/BasePlugin.js";
import "../shared-utils/Subscribe.js";
import "../shared-utils/Utils/FiveUtil.js";
import "../shared-utils/Utils/BaseUtil.js";
import "../shared-utils/Utils/WorkUtil.js";
import "../shared-utils/five/transformPosition.js";
import "../shared-utils/five/getFiveModel.js";
import "../shared-utils/url/defaultUrls.js";
import "../shared-utils/positionToVector3.js";
import "../shared-utils/five/vector3ToScreen.js";
import "../shared-utils/three/temp.js";
import "../shared-utils/three/core/Raycaster.js";
import "../shared-utils/dom/resizeObserver.js";
import "../shared-utils/five/fiveEveryReadyListener.js";
import "../shared-utils/throttle.js";
import "../shared-utils/five/fiveModelLoad.js";
import "../shared-utils/three/PointSelector/utils/PointSelectorHelper.js";
import "../shared-utils/three/Magnifier.js";
import "../shared-utils/three/PointSelector/utils/PointHelper.js";
import "../shared-utils/three/Assets/index.js";
import "../CSS3DRenderPlugin/utils/three/CSS3DObject.js";
import "../shared-utils/even.js";
import "../shared-utils/CSS3DRender/OpacityMesh.js";
import "../shared-utils/three/centerPoint.js";
import "../shared-utils/three/getObjectVisible.js";
import "../shared-utils/three/PointSelector/utils/html.js";
import "../shared-utils/CSS3DRender/index.js";
import "../shared-utils/CSS3DRender/CSS3DRenderer.js";
import "../shared-utils/createResizeObserver.js";
import "../shared-utils/three/PointSelector/utils/PointHelper2.js";
import "../Sculpt/Meshes/Line.js";
import "../Sculpt/typings/style.js";
import "../shared-utils/three/IObject3D.js";
import "../Sculpt/utils/Meshes/getLengthHTML.js";
import "../shared-utils/three/applyObjectMatrixWorld.js";
import "../shared-utils/util.js";
import "../shared-utils/five/getFiveFromParentChain.js";
import "../shared-utils/three/core/LineGeometry.js";
import "../shared-utils/three/core/LineMaterial.js";
import "../shared-utils/three/core/Line2.js";
import "../shared-utils/three/core/LineMaterial2.js";
import "../Sculpt/utils/unit.js";
import "../Sculpt/utils/renderDom.js";
import "../CSS3DRenderPlugin/utils/three/CSS3DSprite.js";
import "../shared-utils/isTouchDevice.js";
import "../shared-utils/five/getPosition.js";
import "../shared-utils/five/getRaycasterByNdcPosition.js";
import "../shared-utils/three/PointSelector/utils/contents.js";
import "../Sculpt/utils/three/rayOnLine.js";
import "../vendor/animejs/lib/anime.es.js";
import "../CSS3DRenderPlugin/utils/three/CSS3DScene.js";
import "../CSS3DRenderPlugin/utils/getAllCSS3DObject.js";
import "../CSS3DRenderPlugin/utils/three/CSS3DGroup.js";
import "@realsee/five";
import "../shared-utils/isTruelyObject.js";
import "../shared-utils/animationFrame/index.js";
import "./utils/Objects/Pipe.js";
import "../shared-utils/animationFrame/BetterTween.js";
import "../shared-utils/three/Extras/Curves/BezierCurve3.js";
import "../shared-utils/three/Extras/Core/Interpolations.js";
import "../shared-utils/three/Extras/Core/Interpolations2.js";
const g = { flowSpeed: 0.6, rotateSpeed: 0 };
class ae extends S {
constructor(t) {
super(t);
// ==================== public properties ====================
d(this, "data");
/** 插件状态
* @property `visible` `<boolean>` 是否可见
* @property `enabled` `<boolean>` 是否启用
* @property `visiblePipeIDs` `<string[]>` 可见的管道 ID
* @property `speed` `<Speed>` 水流速度
* @property `speed.flowSpeed` `<number>` 横向流动速度,默认是 0.6 m/s
* @property `speed.rotateSpeed` `<number>` 纵向旋转速度:默认是 0 deg/s
*/
d(this, "state");
/** 当前插件所有新增 THREE 相关副作用都在 group 下 */
d(this, "group");
/** 用于展示水流的水管 */
d(this, "pipeObjects", []);
// ==================== private properties ====================
/** 水管贴图缓存 */
d(this, "texturePromiseCache", /* @__PURE__ */ new Map());
/** 销毁插件,移除所有副作用,销毁后将不响应任何 API */
d(this, "dispose", () => {
this.disable(), this.five.scene.remove(this.group), this.texturePromiseCache.forEach((t) => t.then((e) => e.dispose())), this.texturePromiseCache.clear();
});
d(this, "onWantsFiveTapGesture", (...t) => {
const [e] = t, i = e.intersectObjects(this.pipeObjects, !1);
if (i.length === 0 || !this.data)
return;
const n = i[0].object.customID, a = this.data.pipes.find(({ id: p }) => p === n), h = this.data.pipelines.find((p) => a && p.pipes.includes(a));
if (!(!a || !h))
return this.hooks.emit("tap", {
intersectObjects: i,
pipe: a,
pipeline: h,
wantsFiveTapGestureParams: t
}), !1;
});
this.state = {
target: null,
visible: !0,
enabled: !0,
isFlowing: !1,
speed: g
}, this.five = t, this.group = new F.Group(), this.group.name = "water-pipe-group", this.five.scene.add(this.group), this.five.once("dispose", this.dispose), this.five.on("wantsTapGesture", this.onWantsFiveTapGesture);
}
/** 加载管道数据,重复调用会使用新数据覆盖旧数据
* @param `data` `<Plugin.ServerData>` Open API 接口返回的数据。
* @param `initialState` `<Plugin.State> | <undefined>` 数据加载后,要应用的 state,默认是 undefined。
* @param `userAction` `<boolean> | <undefined>` 是否是用户操作,默认是 true。
* @param `options` `<Plugin.LoadOptions> | <undefined>` 数据加载配置项。
* @param `options.getPipeRadius` `<(pipe: ServerData.LinesDataset) => number> | <undefined>` 允许用户通过函数自定义管道半径。
* @param `options.getPipeUrl` `<(water: Water) => string> | <undefined>` 允许用户通过函数自定义管道贴图,
* 函数返回的 string 就是当前 water 对应的贴图地址。
*/
// eslint-disable-next-line max-params
load(t, e, i, s) {
return c(this, null, function* () {
const r = this.data;
this.data = yield this.formatData(t, s), this.removeAllPipes(), this.hooks.emit("dataChange", this.data, r), this.pipeObjects = yield Promise.all(
this.data.pipes.filter((n) => !!(n != null && n.texture)).map((b) => c(this, [b], function* ({ id: n, texture: a, path: h, radius: p }) {
const l = yield this.loadPipeTexture(a), f = { id: n, path: h, textureURL: a, texture: l, geometryConfig: { radius: p } };
return new D(f);
}))
), this.data.pipelines.forEach((n) => {
n.pipes.reduce((a, h) => {
const p = this.findPipeObjectWithID(h.id);
return p == null || p.setInitialDisplacement(a), a + ((p == null ? void 0 : p.pathLength) || 0);
}, 0);
}), this.hooks.emit("dataLoaded", this.data), this.state.visible === !1 && this.pipeObjects.forEach((n) => n.setOpacity(0)), this.state.enabled && (this.group.add(...this.pipeObjects), this.five.needsRender = !0), e && this.setState(e, { userAction: i });
});
}
/** 更改插件 State
* @param `state` `<Partial<Plugin.State>>` 插件属性 `state` 的子集。
* @param `options` `<Option> | <undefined>`
* @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。
*/
setState(t, e = {}) {
const i = this.state;
if (O(t, i, { deep: !0 }))
return;
const s = e.userAction !== void 0 ? e.userAction : !0;
if (this.updateState(t, s), t.enabled !== void 0 && i.enabled !== t.enabled && (t.enabled ? this._enable({ userAction: s }) : this._disable({ userAction: s })), t.visible !== void 0 && i.visible !== t.visible) {
const r = { userAction: s, anime: { duration: 500 } };
t.visible ? this._show(r) : this._hide(r);
}
if (t.isFlowing !== void 0 && i.isFlowing !== t.isFlowing && (t.isFlowing ? this._flow() : this._stopFlow()), t.speed !== void 0 && !O(i.speed, this.state.speed, { deep: !0 }) && this._setSpeed(t.speed), t.target !== void 0 && !O(i.target, this.state.target, { deep: !0 })) {
const r = {
target: t.target,
showAnime: { duration: 500 },
hideAnime: { duration: 500 }
};
this._switchPipelines(r);
}
}
/** 启用插件
* @param `options` `<Option> | <undefined>`
* @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。
*/
enable(t = {}) {
var i;
if (this.state.enabled)
return;
const e = (i = t.userAction) != null ? i : !0;
this.updateState({ enabled: !0 }, e), this._enable({ userAction: e });
}
/** 禁用插件
* @param `options` `<Option> | <undefined>`
* @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。
*/
disable(t = {}) {
var i;
if (this.state.enabled === !1)
return;
const e = (i = t.userAction) != null ? i : !0;
this.updateState({ enabled: !1, isFlowing: !1 }, e), this._disable({ userAction: e });
}
/** 展示管道模型,注意如果通过 `switchPipelines` 更改过 `visibleIDs`,则只会展示这一部分模型。
* @param `options` `<Partial<ShowHideOptions>> | <undefined>`
* @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。
* @param `options.anime` `<AnimeOptions> | <undefined>` 动画配置。
* @param `options.anime.duration` `<number> | <undefined>` 动画时间,默认是 500ms。
*/
show() {
return c(this, arguments, function* (t = {}) {
if (this.state.visible)
return;
const e = u({
userAction: !0,
anime: { duration: 500 }
}, t);
this.updateState({ visible: !0 }, e.userAction), yield this._show(e);
});
}
/** 插件内容整体隐藏
* @param `options` `<Partial<ShowHideOptions>> | <undefined>`
* @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。
* @param `options.anime` `<AnimeOptions> | <undefined>` 动画配置。
* @param `options.anime.duration` `<number> | <undefined>` 动画时间,默认是 500ms。
*/
hide() {
return c(this, arguments, function* (t = {}) {
if (this.state.visible === !1)
return;
const e = u({
userAction: !0,
anime: { duration: 500 }
}, t);
this.updateState({ visible: !1 }, e.userAction), yield this._hide(e);
});
}
/** 切换管路
* @param `options` `Partial<ShowPipelinesOptions> | <undefined>`
* @param `options.target` `<{ startLibraryID: number; endLibraryID: number }[]> | <undefined>`
* 目标管路,存在时,展示目标管路包含的管道,同时隐藏其他管道。不存在则展示所有管道。
* startLibraryID 和 endLibraryID 是起始和结束的设备 ID。
* @param `options.showAnime` `<AnimeOptions> | <undefined>` 展示的动画配置。
* @param `options.hideAnime` `<AnimeOptions> | <undefined>` 隐藏的动画配置。
* @param `options.anime` `<AnimeOptions> | <undefined>` 兜底的动画配置。
* @param `options.userAction` `<boolean> | <undefined>` 是否是否是用户操作。
* */
switchPipelines(t) {
return c(this, null, function* () {
var h, p, b, l, f, w;
if (!this.data)
return;
const e = (h = t == null ? void 0 : t.target) != null ? h : null, i = (p = t == null ? void 0 : t.userAction) != null ? p : !0;
this.updateState({ target: e }, i);
const s = { duration: 500 }, r = (l = (b = t == null ? void 0 : t.hideAnime) != null ? b : t == null ? void 0 : t.anime) != null ? l : s, n = (w = (f = t == null ? void 0 : t.showAnime) != null ? f : t == null ? void 0 : t.anime) != null ? w : s, a = {
target: e,
showAnime: n,
hideAnime: r
};
this._switchPipelines(a);
});
}
/** 开始流动 */
flow(t = {}) {
var i;
if (this.state.isFlowing)
return;
const e = (i = t.userAction) != null ? i : !0;
this.updateState({ isFlowing: !0 }, e), this._flow();
}
/** 停止流动 */
stopFlow(t = {}) {
var i;
if (this.state.isFlowing === !1)
return;
const e = (i = t.userAction) != null ? i : !0;
this.updateState({ isFlowing: !1 }, e), this._stopFlow();
}
/** 更改水管流速
* @param `options` `<SetSpeedOptions> | <undefined>`
* @param `options.speed` `<Speed> | <undefined>` 参考 `state.speed` 的描述。
* @param `options.userAction` `<boolean> | <undefined>` 是否是否是用户操作。
*/
setSpeed(t) {
var s, r;
const e = (s = t == null ? void 0 : t.speed) != null ? s : g, i = (r = t.userAction) != null ? r : !0;
this.updateState({ speed: e }, i), this._setSpeed(e);
}
formatData(t, e) {
return c(this, null, function* () {
return y(t, e);
});
}
_enable(t) {
this.hooks.emit("enable", { userAction: t.userAction }), this.five.scene.add(this.group), this.five.needsRender = !0, this.five.on("wantsTapGesture", this.onWantsFiveTapGesture);
}
_disable(t) {
this.hooks.emit("disable", { userAction: t.userAction }), this.disposeAnime(), this.five.scene.remove(this.group), this.five.needsRender = !0, this.five.off("wantsTapGesture", this.onWantsFiveTapGesture);
}
_show(t) {
return c(this, null, function* () {
var s;
this.hooks.emit("show", { userAction: t.userAction });
const e = (s = t == null ? void 0 : t.anime) != null ? s : { duration: 500 }, i = this.findPipeObjectWithTarget(this.state.target);
yield Promise.all(i.map((r) => r == null ? void 0 : r.show(e))), this.five.needsRender = !0;
});
}
_hide(t) {
return c(this, null, function* () {
var i;
this.hooks.emit("hide", { userAction: t.userAction });
const e = (i = t == null ? void 0 : t.anime) != null ? i : { duration: 500 };
yield Promise.all(this.pipeObjects.map((s) => s.hide(e))), this.five.needsRender = !0;
});
}
_switchPipelines(t) {
return c(this, null, function* () {
if (!this.data)
return;
const e = this.findPipeObjectWithTarget(t.target), i = t.hideAnime;
yield Promise.all(this.pipeObjects.map((r) => r.hide(i)));
const s = t.showAnime;
yield Promise.all(e.map((r) => r.show(s)));
});
}
_flow() {
this.pipeObjects.forEach((t) => t.flow());
}
_stopFlow() {
this.pipeObjects.forEach((t) => t.stopFlow());
}
_setSpeed(t) {
this.pipeObjects.forEach((e) => e.setSpeed(t));
}
updateState(t, e) {
const i = this.state;
this.state = u(u({}, this.state), t), this.hooks.emit("stateChange", { state: this.state, prevState: i, userAction: e });
}
/** 加载管道贴图,如果再加载中,复用之前的加载 Promise */
loadPipeTexture(t) {
return c(this, null, function* () {
const e = this.texturePromiseCache.get(t);
if (e)
return e;
const i = x(t);
return this.texturePromiseCache.set(t, i), i;
});
}
/** 销毁所有动画 */
disposeAnime() {
this.pipeObjects.forEach((t) => t.disposeAnime()), this.five.needsRender = !0;
}
/** 移除所有管道模型 */
removeAllPipes() {
this.disposeAnime(), this.group.remove(...this.pipeObjects), this.pipeObjects.forEach((t) => t.dispose()), this.pipeObjects = [], this.five.needsRender = !0;
}
/** 根据 ID 查找管道模型 */
findPipeObjectWithID(t) {
return this.pipeObjects.find(({ customID: e }) => e === t);
}
/** 根据 target 查找管道模型 */
findPipeObjectWithTarget(t) {
return t ? C({ data: this.data, target: t }).map(({ id: i }) => this.findPipeObjectWithID(i)).filter(T) : this.pipeObjects;
}
}
export {
ae as Controller
};