diff --git a/apps/web-visualization-demos/src/page/cesiumThree/CesiumThreeService.ts b/apps/web-visualization-demos/src/page/cesiumThree/CesiumThreeService.ts index 6442b15..fd35a5c 100644 --- a/apps/web-visualization-demos/src/page/cesiumThree/CesiumThreeService.ts +++ b/apps/web-visualization-demos/src/page/cesiumThree/CesiumThreeService.ts @@ -4,7 +4,7 @@ import { 结合1 } from "./结合" class CesiumThreeService { moduleEnter() { - threeHelper.add(new DevPlugin({ axesSize: 1e7 })) + threeHelper.addPlugin(new DevPlugin({ axesSize: 1e7 })) this.init() } diff --git "a/apps/web-visualization-demos/src/page/cesiumThree/\347\273\223\345\220\210.ts" "b/apps/web-visualization-demos/src/page/cesiumThree/\347\273\223\345\220\210.ts" index d25bd15..a0001d9 100644 --- "a/apps/web-visualization-demos/src/page/cesiumThree/\347\273\223\345\220\210.ts" +++ "b/apps/web-visualization-demos/src/page/cesiumThree/\347\273\223\345\220\210.ts" @@ -44,7 +44,7 @@ const cartToVec = function (cart: Cesium.Cartesian3) { export const 结合1 = async () => { const viewer = ViewerHelper.getViewer()! - threeHelper.add(new SyncCesiumPlugin(viewer)) + threeHelper.addPlugin(new SyncCesiumPlugin(viewer)) const scene = threeHelper.getWidget("scene")! const entity = viewer.entities.add({ diff --git a/apps/web-visualization-demos/src/page/threePage/EffectComposer.ts b/apps/web-visualization-demos/src/page/threePage/EffectComposer.ts index 5ab4aa1..a565e55 100644 --- a/apps/web-visualization-demos/src/page/threePage/EffectComposer.ts +++ b/apps/web-visualization-demos/src/page/threePage/EffectComposer.ts @@ -7,7 +7,7 @@ import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js" export const 发光 = () => { const scene = threeHelper.getWidget("scene")! const renderer = threeHelper.getWidget("renderer")! - const camera = threeHelper.getWidget("p_camera")! + const camera = threeHelper.getWidget("camera")! const geometry = new THREE.SphereGeometry(1, 32, 32) const material = new THREE.MeshBasicMaterial({ color: "teal" }) @@ -37,7 +37,9 @@ export const 发光 = () => { outlinePass.selectedObjects = [sphere, cube, torusKnot] threeHelper.animationCollection.delete(Symbol.for("update_renderer")) - threeHelper.animationCollection.set("update_renderPass", (_, delta) => { - composer.render(delta) + threeHelper.animationCollection.set("update_renderPass", { + fn: ({ delta }) => { + composer.render(delta) + }, }) } diff --git a/apps/web-visualization-demos/src/page/threePage/ThreePageService.ts b/apps/web-visualization-demos/src/page/threePage/ThreePageService.ts index ee0d661..eaf4c21 100644 --- a/apps/web-visualization-demos/src/page/threePage/ThreePageService.ts +++ b/apps/web-visualization-demos/src/page/threePage/ThreePageService.ts @@ -6,19 +6,8 @@ const flag = { current: false } class ThreePageService { moduleEnter() { - threeHelper.add(new DevPlugin()) + threeHelper.addPlugin(new DevPlugin()) this.init() - - // const plugin = new OrbitControlsPlugin() - // setInterval(() => { - // if (flag.current) { - // threeHelper.remove(plugin) - // flag.current = false - // } else { - // threeHelper.add(plugin) - // flag.current = true - // } - // }, 5000) } moduleExit() {} diff --git a/packages/tsconfig/base.json b/packages/tsconfig/base.json index db81a71..b18a628 100644 --- a/packages/tsconfig/base.json +++ b/packages/tsconfig/base.json @@ -21,7 +21,8 @@ "allowSyntheticDefaultImports": true, "suppressImplicitAnyIndexErrors": true, "ignoreDeprecations": "5.0", - "jsx": "react-jsx" + "jsx": "react-jsx", + "suppressExcessPropertyErrors": true }, "exclude": ["node_modules"] } diff --git a/packages/zxtool-cesium-utils/src/index.ts b/packages/zxtool-cesium-utils/src/index.ts index 51900f2..9d29d92 100644 --- a/packages/zxtool-cesium-utils/src/index.ts +++ b/packages/zxtool-cesium-utils/src/index.ts @@ -1,4 +1,5 @@ export * from "./materialProperty" export type * from "./type" export * from "./util" +export * from "./v2" export * from "./widget" diff --git a/packages/zxtool-cesium-utils/src/v2/CesiumHelper.ts b/packages/zxtool-cesium-utils/src/v2/CesiumHelper.ts new file mode 100644 index 0000000..271f07e --- /dev/null +++ b/packages/zxtool-cesium-utils/src/v2/CesiumHelper.ts @@ -0,0 +1,41 @@ +import { EmitterHelper, IObj } from "@zxtool/utils" +import { CesiumHelperPlugin, CesiumHelperPluginProps } from "./plugins" +import { ViewerPlugin } from "./plugins/ViewerPlugin" + +export class CesiumHelper { + private isInit = false + private readonly emitter = new EmitterHelper({ maxCount: { history: 1 } }) + private readonly widgetCollection: Map = new Map() + + readonly pluginCollection: Map = new Map() + + getWidget(key: PropertyKey): unknown { + return this.widgetCollection.get(key) + } + getWidgetAsync(key: PropertyKey) { + return this.emitter.onceAsync(key, true).promise + } + + addPlugin(plugin: CesiumHelperPlugin, options?: AO) { + const props: CesiumHelperPluginProps = { + emitter: this.emitter, + widgetCollection: this.widgetCollection, + cesiumHelper: this, + } + plugin.add(props, options) + return this + } + removePlugin(plugin: CesiumHelperPlugin, options?: RO) { + plugin.remove(options) + return this + } + + init(container: string | Element) { + if (this.isInit) return + + // todo + this.addPlugin(new ViewerPlugin(), { container }) + + this.isInit = true + } +} diff --git a/packages/zxtool-cesium-utils/src/v2/index.ts b/packages/zxtool-cesium-utils/src/v2/index.ts new file mode 100644 index 0000000..8a30fb0 --- /dev/null +++ b/packages/zxtool-cesium-utils/src/v2/index.ts @@ -0,0 +1,2 @@ +export * from "./CesiumHelper" +export * from "./plugins" diff --git a/packages/zxtool-cesium-utils/src/v2/plugins/ViewerPlugin.ts b/packages/zxtool-cesium-utils/src/v2/plugins/ViewerPlugin.ts new file mode 100644 index 0000000..53b7c46 --- /dev/null +++ b/packages/zxtool-cesium-utils/src/v2/plugins/ViewerPlugin.ts @@ -0,0 +1,67 @@ +import * as Cesium from "cesium" +import { CesiumHelperPlugin, CesiumHelperPluginProps } from "." +import { CesiumUtil, ViewerUtilSync } from "../../util" +import { genZCUInfo } from "../../util/util" + +export type ViewerPluginAO = Cesium.Viewer.ConstructorOptions & { + container: string | Element + hideWidget?: boolean + fxaa?: boolean + enableIframe?: boolean +} + +const genInfo = genZCUInfo("ViewerPlugin") + +export class ViewerPlugin implements CesiumHelperPlugin { + private key = Symbol.for("viewer") + private addProps: CesiumHelperPluginProps | null = null + + private _viewer?: Cesium.Viewer + get viewer() { + return this._viewer + } + + add(props: CesiumHelperPluginProps, options: ViewerPluginAO): ViewerPlugin { + this.addProps = props + const { cesiumHelper, widgetCollection, emitter } = props + const { pluginCollection } = cesiumHelper + + const plugin = pluginCollection.get(this.key) as ViewerPlugin + if (plugin) { + console.error(genInfo("已经存在一个 ViewerPlugin, 不能重复添加")) + return plugin + } + + const { container, hideWidget = true, fxaa = true, enableIframe, ...rest } = options + if (!container) throw new Error("请传入 container") + + const viewer = new Cesium.Viewer(container, { ...(hideWidget ? ViewerUtilSync.getHideWidgetOption() : null), ...rest }) + // @ts-ignore + if (hideWidget) viewer.cesiumWidget.creditContainer.style.display = "none" + fxaa && ViewerUtilSync.fxaa(viewer) + enableIframe && CesiumUtil.enableIframe() + viewer.scene.globe.depthTestAgainstTerrain = true + + this._viewer = viewer + widgetCollection.set("viewer", viewer) + emitter.emit("viewer", viewer) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { cesiumHelper, widgetCollection, emitter } = this.addProps + const { pluginCollection } = cesiumHelper + + widgetCollection.delete("viewer") + emitter.clearHistory("viewer") + + this.viewer?.destroy() + this._viewer = undefined + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-cesium-utils/src/v2/plugins/index.ts b/packages/zxtool-cesium-utils/src/v2/plugins/index.ts new file mode 100644 index 0000000..50d55ac --- /dev/null +++ b/packages/zxtool-cesium-utils/src/v2/plugins/index.ts @@ -0,0 +1,14 @@ +import type { EmitterHelper, IObj } from "@zxtool/utils" +import type { CesiumHelper } from "../CesiumHelper" + +export interface CesiumHelperPluginProps { + emitter: EmitterHelper + widgetCollection: Map + cesiumHelper: CesiumHelper +} +export interface CesiumHelperPlugin { + add(props: CesiumHelperPluginProps, options?: AO): CesiumHelperPlugin + remove(options?: RO): void +} + +export * from "./ViewerPlugin" diff --git a/packages/zxtool-three-utils/src/geometry/WallGeometry.ts b/packages/zxtool-three-utils/src/geometry/WallGeometry.ts new file mode 100644 index 0000000..5b7c07a --- /dev/null +++ b/packages/zxtool-three-utils/src/geometry/WallGeometry.ts @@ -0,0 +1,65 @@ +import { Num2 } from "@zxtool/utils" +import * as THREE from "three" + +export interface WallGeometryProps { + points: Num2[] + height?: number + heights?: Num2[] + uvType?: "PER" | "ALL" + face?: "XOY" | "XOZ" +} + +export class WallGeometry extends THREE.BufferGeometry { + type = "WallGeometry" + parameters: WallGeometryProps + + constructor(props: WallGeometryProps) { + const { points, height = 1, heights, uvType = "ALL", face = "XOZ" } = props + + super() + this.parameters = { points, height, uvType } + + const vertices: number[] = [] + const uvs: number[] = [] + const per = 1 / (points.length - 1) + + for (let i = 0; i < points.length - 1; i++) { + const cur = points[i] + const next = points[i + 1] + let curHeight = [0, height] + let nextHeight = [0, height] + if (heights?.[i]) curHeight = [heights[i][0] ?? 0, heights[i][1] ?? height] + if (heights?.[i + 1]) nextHeight = [heights[i + 1][0] ?? 0, heights[i + 1][1] ?? height] + + if (face === "XOY") { + vertices.push(cur[0], cur[1], curHeight[0], next[0], next[1], nextHeight[0], next[0], next[1], nextHeight[1]) + vertices.push(cur[0], cur[1], curHeight[0], next[0], next[1], nextHeight[1], cur[0], cur[1], curHeight[1]) + } else { + vertices.push(cur[0], curHeight[0], cur[1], next[0], nextHeight[0], next[1], next[0], nextHeight[1], next[1]) + vertices.push(cur[0], curHeight[0], cur[1], next[0], nextHeight[1], next[1], cur[0], curHeight[1], cur[1]) + } + + if (uvType === "PER") { + uvs.push(0, 0, 1, 0, 1, 1) + uvs.push(0, 0, 1, 1, 0, 1) + } else { + uvs.push(i * per, 0, (i + 1) * per, 0, (i + 1) * per, 1) + uvs.push(i * per, 0, (i + 1) * per, 1, i * per, 1) + } + } + + this.setAttribute("position", new THREE.BufferAttribute(new Float32Array(vertices), 3)) + this.setAttribute("uv", new THREE.BufferAttribute(new Float32Array(uvs), 2)) + this.computeVertexNormals() + } + + copy(source: any) { + super.copy(source) + this.parameters = Object.assign({}, source.parameters) + return this + } + + static fromJSON(data: WallGeometryProps) { + return new WallGeometry(data) + } +} diff --git a/packages/zxtool-three-utils/src/geometry/index.ts b/packages/zxtool-three-utils/src/geometry/index.ts new file mode 100644 index 0000000..46563e6 --- /dev/null +++ b/packages/zxtool-three-utils/src/geometry/index.ts @@ -0,0 +1 @@ +export * from "./WallGeometry" diff --git a/packages/zxtool-three-utils/src/widget/CustomGridHelper.ts b/packages/zxtool-three-utils/src/helper/CustomGridHelper.ts similarity index 100% rename from packages/zxtool-three-utils/src/widget/CustomGridHelper.ts rename to packages/zxtool-three-utils/src/helper/CustomGridHelper.ts diff --git a/packages/zxtool-three-utils/src/helper/index.ts b/packages/zxtool-three-utils/src/helper/index.ts new file mode 100644 index 0000000..5298155 --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/index.ts @@ -0,0 +1,3 @@ +export * from "./CustomGridHelper" +export * from "./threeHelper/ThreeHelper" +export * from "./threeHelper/plugins" diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/ThreeHelper.ts b/packages/zxtool-three-utils/src/helper/threeHelper/ThreeHelper.ts new file mode 100644 index 0000000..3799536 --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/ThreeHelper.ts @@ -0,0 +1,67 @@ +import { EmitterHelper, IObj } from "@zxtool/utils" +import { + AnimationWithState, + FunctionWithState, + StateCbCollection, + ThreeHelperPlugin, + ThreeHelperPluginProps, +} from "./plugins" +import { AnimationPlugin } from "./plugins/AnimationPlugin" +import { PCameraPlugin } from "./plugins/PCameraPlugin" +import { RendererPlugin } from "./plugins/RendererPlugin" +import { ResizePlugin } from "./plugins/ResizePlugin" +import { ScenePlugin } from "./plugins/ScenePlugin" + +export interface ThreeHelper { + getWidget(type: "scene"): THREE.Scene | undefined + getWidget(type: "renderer"): THREE.WebGLRenderer | undefined + getWidget(type: "camera"): THREE.Camera | undefined + + getWidgetAsync(type: "scene"): Promise + getWidgetAsync(type: "renderer"): Promise + getWidgetAsync(type: "camera"): Promise +} + +export class ThreeHelper { + private isInit = false + private readonly emitter = new EmitterHelper({ maxCount: { history: 1 } }) + private readonly widgetCollection: Map = new Map() + + readonly time = { value: 0 } + readonly animationCollection: StateCbCollection = new Map() + readonly resizeCollection: StateCbCollection = new Map() + readonly pluginCollection: Map = new Map() + + getWidget(key: PropertyKey): unknown { + return this.widgetCollection.get(key) + } + getWidgetAsync(key: PropertyKey) { + return this.emitter.onceAsync(key, true).promise + } + + addPlugin(plugin: ThreeHelperPlugin, options?: AO) { + const props: ThreeHelperPluginProps = { + emitter: this.emitter, + widgetCollection: this.widgetCollection, + threeHelper: this, + } + plugin.add(props, options) + return this + } + removePlugin(plugin: ThreeHelperPlugin, options?: RO) { + plugin.remove(options) + return this + } + + init(canvas: HTMLCanvasElement) { + if (this.isInit) return + + this.addPlugin(new RendererPlugin(), { canvas }) + .addPlugin(new ScenePlugin()) + .addPlugin(new PCameraPlugin()) + .addPlugin(new AnimationPlugin()) + .addPlugin(new ResizePlugin()) + + this.isInit = true + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/AnimationPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/AnimationPlugin.ts new file mode 100644 index 0000000..998cfcd --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/AnimationPlugin.ts @@ -0,0 +1,57 @@ +import { throttle } from "lodash" +import * as THREE from "three" +import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +const genInfo = genZTUInfo("AnimationPlugin") + +export class AnimationPlugin implements ThreeHelperPlugin { + private key = Symbol.for("animation") + private animationId = { value: 0 } + private addProps: ThreeHelperPluginProps | null = null + + add(props: ThreeHelperPluginProps): AnimationPlugin { + this.addProps = props + const { threeHelper } = props + const { time, animationCollection, pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as AnimationPlugin + if (plugin) { + console.error(genInfo("已经存在一个 AnimationPlugin, 不能重复添加")) + return plugin + } + + const clock = new THREE.Clock() + + const animation = (t = 0) => { + time.value = t + const delta = clock.getDelta() + animationCollection.forEach<{ _throttled?: boolean }>(item => { + const { fn, state = {} } = item + if (state.enable === false) return + if (state.throttleTime && !state._throttled) { + fn({ time: t, delta, state }) + item.fn = throttle(item.fn, state.throttleTime) + state._throttled = true + } else fn({ time: t, delta, state }) + }) + this.animationId.value = requestAnimationFrame(animation) + } + animation() + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper } = this.addProps + const { time, pluginCollection } = threeHelper + + cancelAnimationFrame(this.animationId.value) + time.value = 0 + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/CSS2DRendererPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/CSS2DRendererPlugin.ts new file mode 100644 index 0000000..99cbd52 --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/CSS2DRendererPlugin.ts @@ -0,0 +1,68 @@ +import { CSS2DParameters, CSS2DRenderer } from "three/examples/jsm/Addons.js" +import { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +const genInfo = genZTUInfo("CSS2DRendererPlugin") + +export class CSS2DRendererPlugin implements ThreeHelperPlugin { + private key = Symbol.for("css2d_renderer") + private ac_key = Symbol.for("update_css2d_renderer") + private rc_key = Symbol.for("resize_css2d_renderer") + private addProps: ThreeHelperPluginProps | null = null + + private _css2dRenderer?: CSS2DRenderer + get css2dRenderer() { + return this._css2dRenderer + } + + add(props: ThreeHelperPluginProps, options?: CSS2DParameters): CSS2DRendererPlugin { + this.addProps = props + const { threeHelper, widgetCollection, emitter } = props + const { animationCollection, pluginCollection, resizeCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as CSS2DRendererPlugin + if (plugin) { + console.error(genInfo("已经存在一个 CSS2DRendererPlugin, 不能重复添加")) + return plugin + } + + const css2dRenderer = new CSS2DRenderer(options) + css2dRenderer!.setSize(window.innerWidth, window.innerHeight) + this._css2dRenderer = css2dRenderer + + widgetCollection.set("css2d_renderer", this.css2dRenderer) + emitter.emit("css2d_renderer", this.css2dRenderer) + + animationCollection.set(this.ac_key, { + fn() { + const camera = widgetCollection.get("camera") + const scene = widgetCollection.get("scene") + if (camera && scene) css2dRenderer?.render(scene, camera) + }, + }) + resizeCollection.set(this.rc_key, { + fn() { + css2dRenderer?.setSize(window.innerWidth, window.innerHeight) + }, + }) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper, widgetCollection, emitter } = this.addProps + const { animationCollection, resizeCollection, pluginCollection } = threeHelper + + widgetCollection.delete("css2d_renderer") + emitter.clearHistory("css2d_renderer") + + this._css2dRenderer = undefined + animationCollection.delete(this.ac_key) + resizeCollection.delete(this.rc_key) + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/CSS3DRendererPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/CSS3DRendererPlugin.ts new file mode 100644 index 0000000..f4b81be --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/CSS3DRendererPlugin.ts @@ -0,0 +1,68 @@ +import { CSS3DParameters, CSS3DRenderer } from "three/examples/jsm/Addons.js" +import { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +const genInfo = genZTUInfo("CSS3DRendererPlugin") + +export class CSS3DRendererPlugin implements ThreeHelperPlugin { + private key = Symbol.for("css3d_renderer") + private ac_key = Symbol.for("update_css3d_renderer") + private rc_key = Symbol.for("resize_css3d_renderer") + private addProps: ThreeHelperPluginProps | null = null + + private _css3dRenderer?: CSS3DRenderer + get css3dRenderer() { + return this._css3dRenderer + } + + add(props: ThreeHelperPluginProps, options?: CSS3DParameters): CSS3DRendererPlugin { + this.addProps = props + const { threeHelper, widgetCollection, emitter } = props + const { animationCollection, pluginCollection, resizeCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as CSS3DRendererPlugin + if (plugin) { + console.error(genInfo("已经存在一个 CSS3DRendererPlugin, 不能重复添加")) + return plugin + } + + const css3dRenderer = new CSS3DRenderer(options) + css3dRenderer!.setSize(window.innerWidth, window.innerHeight) + this._css3dRenderer = css3dRenderer + + widgetCollection.set("css3d_renderer", this.css3dRenderer) + emitter.emit("css3d_renderer", this.css3dRenderer) + + animationCollection.set(this.ac_key, { + fn() { + const camera = widgetCollection.get("camera") + const scene = widgetCollection.get("scene") + if (camera && scene) css3dRenderer?.render(scene, camera) + }, + }) + resizeCollection.set(this.rc_key, { + fn() { + css3dRenderer?.setSize(window.innerWidth, window.innerHeight) + }, + }) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper, widgetCollection, emitter } = this.addProps + const { animationCollection, resizeCollection, pluginCollection } = threeHelper + + widgetCollection.delete("css3d_renderer") + emitter.clearHistory("css3d_renderer") + + this._css3dRenderer = undefined + animationCollection.delete(this.ac_key) + resizeCollection.delete(this.rc_key) + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/DevPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/DevPlugin.ts new file mode 100644 index 0000000..a0f86a8 --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/DevPlugin.ts @@ -0,0 +1,81 @@ +import * as THREE from "three" +import Stats from "three/examples/jsm/libs/stats.module.js" +import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +export interface DevPluginAO { + enableStats?: boolean + enableAxes?: boolean + axesSize?: number +} + +const genInfo = genZTUInfo("DevPlugin") + +export class DevPlugin implements ThreeHelperPlugin { + private key = Symbol.for("dev") + private ac_key = Symbol.for("update_stats") + private addProps: ThreeHelperPluginProps | null = null + + private _stats?: Stats + get stats() { + return this._stats + } + private _axesHelper?: THREE.AxesHelper + get axesHelper() { + return this._axesHelper + } + + add(props: ThreeHelperPluginProps, options: DevPluginAO = {}): DevPlugin { + this.addProps = props + const { threeHelper } = props + const { animationCollection, pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as DevPlugin + if (plugin) { + console.error(genInfo("已经存在一个 DevPlugin, 不能重复添加")) + return plugin + } + + const scene = threeHelper.getWidget("scene") + if (!scene) { + console.error(genInfo("不存在可用的 scene")) + return this + } + + const { enableStats = true, enableAxes = true, axesSize = 50 } = options + + if (enableAxes) { + this._axesHelper = new THREE.AxesHelper(axesSize) + scene.add(this._axesHelper) + } + if (enableStats) { + this._stats = new Stats() + document.body.appendChild(this._stats.dom) + animationCollection.set(this.ac_key, { + fn: () => this.stats?.update(), + }) + } + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper } = this.addProps + + const scene = threeHelper.getWidget("scene") + + if (this.stats) { + this.stats.dom.remove() + this._stats = undefined + } + if (this.axesHelper) { + scene?.remove(this.axesHelper) + this._axesHelper = undefined + } + + threeHelper.pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/EffectComposerPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/EffectComposerPlugin.ts new file mode 100644 index 0000000..39e767f --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/EffectComposerPlugin.ts @@ -0,0 +1,71 @@ +import { EffectComposer, RenderPass } from "three/examples/jsm/Addons.js" +import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +const genInfo = genZTUInfo("EffectComposerPlugin") + +export class EffectComposerPlugin implements ThreeHelperPlugin { + private key = Symbol.for("effect_composer") + private ac_key = Symbol.for("update_effect_composer") + private addProps: ThreeHelperPluginProps | null = null + + private _effectComposer?: EffectComposer + get effectComposer() { + return this._effectComposer + } + + add(props: ThreeHelperPluginProps): EffectComposerPlugin { + this.addProps = props + const { threeHelper } = props + const { animationCollection, pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as EffectComposerPlugin + if (plugin) { + console.error(genInfo("已经存在一个 EffectComposerPlugin, 不能重复添加")) + return plugin + } + + const scene = threeHelper.getWidget("scene")! + const renderer = threeHelper.getWidget("renderer")! + const camera = threeHelper.getWidget("camera")! + + const effectComposer = new EffectComposer(renderer) + effectComposer.setSize(window.innerWidth, window.innerHeight) + effectComposer.setPixelRatio(window.devicePixelRatio) + effectComposer.addPass(new RenderPass(scene, camera)) + this._effectComposer = effectComposer + + const updateRenderer = animationCollection.get(Symbol.for("update_renderer")) + if (updateRenderer) { + if (!updateRenderer.state) updateRenderer.state = {} + updateRenderer.state.enable = false + } + + animationCollection.set(this.ac_key, { + fn() { + effectComposer.render() + }, + }) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper } = this.addProps + const { animationCollection, pluginCollection } = threeHelper + + this._effectComposer?.dispose() + this._effectComposer = undefined + animationCollection.delete(this.ac_key) + const updateRenderer = animationCollection.get(Symbol.for("update_renderer")) + if (updateRenderer) { + if (!updateRenderer.state) updateRenderer.state = {} + updateRenderer.state.enable = true + } + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/MouseEventPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/MouseEventPlugin.ts new file mode 100644 index 0000000..ecfdcaa --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/MouseEventPlugin.ts @@ -0,0 +1,131 @@ +import { LikeDom } from "@zxtool/utils" +import * as THREE from "three" +import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +type RawCb = (intersection: THREE.Intersection | null, e: MouseEvent) => void +export interface MouseEventPluginAO { + dom?: LikeDom +} + +const genInfo = genZTUInfo("MouseEventPlugin") + +export class MouseEventPlugin implements ThreeHelperPlugin { + private key = Symbol.for("mouse_event") + private raycaster = new THREE.Raycaster() + private pointerV2 = new THREE.Vector2() + private dom: LikeDom = document + private addProps: ThreeHelperPluginProps | null = null + private curObj: THREE.Object3D | null = null + private cbs = { + down: (ev: unknown) => { + const e = ev as PointerEvent + if (e.button !== 0) return + this.cbs.state.startTime = Date.now() + this.cbs.state.startX = e.clientX + this.cbs.state.startY = e.clientY + }, + up: (ev: unknown) => { + const e = ev as PointerEvent + const { button, clientX, clientY } = e + if (button !== 0) return + const { startTime, startX, startY } = this.cbs.state + const deltaTime = Date.now() - startTime + const deltaX = clientX - startX + const deltaY = clientY - startY + if (deltaTime > 400 || deltaX * deltaX + deltaY * deltaY > 20) return + + const [intersection] = this.getIntersection(clientX, clientY) + this.onClick?.(intersection, e) + + const fn = intersection?.object?.__customField?.onClick + if (typeof fn === "function") { + this.clearClick?.() + fn(intersection!.object.__customField, intersection!) + } + }, + move: (ev: unknown) => { + const e = ev as PointerEvent + const [intersection] = this.getIntersection(e.clientX, e.clientY) + this.onMove?.(intersection, e) + if (this.curObj === intersection?.object ?? null) return + + const leave = this.curObj?.__customField?.onLeave + if (typeof leave === "function") leave(this.curObj!.__customField, intersection!) + const enter = intersection?.object?.__customField?.onEnter + if (typeof enter === "function") enter(intersection!.object.__customField, intersection!) + + this.curObj = intersection?.object ?? null + }, + state: { startTime: 0, startX: 0, startY: 0 }, + } + + include?: THREE.Object3D[] = undefined + exclude?: THREE.Object3D[] = undefined + + onClick?: RawCb + onMove?: RawCb + clearClick?: () => void + + private getIntersection = (screenX: number, screenY: number) => { + if (!this.addProps) throw new Error(genInfo("未添加插件")) + const { threeHelper } = this.addProps + + const scene = threeHelper.getWidget("scene") + const camera = threeHelper.getWidget("camera") + if (!scene || !camera) return [null, []] as const + + this.pointerV2.x = (screenX / window.innerWidth - 0.5) * 2 + this.pointerV2.y = (screenY / window.innerHeight - 0.5) * -2 + this.raycaster.setFromCamera(this.pointerV2, camera) + + const include = this.include ?? scene.children + const intersections = this.raycaster.intersectObjects(include) + + let intersection: THREE.Intersection | null = intersections[0] ?? null + if (this.exclude?.length) intersection = this.exclude.includes(intersection.object) ? null : intersection + return [intersection, intersections] as const + } + + add(props: ThreeHelperPluginProps, options: MouseEventPluginAO = {}): MouseEventPlugin { + this.addProps = props + const { threeHelper } = props + const { pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as MouseEventPlugin + if (plugin) { + console.error(genInfo("已经存在一个 MouseEventPlugin, 不能重复添加")) + return plugin + } + + if (options.dom) this.dom = options.dom + + this.dom.addEventListener("pointerdown", this.cbs.down) + this.dom.addEventListener("pointermove", this.cbs.move) + this.dom.addEventListener("pointerup", this.cbs.up) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper } = this.addProps + const { pluginCollection } = threeHelper + + this.dom.removeEventListener("pointerdown", this.cbs.down) + this.dom.removeEventListener("pointermove", this.cbs.move) + this.dom.removeEventListener("pointerup", this.cbs.up) + this.cbs.state = { startTime: 0, startX: 0, startY: 0 } + this.curObj = null + this.dom = document + this.include = undefined + this.exclude = undefined + this.onClick = undefined + this.onMove = undefined + this.clearClick = undefined + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/OCameraPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/OCameraPlugin.ts new file mode 100644 index 0000000..0502dbf --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/OCameraPlugin.ts @@ -0,0 +1,98 @@ +import * as THREE from "three" +import { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +export interface OCameraPluginAO { + width?: number + height?: number + near?: number + far?: number +} + +const genInfo = genZTUInfo("OCameraPlugin") + +export class OCameraPlugin implements ThreeHelperPlugin { + private key = Symbol.for("camera") + private rc_key = Symbol.for("resize_camera") + private addProps: ThreeHelperPluginProps | null = null + private size!: { width?: number; height?: number } + + private _camera?: THREE.OrthographicCamera + get camera() { + return this._camera + } + + private calcConfig(width = 10, height?: number) { + const aspect = window.innerWidth / window.innerHeight + if (height) { + const halfHeight = height * 0.5 + return { left: -aspect * halfHeight, right: aspect * halfHeight, top: halfHeight, bottom: -halfHeight } + } + const halfWidth = width * 0.5 + return { left: -halfWidth, right: halfWidth, top: halfWidth / aspect, bottom: -halfWidth / aspect } + } + + updateSize(width?: number, height?: number) { + if (!this.camera) throw new Error(genInfo("插件未被添加")) + this.size = { width, height } + const { left, right, top, bottom } = this.calcConfig(width, height) + this.camera.left = left + this.camera.right = right + this.camera.top = top + this.camera.bottom = bottom + } + + add(props: ThreeHelperPluginProps, options: OCameraPluginAO = {}): OCameraPlugin { + this.addProps = props + const { threeHelper, widgetCollection, emitter } = props + const { resizeCollection, pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as OCameraPlugin + if (plugin) { + console.error(genInfo("已经存在一个 CameraPlugin, 不能重复添加")) + return plugin + } + + const { width, height, near = 0.1, far = 1e4 } = options + this.size = { width, height } + const { left, right, top, bottom } = this.calcConfig(width, height) + + const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far) + camera.position.set(0, 0, 10) + this._camera = camera + + widgetCollection.set("camera", camera) + emitter.emit("camera", camera) + + resizeCollection.set(this.rc_key, { + fn: () => { + const { width, height } = this.size + const { left, right, top, bottom } = this.calcConfig(width, height) + camera.left = left + camera.right = right + camera.top = top + camera.bottom = bottom + camera.updateProjectionMatrix() + }, + }) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper, widgetCollection, emitter } = this.addProps + const { resizeCollection, pluginCollection } = threeHelper + + widgetCollection.delete("camera") + emitter.clearHistory("camera") + + this._camera?.remove() + this._camera = undefined + resizeCollection.delete(this.rc_key) + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/OControlsPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/OControlsPlugin.ts new file mode 100644 index 0000000..4b5b6bf --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/OControlsPlugin.ts @@ -0,0 +1,81 @@ +import * as THREE from "three" +import { OrbitControls } from "three/examples/jsm/Addons.js" +import { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +export interface OControlsPluginAO { + enableDamping?: boolean + /** 是否将鼠标操作逻辑改成和 cesium 一样 */ + resetMouse?: boolean +} + +const genInfo = genZTUInfo("OControlsPlugin") + +export class OControlsPlugin implements ThreeHelperPlugin { + private key = Symbol.for("controls") + private ac_key = Symbol.for("update_controls") + private addProps: ThreeHelperPluginProps | null = null + + private _controls?: OrbitControls + get controls() { + return this._controls + } + + add(props: ThreeHelperPluginProps, options: OControlsPluginAO = {}): OControlsPlugin { + this.addProps = props + const { threeHelper, widgetCollection, emitter } = props + const { animationCollection, pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as OControlsPlugin + if (plugin) { + console.error(genInfo("已经存在一个 ControlsPlugin, 不能重复添加")) + return plugin + } + + const { enableDamping = true, resetMouse = true } = options + const renderer = threeHelper.getWidget("renderer") + const camera = threeHelper.getWidget("camera") + + if (!renderer?.domElement || !camera) { + console.error(genInfo("不存在可用的 renderer 和 camera")) + return this + } + + const controls = new OrbitControls(camera, renderer.domElement) + controls.enableDamping = enableDamping + if (resetMouse) { + controls.enablePan = true + controls.mouseButtons.LEFT = THREE.MOUSE.PAN + controls.mouseButtons.MIDDLE = THREE.MOUSE.ROTATE + } + this._controls = controls + + widgetCollection.set("controls", controls) + emitter.emit("controls", controls) + + animationCollection.set(this.ac_key, { + fn({ delta }) { + controls.update?.(delta) + }, + }) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper, widgetCollection, emitter } = this.addProps + const { animationCollection, pluginCollection } = threeHelper + + widgetCollection.delete("controls") + emitter.clearHistory("controls") + + this.controls?.dispose() + this._controls = undefined + animationCollection.delete(this.ac_key) + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/PCameraPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/PCameraPlugin.ts new file mode 100644 index 0000000..8a7de5b --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/PCameraPlugin.ts @@ -0,0 +1,68 @@ +import * as THREE from "three" +import { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +export interface PCameraPluginAO { + fov?: number + near?: number + far?: number +} + +const genInfo = genZTUInfo("PCameraPlugin") + +export class PCameraPlugin implements ThreeHelperPlugin { + private key = Symbol.for("camera") + private rc_key = Symbol.for("resize_camera") + private addProps: ThreeHelperPluginProps | null = null + + private _camera?: THREE.PerspectiveCamera + get camera() { + return this._camera + } + + add(props: ThreeHelperPluginProps, options: PCameraPluginAO = {}): PCameraPlugin { + this.addProps = props + const { threeHelper, widgetCollection, emitter } = props + const { resizeCollection, pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as PCameraPlugin + if (plugin) { + console.error(genInfo("已经存在一个 CameraPlugin, 不能重复添加")) + return plugin + } + + const { fov = 45, near = 0.1, far = 1e4 } = options + const camera = new THREE.PerspectiveCamera(fov, window.innerWidth / window.innerHeight, near, far) + camera.position.set(5, 5, 5) + this._camera = camera + + widgetCollection.set("camera", camera) + emitter.emit("camera", camera) + + resizeCollection.set(this.rc_key, { + fn() { + camera.aspect = window.innerWidth / window.innerHeight + camera.updateProjectionMatrix() + }, + }) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper, widgetCollection, emitter } = this.addProps + const { resizeCollection, pluginCollection } = threeHelper + + widgetCollection.delete("camera") + emitter.clearHistory("camera") + + this._camera?.remove() + this._camera = undefined + resizeCollection.delete(this.rc_key) + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/RendererPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/RendererPlugin.ts new file mode 100644 index 0000000..49c3476 --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/RendererPlugin.ts @@ -0,0 +1,98 @@ +import * as THREE from "three" +import { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +const genInfo = genZTUInfo("RendererPlugin") + +export class RendererPlugin implements ThreeHelperPlugin { + private key = Symbol.for("renderer") + private ac_key = Symbol.for("update_renderer") + private rc_key = Symbol.for("resize_renderer") + private addProps: ThreeHelperPluginProps | null = null + + private _renderer?: THREE.WebGLRenderer + get renderer() { + return this._renderer + } + + add(props: ThreeHelperPluginProps, options?: THREE.WebGLRendererParameters): RendererPlugin { + this.addProps = props + const { threeHelper, widgetCollection, emitter } = props + const { animationCollection, resizeCollection, pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as RendererPlugin + if (plugin) { + console.error(genInfo("已经存在一个 RendererPlugin, 不能重复添加")) + return plugin + } + + const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true, logarithmicDepthBuffer: true, ...options }) + renderer.shadowMap.enabled = true + renderer.toneMapping = THREE.ACESFilmicToneMapping + renderer.outputColorSpace = THREE.SRGBColorSpace + renderer.setSize(window.innerWidth, window.innerHeight) + renderer.setPixelRatio(window.devicePixelRatio) + this._renderer = renderer + + widgetCollection.set("renderer", renderer) + emitter.emit("renderer", renderer) + + animationCollection.set(this.ac_key, { + fn() { + const camera = widgetCollection.get("camera") + const scene = widgetCollection.get("scene") + if (camera && scene) renderer.render(scene, camera) + }, + }) + resizeCollection.set(this.rc_key, { + fn() { + renderer.setSize(window.innerWidth, window.innerHeight) + }, + }) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper, widgetCollection, emitter } = this.addProps + const { animationCollection, resizeCollection, pluginCollection } = threeHelper + + widgetCollection.delete("renderer") + emitter.clearHistory("renderer") + + this.renderer?.dispose() + this._renderer = undefined + animationCollection.delete(this.ac_key) + resizeCollection.delete(this.rc_key) + + pluginCollection.delete(this.key) + this.addProps = null + } +} + +// interface Test { +// getAny(a: A): Test +// } + +// class TTTT implements Test<{ hello: string }> { +// getAny(a: { hello: string }) { +// return this +// } +// } + +// type Func> = (t: O, p: T) => O + +// const func = , T extends IObj = IObj>(t: O, p?: T) => {} +// func(new TTTT(), { hello: 1 }) + +// class TestPlugin implements ThreeHelperPlugin<{ hello: string }> { +// add(props: ThreeHelperPluginProps, options?: { hello: string }): TestPlugin { +// return this +// } +// remove(): void {} +// } + +// const addPlugin = (plugin: ThreeHelperPlugin, options?: AO) => {} +// addPlugin(new RendererPlugin(), { aa: 1 }) diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/ResizePlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/ResizePlugin.ts new file mode 100644 index 0000000..d1e5b8d --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/ResizePlugin.ts @@ -0,0 +1,45 @@ +import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +const genInfo = genZTUInfo("ResizePlugin") + +export class ResizePlugin implements ThreeHelperPlugin { + private key = Symbol.for("resize") + private addProps: ThreeHelperPluginProps | null = null + private resizeFn: (() => void) | null = null + + add(props: ThreeHelperPluginProps): ResizePlugin { + this.addProps = props + const { threeHelper } = props + const { resizeCollection, pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as ResizePlugin + if (plugin) { + console.error(genInfo("已经存在一个 ResizePlugin, 不能重复添加")) + return plugin + } + + this.resizeFn = () => { + resizeCollection.forEach(({ fn, state = {} }) => { + if (state.enable === false) return + fn({ state }) + }) + } + window.addEventListener("resize", this.resizeFn) + + pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper } = this.addProps + const { pluginCollection } = threeHelper + + this.resizeFn && window.removeEventListener("resize", this.resizeFn) + this.resizeFn = null + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/ScenePlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/ScenePlugin.ts new file mode 100644 index 0000000..1ea07a3 --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/ScenePlugin.ts @@ -0,0 +1,48 @@ +import * as THREE from "three" +import { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +const genInfo = genZTUInfo("ScenePlugin") + +export class ScenePlugin implements ThreeHelperPlugin { + private key = Symbol.for("scene") + private addProps: ThreeHelperPluginProps | null = null + + private _scene?: THREE.Scene + get scene() { + return this._scene + } + + add(props: ThreeHelperPluginProps): ScenePlugin { + this.addProps = props + const { threeHelper, widgetCollection, emitter } = props + + const plugin = threeHelper.pluginCollection.get(this.key) as ScenePlugin + if (plugin) { + console.error(genInfo("已经存在一个 ScenePlugin, 不能重复添加")) + return plugin + } + + const scene = new THREE.Scene() + this._scene = scene + + widgetCollection.set("scene", scene) + emitter.emit("scene", scene) + + threeHelper.pluginCollection.set(this.key, this) + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper, widgetCollection, emitter } = this.addProps + + widgetCollection.delete("scene") + emitter.clearHistory("scene") + + this._scene = undefined + + threeHelper.pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/helper/threeHelper/plugins/SyncCesiumPlugin.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/SyncCesiumPlugin.ts new file mode 100644 index 0000000..efa4fd6 --- /dev/null +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/SyncCesiumPlugin.ts @@ -0,0 +1,105 @@ +import type { Viewer } from "cesium" +import * as THREE from "three" +import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." +import { genZTUInfo } from "../../../util/util" + +interface SyncCesiumPluginAO { + viewer: Viewer +} + +const genInfo = genZTUInfo("SyncCesiumPlugin") + +export class SyncCesiumPlugin implements ThreeHelperPlugin { + private key = Symbol.for("sync_cesium") + private ac_key = Symbol.for("update_sync_cesium") + private viewer?: Viewer + private addProps: ThreeHelperPluginProps | null = null + private cache?: { near: number; far: number } + + constructor(viewer: Viewer) { + this.viewer = viewer + } + + add(props: ThreeHelperPluginProps, options?: SyncCesiumPluginAO): SyncCesiumPlugin { + this.addProps = props + const { threeHelper } = props + const { animationCollection, pluginCollection } = threeHelper + + const plugin = pluginCollection.get(this.key) as SyncCesiumPlugin + if (plugin) { + console.error(genInfo("已经存在一个 EffectComposerPlugin, 不能重复添加")) + return plugin + } + + const camera = threeHelper.getWidget("camera") as THREE.PerspectiveCamera + if (!camera) { + console.error(genInfo("不存在可用的 camera")) + return this + } + + this.cache = { near: camera.near, far: camera.far } + camera.near = 100 + camera.far = 1e8 + // const updateRenderer = animationCollection.get(Symbol.for("update_renderer")) + // if (updateRenderer) { + // if (!updateRenderer.state) updateRenderer.state = {} + // updateRenderer.state.enable = false + // } + + animationCollection.set(this.ac_key, { + fn: () => { + if (!this.viewer) return + /*************** sync camera ***************/ + const viewerCamera = this.viewer.camera + // @ts-ignore + camera.fov = THREE.MathUtils.radToDeg(viewerCamera.frustum.fovy) + camera.matrixAutoUpdate = false + const cvm = viewerCamera.viewMatrix + const civm = viewerCamera.inverseViewMatrix + + camera.lookAt(new THREE.Vector3(0, 0, 0)) + // prettier-ignore + camera.matrixWorld.set( + civm[0], civm[4], civm[8], civm[12], + civm[1], civm[5], civm[9], civm[13], + civm[2], civm[6], civm[10], civm[14], + civm[3], civm[7], civm[11], civm[15] + ) + // prettier-ignore + camera.matrixWorldInverse.set( + cvm[0], cvm[4], cvm[8], cvm[12], + cvm[1], cvm[5], cvm[9], cvm[13], + cvm[2], cvm[6], cvm[10], cvm[14], + cvm[3], cvm[7], cvm[11], cvm[15] + ) + + camera.updateProjectionMatrix() + + /*************** update renderer ***************/ + // if (cache.updateRenderer) { + // const { fn, state = {} } = cache.updateRenderer + // fn({ time, delta, state }) + // } + }, + }) + + return this + } + + remove(): void { + if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) + const { threeHelper } = this.addProps + const { animationCollection, pluginCollection } = threeHelper + + this.viewer = undefined + animationCollection.delete(this.ac_key) + const camera = threeHelper.getWidget("camera") as THREE.PerspectiveCamera + if (this.cache && camera) { + camera.near = this.cache.near + camera.far = this.cache.far + } + + pluginCollection.delete(this.key) + this.addProps = null + } +} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/index.ts b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/index.ts similarity index 73% rename from packages/zxtool-three-utils/src/widget/threeHelper/plugins/index.ts rename to packages/zxtool-three-utils/src/helper/threeHelper/plugins/index.ts index 0c6031a..4fb00a1 100644 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/index.ts +++ b/packages/zxtool-three-utils/src/helper/threeHelper/plugins/index.ts @@ -23,38 +23,39 @@ export interface StateCbCollection extends Omit< set(key: K, value: StateCbCollectionV): this forEach( callbackfn: (value: StateCbCollectionV, key: K, map: Map>) => void, - thisArg?: any, + thisArg?: unknown, ): void } -export type AnimationWithState = { +export type AnimationWithState = { fn(props: { time: number; delta: number; state: T }): void state?: T } -export type ClickWithState = { - fn(props: { objs: THREE.Intersection>[]; e: MouseEvent; state: T }): void - state?: T -} -export type FunctionWithState = { +export type FunctionWithState = { fn(props: { state: T }): void state?: T } export interface ThreeHelperPluginProps { - KEY: PropertyKey emitter: EmitterHelper - initializedCache: Map - clearCollection: StateCbCollection widgetCollection: Map threeHelper: ThreeHelper } -export interface ThreeHelperPlugin { - add(props: ThreeHelperPluginProps): void - remove(props: ThreeHelperPluginProps): void +export interface ThreeHelperPlugin { + add(props: ThreeHelperPluginProps, options?: AO): ThreeHelperPlugin + remove(options?: RO): void } -export * from "./ClickPlugin" +export * from "./AnimationPlugin" +export * from "./CSS2DRendererPlugin" +export * from "./CSS3DRendererPlugin" export * from "./DevPlugin" export * from "./EffectComposerPlugin" -export * from "./OrbitControlsPlugin" +export * from "./MouseEventPlugin" +export * from "./OCameraPlugin" +export * from "./OControlsPlugin" +export * from "./PCameraPlugin" +export * from "./RendererPlugin" +export * from "./ResizePlugin" +export * from "./ScenePlugin" export * from "./SyncCesiumPlugin" diff --git a/packages/zxtool-three-utils/src/index.ts b/packages/zxtool-three-utils/src/index.ts index 838fec9..14a9e9e 100644 --- a/packages/zxtool-three-utils/src/index.ts +++ b/packages/zxtool-three-utils/src/index.ts @@ -1,4 +1,3 @@ -export * from "./util/LoaderUtil" -export * from "./widget/CustomGridHelper" -export * from "./widget/threeHelper/ThreeHelper" -export * from "./widget/threeHelper/plugins" +export * from "./geometry" +export * from "./helper" +export * from "./util" diff --git a/packages/zxtool-three-utils/src/type/type.d.ts b/packages/zxtool-three-utils/src/type/type.d.ts new file mode 100644 index 0000000..da6ba37 --- /dev/null +++ b/packages/zxtool-three-utils/src/type/type.d.ts @@ -0,0 +1,11 @@ +import { IObj } from "@zxtool/utils" + +declare module "three" { + export interface Object3D { + __customField: { + onClick?: (data: Object3D["__customField"], e: THREE.Intersection>) => void + onEnter?: (data: Object3D["__customField"], e: THREE.Intersection>) => void + onLeave?: (data: Object3D["__customField"], e: THREE.Intersection>) => void + } & IObj + } +} diff --git a/packages/zxtool-three-utils/src/util/LoaderUtil.ts b/packages/zxtool-three-utils/src/util/LoaderUtil.ts index 16b042a..0450f26 100644 --- a/packages/zxtool-three-utils/src/util/LoaderUtil.ts +++ b/packages/zxtool-three-utils/src/util/LoaderUtil.ts @@ -1,13 +1,12 @@ import * as THREE from "three" -import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader" -import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js" -import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js" +import { DRACOLoader, GLTFLoader, RGBELoader } from "three/examples/jsm/Addons.js" const textureLoader = new THREE.TextureLoader() const cubeTextureLoader = new THREE.CubeTextureLoader() const rgbeLoader = new RGBELoader() const dracoLoader = new DRACOLoader() const gltfLoader = new GLTFLoader() +const fileLoader = new THREE.FileLoader() dracoLoader.setDecoderPath("/draco/") gltfLoader.setDRACOLoader(dracoLoader) @@ -18,4 +17,5 @@ export const LoaderUtil = { rgbeLoader, dracoLoader, gltfLoader, + fileLoader, } diff --git a/packages/zxtool-three-utils/src/util/index.ts b/packages/zxtool-three-utils/src/util/index.ts new file mode 100644 index 0000000..8d003f1 --- /dev/null +++ b/packages/zxtool-three-utils/src/util/index.ts @@ -0,0 +1 @@ +export * from "./LoaderUtil" diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/ThreeHelper.ts b/packages/zxtool-three-utils/src/widget/threeHelper/ThreeHelper.ts deleted file mode 100644 index 2ea3a98..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/ThreeHelper.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { EmitterHelper } from "@zxtool/utils" -import { - AnimationWithState, - ClickWithState, - FunctionWithState, - StateCbCollection, - ThreeHelperPlugin, - ThreeHelperPluginProps, -} from "./plugins" -import { AnimationPlugin } from "./plugins/AnimationPlugin" -import { ResizePlugin } from "./plugins/ResizePlugin" -import { ThreeBasePlugin } from "./plugins/ThreeBasePlugin" - -export interface ThreeHelper { - getWidget(type: "scene"): THREE.Scene | undefined - getWidget(type: "renderer"): THREE.WebGLRenderer | undefined - getWidget(type: "p_camera"): THREE.PerspectiveCamera | undefined - getWidget(type: "canvas"): HTMLCanvasElement | undefined - - getWidgetAsync(type: "scene"): Promise - getWidgetAsync(type: "renderer"): Promise - getWidgetAsync(type: "p_camera"): Promise - getWidgetAsync(type: "canvas"): Promise -} - -export class ThreeHelper { - private readonly KEY: PropertyKey = Symbol("TH") - private readonly emitter = new EmitterHelper({ maxCount: { history: 1 } }) - private readonly initializedCache: Map = new Map() - private readonly clearCollection: StateCbCollection = new Map() - private readonly widgetCollection: Map = new Map() - - readonly time = { value: 0 } - readonly animationCollection: StateCbCollection = new Map() - readonly clickCollection: StateCbCollection = new Map() - readonly resizeCollection: StateCbCollection = new Map() - readonly pluginCollection: Map = new Map() - - getWidget(key: PropertyKey): any { - return this.widgetCollection.get(key) - } - getWidgetAsync(key: PropertyKey) { - return this.emitter.onceAsync(key, true).promise - } - - add(plugin: ThreeHelperPlugin) { - const props: ThreeHelperPluginProps = { - KEY: this.KEY, - emitter: this.emitter, - initializedCache: this.initializedCache, - clearCollection: this.clearCollection, - widgetCollection: this.widgetCollection, - threeHelper: this, - } - plugin.add(props) - } - remove(plugin: ThreeHelperPlugin) { - const props: ThreeHelperPluginProps = { - KEY: this.KEY, - emitter: this.emitter, - initializedCache: this.initializedCache, - clearCollection: this.clearCollection, - widgetCollection: this.widgetCollection, - threeHelper: this, - } - plugin.remove(props) - } - - init(canvas: HTMLCanvasElement) { - if (this.initializedCache.get(this.KEY)) return - - this.add(new ThreeBasePlugin(canvas)) - this.add(new AnimationPlugin()) - this.add(new ResizePlugin()) - - this.initializedCache.set(this.KEY, true) - } -} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/AnimationPlugin.ts b/packages/zxtool-three-utils/src/widget/threeHelper/plugins/AnimationPlugin.ts deleted file mode 100644 index b1d139b..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/AnimationPlugin.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { throttle } from "lodash" -import * as THREE from "three" -import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." - -export class AnimationPlugin implements ThreeHelperPlugin { - private key = Symbol.for("animation") - private animationId = { value: 0 } - - add(props: ThreeHelperPluginProps): void { - const { threeHelper, initializedCache, clearCollection } = props - const { time, animationCollection } = threeHelper - if (initializedCache.get(this.key)) return - - const clock = new THREE.Clock() - - const animation = (t = 0) => { - time.value = t - const delta = clock.getDelta() - animationCollection.forEach<{ _throttled?: boolean }>(item => { - const { fn, state = {} } = item - if (state.throttleTime && !state._throttled) { - fn({ time: t, delta, state }) - item.fn = throttle(item.fn, state.throttleTime) - state._throttled = true - } else fn({ time: t, delta, state }) - }) - this.animationId.value = requestAnimationFrame(animation) - } - animation() - - clearCollection.set(this.key, { - fn: () => { - cancelAnimationFrame(this.animationId.value) - time.value = 0 - animationCollection.clear() - initializedCache.set(this.key, false) - }, - }) - - initializedCache.set(this.key, true) - } - - remove({ clearCollection }: ThreeHelperPluginProps): void { - const clearObj = clearCollection.get(this.key) - if (clearObj) clearObj.fn({ state: clearObj.state ?? {} }) - } -} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/CameraPlugin.ts b/packages/zxtool-three-utils/src/widget/threeHelper/plugins/CameraPlugin.ts deleted file mode 100644 index 47403e9..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/CameraPlugin.ts +++ /dev/null @@ -1,53 +0,0 @@ -import * as THREE from "three" -import { ThreeHelperPlugin, ThreeHelperPluginProps } from "." -import { genZTUInfo } from "../../../util/util" - -const genInfo = genZTUInfo("CameraPlugin") - -export class CameraPlugin implements ThreeHelperPlugin { - private key = Symbol.for("animation") - private _camera: THREE.Camera - private addProps!: ThreeHelperPluginProps - - get camera() { - return this.camera - } - set camera(c: THREE.Camera) { - if (!this.addProps) throw new Error(genInfo("设置 camera 之前需要先添加此插件")) - const { widgetCollection, emitter } = this.addProps - - this._camera = c - widgetCollection.set("camera", c) - emitter.emit("camera", c) - } - - constructor() { - this._camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1e4) - this._camera.position.set(5, 5, 5) - } - - add(props: ThreeHelperPluginProps): CameraPlugin { - this.addProps = props - const { widgetCollection, emitter, threeHelper } = props - - const plugin = threeHelper.pluginCollection.get(this.key) as CameraPlugin - if (plugin) { - console.error(genInfo("已经存在一个 CameraPlugin, 不能重复添加")) - return plugin - } - - widgetCollection.set("camera", this.camera) - emitter.emit("camera", this.camera) - - return this - } - - remove(): void { - if (!this.addProps) throw new Error(genInfo("未添加的插件不能被移除")) - - const { widgetCollection, emitter } = this.addProps - - widgetCollection.delete("camera") - emitter.clearHistory("camera") - } -} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/ClickPlugin.ts b/packages/zxtool-three-utils/src/widget/threeHelper/plugins/ClickPlugin.ts deleted file mode 100644 index fc9500f..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/ClickPlugin.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { LikeDom } from "@zxtool/utils" -import * as THREE from "three" -import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." - -export class ClickPlugin implements ThreeHelperPlugin { - private key = Symbol.for("click") - private cc_key = Symbol.for("default_click") - private dom: LikeDom - - constructor(dom: LikeDom) { - this.dom = dom - } - - add(props: ThreeHelperPluginProps): void { - const { threeHelper, initializedCache, clearCollection } = props - const { clickCollection } = threeHelper - if (initializedCache.get(this.key)) return - - const raycaster = new THREE.Raycaster() - const mouse = new THREE.Vector2() - - const clickFn = (ev: unknown) => { - const scene = threeHelper.getWidget("scene") - const camera = threeHelper.getWidget("p_camera") - if (!scene || !camera) return - - const e = ev as MouseEvent - mouse.x = (e.clientX / window.innerWidth - 0.5) * 2 - mouse.y = (e.clientY / window.innerHeight - 0.5) * -2 - - raycaster.setFromCamera(mouse, camera) - let res: THREE.Intersection>[] | null = null - - clickCollection.forEach(({ fn, state = {} }) => { - const objs = state.objs - if (objs?.length) { - const _res = raycaster.intersectObjects(objs) - if (_res.length) fn({ objs: _res, e, state }) - } else { - if (!res) res = raycaster.intersectObjects(scene.children) - fn({ objs: res, e, state }) - } - }) - } - - this.dom.addEventListener("click", clickFn) - - clearCollection.set(this.key, { - fn: () => { - this.dom.removeEventListener("click", clickFn) - clickCollection.clear() - initializedCache.set(this.key, false) - }, - }) - - clickCollection.set(this.cc_key, { - fn({ objs }) { - const mesh = objs?.[0]?.object - // @ts-ignore - if (typeof mesh?.__onClick === "function") mesh.__onClick() - }, - }) - - initializedCache.set(this.key, true) - } - - remove({ clearCollection }: ThreeHelperPluginProps): void { - const clearObj = clearCollection.get(this.key) - if (clearObj) clearObj.fn({ state: clearObj.state ?? {} }) - } -} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/DevPlugin.ts b/packages/zxtool-three-utils/src/widget/threeHelper/plugins/DevPlugin.ts deleted file mode 100644 index c7debd3..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/DevPlugin.ts +++ /dev/null @@ -1,65 +0,0 @@ -import * as THREE from "three" -import Stats from "three/examples/jsm/libs/stats.module.js" -import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." - -export interface DevPluginConfig { - enableStats?: boolean - enableAxes?: boolean - axesSize?: number -} - -export class DevPlugin implements ThreeHelperPlugin { - private key = Symbol.for("dev") - private ac_key = Symbol.for("update_stats") - private stats?: Stats - private axesHelper?: THREE.AxesHelper - private config: DevPluginConfig - - constructor(config: DevPluginConfig = {}) { - this.config = config - } - - add(props: ThreeHelperPluginProps): void { - const { threeHelper, initializedCache, clearCollection } = props - const { animationCollection } = threeHelper - if (initializedCache.get(this.key)) return - - const scene = threeHelper.getWidget("scene") - if (!scene) return - - const { enableStats = true, enableAxes = true, axesSize = 50 } = this.config - - if (enableAxes) { - this.axesHelper = new THREE.AxesHelper(axesSize) - scene.add(this.axesHelper) - } - if (enableStats) { - this.stats = new Stats() - document.body.appendChild(this.stats.dom) - animationCollection.set(this.ac_key, { - fn: () => this.stats?.update(), - }) - } - - clearCollection.set(this.key, { - fn: () => { - if (this.stats) { - this.stats.dom.remove() - this.stats = undefined - } - if (this.axesHelper) { - scene.remove(this.axesHelper) - this.axesHelper = undefined - } - initializedCache.set(this.key, false) - }, - }) - - initializedCache.set(this.key, true) - } - - remove({ clearCollection }: ThreeHelperPluginProps): void { - const clearObj = clearCollection.get(this.key) - if (clearObj) clearObj.fn({ state: clearObj.state ?? {} }) - } -} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/EffectComposerPlugin.ts b/packages/zxtool-three-utils/src/widget/threeHelper/plugins/EffectComposerPlugin.ts deleted file mode 100644 index fb4c69a..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/EffectComposerPlugin.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js" -import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js" -import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." - -export class EffectComposerPlugin implements ThreeHelperPlugin { - private key = Symbol.for("effect_composer") - private ac_key = Symbol.for("update_effect_composer") - private _effectComposer: EffectComposer | null = null - - get effectComposer() { - return this._effectComposer - } - - add(props: ThreeHelperPluginProps): void { - const { threeHelper, initializedCache, clearCollection } = props - const { animationCollection } = threeHelper - if (initializedCache.get(this.key)) return - - const scene = threeHelper.getWidget("scene")! - const renderer = threeHelper.getWidget("renderer")! - const camera = threeHelper.getWidget("p_camera")! - - const effectComposer = new EffectComposer(renderer) - effectComposer.setSize(window.innerWidth, window.innerHeight) - effectComposer.setPixelRatio(window.devicePixelRatio) - effectComposer.addPass(new RenderPass(scene, camera)) - this._effectComposer = effectComposer - - const updateRendererCache = animationCollection.get(Symbol.for("update_renderer")) - - animationCollection.set(this.ac_key, { - fn() { - effectComposer.render() - }, - }) - - clearCollection.set(this.key, { - fn: () => { - updateRendererCache && animationCollection.set(Symbol.for("update_renderer"), updateRendererCache) - animationCollection.delete(this.ac_key) - this._effectComposer = null - initializedCache.set(this.key, false) - }, - }) - - initializedCache.set(this.key, true) - } - - remove({ clearCollection }: ThreeHelperPluginProps): void { - const clearObj = clearCollection.get(this.key) - if (clearObj) clearObj.fn({ state: clearObj.state ?? {} }) - } -} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/OrbitControlsPlugin.ts b/packages/zxtool-three-utils/src/widget/threeHelper/plugins/OrbitControlsPlugin.ts deleted file mode 100644 index 64b518a..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/OrbitControlsPlugin.ts +++ /dev/null @@ -1,72 +0,0 @@ -import * as THREE from "three" -import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js" -import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." - -export interface IControlsConfig { - enableDamping?: boolean - distance?: [number, number] - /** 是否将鼠标操作逻辑改成和 cesium 一样 */ - resetMouse?: boolean -} - -export class OrbitControlsPlugin implements ThreeHelperPlugin { - private key = Symbol.for("o_controls") - private ac_key = Symbol.for("update_o_controls") - private controls?: OrbitControls - private config: IControlsConfig - - constructor(config: IControlsConfig = {}) { - this.config = config - } - - add(props: ThreeHelperPluginProps): void { - const { threeHelper, initializedCache, clearCollection, widgetCollection, emitter } = props - const { animationCollection } = threeHelper - if (initializedCache.get(this.key)) return - - const scene = threeHelper.getWidget("scene") - const canvas = threeHelper.getWidget("canvas") - const camera = threeHelper.getWidget("p_camera") - if (!scene || !canvas || !camera) return - - const { enableDamping = true, distance = [1, 1000], resetMouse = true } = this.config - - this.controls = new OrbitControls(camera, canvas) - this.controls.enableDamping = enableDamping - this.controls.minDistance = distance[0] - this.controls.maxDistance = distance[1] - - if (resetMouse) { - this.controls.enablePan = true - this.controls.mouseButtons.LEFT = THREE.MOUSE.PAN - this.controls.mouseButtons.MIDDLE = THREE.MOUSE.ROTATE - } - - animationCollection.set(this.ac_key, { - fn: ({ delta }) => { - this.controls?.update(delta) - }, - }) - - widgetCollection.set("o_controls", this.controls) - emitter.emit("o_controls", this.controls) - - clearCollection.set(this.key, { - fn: () => { - this.controls?.dispose() - this.controls = undefined - animationCollection.delete(this.ac_key) - initializedCache.set(this.key, false) - widgetCollection.delete("o_controls") - emitter.clearHistory("o_controls") - }, - }) - - initializedCache.set(this.key, true) - } - - remove({ clearCollection }: ThreeHelperPluginProps): void { - const clearObj = clearCollection.get(this.key) - if (clearObj) clearObj.fn({ state: clearObj.state ?? {} }) - } -} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/ResizePlugin.ts b/packages/zxtool-three-utils/src/widget/threeHelper/plugins/ResizePlugin.ts deleted file mode 100644 index f63671d..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/ResizePlugin.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." - -export class ResizePlugin implements ThreeHelperPlugin { - private key = Symbol.for("resize") - private rc_key = Symbol.for("resize_camera_renderer") - - add(props: ThreeHelperPluginProps): void { - const { threeHelper, initializedCache, clearCollection } = props - const { resizeCollection } = threeHelper - if (initializedCache.get(this.key)) return - const camera = threeHelper.getWidget("p_camera")! - const renderer = threeHelper.getWidget("renderer")! - - const resizeFn = () => { - resizeCollection.forEach(({ fn, state = {} }) => fn({ state })) - } - - window.addEventListener("resize", resizeFn) - - resizeCollection.set(this.rc_key, { - fn: () => { - renderer.setSize(window.innerWidth, window.innerHeight) - renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) - camera.aspect = window.innerWidth / window.innerHeight - camera.updateProjectionMatrix() - }, - }) - clearCollection.set(this.key, { - fn: () => { - window.removeEventListener("resize", resizeFn) - resizeCollection.clear() - initializedCache.set(this.key, false) - }, - }) - - initializedCache.set(this.key, true) - } - - remove({ clearCollection }: ThreeHelperPluginProps): void { - const clearObj = clearCollection.get(this.key) - if (clearObj) clearObj.fn({ state: clearObj.state ?? {} }) - } -} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/SyncCesiumPlugin.ts b/packages/zxtool-three-utils/src/widget/threeHelper/plugins/SyncCesiumPlugin.ts deleted file mode 100644 index 688c585..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/SyncCesiumPlugin.ts +++ /dev/null @@ -1,83 +0,0 @@ -import type { Viewer } from "cesium" -import * as THREE from "three" -import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." - -export class SyncCesiumPlugin implements ThreeHelperPlugin { - private key = Symbol.for("sync_cesium") - private ac_key = Symbol.for("update_sync_cesium") - private viewer: Viewer - - constructor(viewer: Viewer) { - this.viewer = viewer - } - - add(props: ThreeHelperPluginProps): void { - const { threeHelper, initializedCache, clearCollection } = props - const { animationCollection } = threeHelper - if (initializedCache.get(this.key)) return - - const camera = threeHelper.getWidget("p_camera")! - - const cache = { - near: camera.near, - far: camera.far, - updateRenderer: animationCollection.get(Symbol.for("update_renderer")), - } - camera.near = 100 - camera.far = 1e8 - animationCollection.delete(Symbol.for("update_renderer")) - - animationCollection.set(this.ac_key, { - fn: ({ time, delta }) => { - /*************** sync camera ***************/ - const viewerCamera = this.viewer.camera - // @ts-ignore - camera.fov = THREE.MathUtils.radToDeg(viewerCamera.frustum.fovy) - camera.matrixAutoUpdate = false - const cvm = viewerCamera.viewMatrix - const civm = viewerCamera.inverseViewMatrix - - camera.lookAt(new THREE.Vector3(0, 0, 0)) - // prettier-ignore - camera.matrixWorld.set( - civm[0], civm[4], civm[8], civm[12], - civm[1], civm[5], civm[9], civm[13], - civm[2], civm[6], civm[10], civm[14], - civm[3], civm[7], civm[11], civm[15] - ) - // prettier-ignore - camera.matrixWorldInverse.set( - cvm[0], cvm[4], cvm[8], cvm[12], - cvm[1], cvm[5], cvm[9], cvm[13], - cvm[2], cvm[6], cvm[10], cvm[14], - cvm[3], cvm[7], cvm[11], cvm[15] - ) - - camera.updateProjectionMatrix() - - /*************** update renderer ***************/ - if (cache.updateRenderer) { - const { fn, state = {} } = cache.updateRenderer - fn({ time, delta, state }) - } - }, - }) - - clearCollection.set(this.key, { - fn: () => { - cache.updateRenderer && animationCollection.set(Symbol.for("update_renderer"), cache.updateRenderer) - camera.near = cache.near - camera.far = cache.far - animationCollection.delete(this.ac_key) - initializedCache.set(this.key, false) - }, - }) - - initializedCache.set(this.key, true) - } - - remove({ clearCollection }: ThreeHelperPluginProps): void { - const clearObj = clearCollection.get(this.key) - if (clearObj) clearObj.fn({ state: clearObj.state ?? {} }) - } -} diff --git a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/ThreeBasePlugin.ts b/packages/zxtool-three-utils/src/widget/threeHelper/plugins/ThreeBasePlugin.ts deleted file mode 100644 index 4993bae..0000000 --- a/packages/zxtool-three-utils/src/widget/threeHelper/plugins/ThreeBasePlugin.ts +++ /dev/null @@ -1,64 +0,0 @@ -import * as THREE from "three" -import type { ThreeHelperPlugin, ThreeHelperPluginProps } from "." - -export class ThreeBasePlugin implements ThreeHelperPlugin { - private key = Symbol.for("three_base") - private ac_key = Symbol.for("update_renderer") - private canvas: HTMLCanvasElement - private scene?: THREE.Scene - private camera?: THREE.PerspectiveCamera - private renderer?: THREE.WebGLRenderer - - constructor(canvas: HTMLCanvasElement) { - this.canvas = canvas - } - - add(props: ThreeHelperPluginProps): void { - const { threeHelper, initializedCache, emitter, clearCollection, widgetCollection } = props - const { animationCollection } = threeHelper - if (initializedCache.get(this.key)) return - - this.scene = new THREE.Scene() - this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1e4) - this.camera.position.set(5, 5, 5) - this.renderer = new THREE.WebGLRenderer({ - canvas: this.canvas, - alpha: true, - antialias: true, - logarithmicDepthBuffer: true, - }) - this.renderer.shadowMap.enabled = true - this.renderer.toneMapping = THREE.ACESFilmicToneMapping - this.renderer.outputColorSpace = THREE.SRGBColorSpace - this.renderer.setSize(window.innerWidth, window.innerHeight) - this.renderer.setPixelRatio(window.devicePixelRatio) - - animationCollection.set(this.ac_key, { - fn: () => { - if (this.renderer && this.camera && this.scene) this.renderer.render(this.scene, this.camera) - }, - }) - - widgetCollection.set("scene", this.scene) - widgetCollection.set("renderer", this.renderer) - widgetCollection.set("p_camera", this.camera) - widgetCollection.set("canvas", this.canvas) - emitter.emit("scene", this.scene) - emitter.emit("renderer", this.renderer) - emitter.emit("p_camera", this.camera) - emitter.emit("canvas", this.canvas) - - clearCollection.set(this.key, { - fn: () => { - // todo - }, - }) - - initializedCache.set(this.key, true) - } - - remove({ clearCollection }: ThreeHelperPluginProps): void { - const clearObj = clearCollection.get(this.key) - if (clearObj) clearObj.fn({ state: clearObj.state ?? {} }) - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 53bef64..43b9ce7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -709,7 +709,13 @@ importers: json-server: specifier: 0.17.4 version: 0.17.4 + jsonwebtoken: + specifier: ^9.0.2 + version: 9.0.2 devDependencies: + '@types/jsonwebtoken': + specifier: ^9.0.5 + version: 9.0.5 nodemon: specifier: ^3.0.2 version: 3.0.2 @@ -749,6 +755,9 @@ importers: custom-style: specifier: workspace:* version: link:../../packages/custom-style + delaunator: + specifier: ^5.0.0 + version: 5.0.0 gl-matrix: specifier: ^3.4.3 version: 3.4.3 @@ -770,6 +779,9 @@ importers: nipplejs: specifier: ^0.10.1 version: 0.10.1 + point-in-polygon: + specifier: ^1.1.0 + version: 1.1.0 postprocessing: specifier: ^6.33.4 version: 6.33.4(three@0.158.0) @@ -795,12 +807,21 @@ importers: specifier: ^0.0.126 version: 0.0.126(three@0.158.0) devDependencies: + '@types/delaunator': + specifier: ^5.0.2 + version: 5.0.2 + '@types/geojson': + specifier: ^7946.0.13 + version: 7946.0.13 '@types/gl-matrix': specifier: ^3.2.0 version: 3.2.0 '@types/lodash': specifier: ^4.14.202 version: 4.14.202 + '@types/point-in-polygon': + specifier: ^1.1.5 + version: 1.1.5 '@types/react': specifier: 18.2.20 version: 18.2.20 @@ -855,6 +876,9 @@ importers: normalize.css: specifier: ^8.0.1 version: 8.0.1 + pinia: + specifier: ^2.1.7 + version: 2.1.7(typescript@5.3.2)(vue@3.3.11) vant: specifier: 4.8.1 version: 4.8.1(vue@3.3.11) @@ -871,6 +895,9 @@ importers: '@vitejs/plugin-vue': specifier: ^4.5.2 version: 4.5.2(vite@5.0.8)(vue@3.3.11) + '@vitejs/plugin-vue-jsx': + specifier: ^3.1.0 + version: 3.1.0(vite@5.0.8)(vue@3.3.11) '@zxtool/utils': specifier: workspace:* version: link:../../packages/zxtool-utils @@ -1008,7 +1035,7 @@ packages: resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/highlight': 7.22.20 + '@babel/highlight': 7.23.4 chalk: 2.4.2 dev: true @@ -1052,15 +1079,15 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.0 - '@babel/helper-compilation-targets': 7.22.15 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.2) - '@babel/helpers': 7.23.2 - '@babel/parser': 7.23.0 + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.2) + '@babel/helpers': 7.23.6 + '@babel/parser': 7.23.6 '@babel/template': 7.22.15 - '@babel/traverse': 7.23.2 - '@babel/types': 7.23.0 + '@babel/traverse': 7.23.6 + '@babel/types': 7.23.6 convert-source-map: 2.0.0 debug: 4.3.4(supports-color@5.5.0) gensync: 1.0.0-beta.2 @@ -1107,16 +1134,6 @@ packages: semver: 6.3.1 dev: true - /@babel/generator@7.23.0: - resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.6 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 - jsesc: 2.5.2 - dev: true - /@babel/generator@7.23.6: resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} engines: {node: '>=6.9.0'} @@ -1141,17 +1158,6 @@ packages: '@babel/types': 7.23.6 dev: true - /@babel/helper-compilation-targets@7.22.15: - resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.23.5 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.22.2 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - /@babel/helper-compilation-targets@7.23.6: resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} engines: {node: '>=6.9.0'} @@ -1163,8 +1169,8 @@ packages: semver: 6.3.1 dev: true - /@babel/helper-create-class-features-plugin@7.22.15(@babel/core@7.23.6): - resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==} + /@babel/helper-create-class-features-plugin@7.23.7(@babel/core@7.23.6): + resolution: {integrity: sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1242,13 +1248,13 @@ packages: '@babel/types': 7.23.6 dev: true - /@babel/helper-module-transforms@7.23.0(@babel/core@7.23.2): - resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==} + /@babel/helper-module-transforms@7.23.3(@babel/core@7.21.0): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.23.2 + '@babel/core': 7.21.0 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-module-imports': 7.22.15 '@babel/helper-simple-access': 7.22.5 @@ -1256,13 +1262,13 @@ packages: '@babel/helper-validator-identifier': 7.22.20 dev: true - /@babel/helper-module-transforms@7.23.3(@babel/core@7.21.0): + /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.2): resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.0 + '@babel/core': 7.23.2 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-module-imports': 7.22.15 '@babel/helper-simple-access': 7.22.5 @@ -1363,17 +1369,6 @@ packages: '@babel/types': 7.23.6 dev: true - /@babel/helpers@7.23.2: - resolution: {integrity: sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.6 - '@babel/types': 7.23.6 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/helpers@7.23.6: resolution: {integrity: sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==} engines: {node: '>=6.9.0'} @@ -1385,15 +1380,6 @@ packages: - supports-color dev: true - /@babel/highlight@7.22.20: - resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - /@babel/highlight@7.23.4: resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} engines: {node: '>=6.9.0'} @@ -1402,14 +1388,6 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser@7.23.0: - resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.23.6 - dev: true - /@babel/parser@7.23.6: resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==} engines: {node: '>=6.0.0'} @@ -1457,7 +1435,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.23.6 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.6) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.6) '@babel/helper-plugin-utils': 7.22.5 dev: true @@ -1672,6 +1650,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.23.6): resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} engines: {node: '>=6.9.0'} @@ -1745,7 +1733,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.23.6 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.6) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.6) '@babel/helper-plugin-utils': 7.22.5 dev: true @@ -1756,7 +1744,7 @@ packages: '@babel/core': ^7.12.0 dependencies: '@babel/core': 7.23.6 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.6) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.6) '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.6) dev: true @@ -2085,7 +2073,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.23.6 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.6) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.6) '@babel/helper-plugin-utils': 7.22.5 dev: true @@ -2097,7 +2085,7 @@ packages: dependencies: '@babel/core': 7.23.6 '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.6) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.6) '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.6) dev: true @@ -2269,17 +2257,17 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-typescript@7.22.15(@babel/core@7.23.6): - resolution: {integrity: sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==} + /@babel/plugin-transform-typescript@7.23.6(@babel/core@7.23.6): + resolution: {integrity: sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.23.6 '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.6) + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.6) '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.23.6) + '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.6) dev: true /@babel/plugin-transform-unicode-escapes@7.22.10(@babel/core@7.23.6): @@ -2453,7 +2441,7 @@ packages: '@babel/helper-validator-option': 7.23.5 '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.6) '@babel/plugin-transform-modules-commonjs': 7.23.0(@babel/core@7.23.6) - '@babel/plugin-transform-typescript': 7.22.15(@babel/core@7.23.6) + '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.23.6) dev: true /@babel/regjsgen@0.8.0: @@ -2482,24 +2470,6 @@ packages: '@babel/types': 7.23.6 dev: true - /@babel/traverse@7.23.2: - resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.6 - '@babel/types': 7.23.6 - debug: 4.3.4(supports-color@5.5.0) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/traverse@7.23.6: resolution: {integrity: sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==} engines: {node: '>=6.9.0'} @@ -2518,15 +2488,6 @@ packages: - supports-color dev: true - /@babel/types@7.23.0: - resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.23.4 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - dev: true - /@babel/types@7.23.6: resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} engines: {node: '>=6.9.0'} @@ -4745,7 +4706,7 @@ packages: resolution: {integrity: sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==} engines: {node: '>=12'} dependencies: - '@babel/code-frame': 7.22.13 + '@babel/code-frame': 7.23.5 '@babel/runtime': 7.23.1 '@types/aria-query': 5.0.2 aria-query: 5.1.3 @@ -5969,8 +5930,8 @@ packages: /@types/babel__core@7.20.2: resolution: {integrity: sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==} dependencies: - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 '@types/babel__generator': 7.6.5 '@types/babel__template': 7.4.2 '@types/babel__traverse': 7.20.2 @@ -6011,6 +5972,10 @@ packages: '@types/ms': 0.7.32 dev: true + /@types/delaunator@5.0.2: + resolution: {integrity: sha512-lqBrFSZT+7NYMtz454avpNJaAJYz4TAxsR99HOYqZLXYTduPYjpcmm8BonGGHXsE3L67yk5qO6qxKcrHpxXPMA==} + dev: true + /@types/eslint-scope@3.7.5: resolution: {integrity: sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==} dependencies: @@ -6054,7 +6019,6 @@ packages: /@types/geojson@7946.0.13: resolution: {integrity: sha512-bmrNrgKMOhM3WsafmbGmC+6dsF2Z308vLFsQ3a/bT8X8Sv5clVYpPars/UPq+sAaJP+5OoLAYgwbkS5QEJdLUQ==} - dev: false /@types/geojson@7946.0.8: resolution: {integrity: sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==} @@ -6161,6 +6125,12 @@ packages: '@types/node': 18.19.3 dev: true + /@types/jsonwebtoken@9.0.5: + resolution: {integrity: sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==} + dependencies: + '@types/node': 18.19.3 + dev: true + /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: @@ -6215,6 +6185,10 @@ packages: resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} dev: true + /@types/point-in-polygon@1.1.5: + resolution: {integrity: sha512-VYZQKsxOQCzemTWCvsdXbu6T+zbYHY5d/B34FFfcgGC3O8zDeTUcrhZOiW3+RIFVayUdewcSKF3trbvNCs3w0w==} + dev: true + /@types/prettier@2.7.3: resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} dev: true @@ -7255,6 +7229,22 @@ packages: - supports-color dev: true + /@vitejs/plugin-vue-jsx@3.1.0(vite@5.0.8)(vue@3.3.11): + resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 || ^5.0.0 + vue: ^3.0.0 + dependencies: + '@babel/core': 7.23.6 + '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.23.6) + '@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.23.6) + vite: 5.0.8(@types/node@18.19.3)(sass@1.69.7) + vue: 3.3.11(typescript@5.3.2) + transitivePeerDependencies: + - supports-color + dev: true + /@vitejs/plugin-vue@4.5.2(vite@5.0.8)(vue@3.3.11): resolution: {integrity: sha512-UGR3DlzLi/SaVBPX0cnSyE37vqxU3O6chn8l0HJNzQzDia6/Au2A4xKv+iIJW8w2daf80G7TYHhi1pAUjdZ0bQ==} engines: {node: ^14.18.0 || >=16.0.0} @@ -7285,6 +7275,29 @@ packages: path-browserify: 1.0.1 dev: true + /@vue/babel-helper-vue-transform-on@1.1.5: + resolution: {integrity: sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w==} + dev: true + + /@vue/babel-plugin-jsx@1.1.5(@babel/core@7.23.6): + resolution: {integrity: sha512-nKs1/Bg9U1n3qSWnsHhCVQtAzI6aQXqua8j/bZrau8ywT1ilXQbK4FwEJGmU8fV7tcpuFvWmmN7TMmV1OBma1g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-module-imports': 7.22.15 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.6) + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.6 + '@babel/types': 7.23.6 + '@vue/babel-helper-vue-transform-on': 1.1.5 + camelcase: 6.3.0 + html-tags: 3.3.1 + svg-tags: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /@vue/compiler-core@3.3.11: resolution: {integrity: sha512-h97/TGWBilnLuRaj58sxNrsUU66fwdRKLOLQ9N/5iNDfp+DZhYH9Obhe0bXxhedl8fjAgpRANpiZfbgWyruQ0w==} dependencies: @@ -8457,6 +8470,10 @@ packages: buffer-fill: 1.0.0 dev: true + /buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + dev: false + /buffer-fill@1.0.0: resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} dev: true @@ -9759,6 +9776,12 @@ packages: has-property-descriptors: 1.0.0 object-keys: 1.1.1 + /delaunator@5.0.0: + resolution: {integrity: sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==} + dependencies: + robust-predicates: 3.0.2 + dev: false + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -10132,6 +10155,12 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /editions@2.3.1: resolution: {integrity: sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==} engines: {node: '>=0.8'} @@ -13805,6 +13834,22 @@ packages: engines: {'0': node >= 0.2.0} dev: true + /jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.5.4 + dev: false + /jsts@2.7.1: resolution: {integrity: sha512-x2wSZHEBK20CY+Wy+BPE7MrFQHW6sIsdaGUMEqmGAio+3gFzQaBYPwLRonUfQf9Ak8pBieqj9tUofX1+WtAEIg==} engines: {node: '>= 12'} @@ -13818,6 +13863,21 @@ packages: object.assign: 4.1.4 dev: true + /jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: false + + /jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + dev: false + /kdbush@4.0.2: resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} @@ -14109,13 +14169,32 @@ packages: resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} dev: true + /lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + dev: false + + /lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + dev: false + /lodash.isfunction@3.0.9: resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} dev: true + /lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + dev: false + + /lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + dev: false + /lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - dev: true + + /lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + dev: false /lodash.kebabcase@4.1.1: resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} @@ -14133,6 +14212,10 @@ packages: resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} dev: true + /lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + dev: false + /lodash.snakecase@4.1.1: resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} dev: true @@ -15884,6 +15967,24 @@ packages: engines: {node: '>=10'} dev: true + /pinia@2.1.7(typescript@5.3.2)(vue@3.3.11): + resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==} + peerDependencies: + '@vue/composition-api': ^1.4.0 + typescript: '>=4.4.4' + vue: ^2.6.14 || ^3.3.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + typescript: + optional: true + dependencies: + '@vue/devtools-api': 6.5.1 + typescript: 5.3.2 + vue: 3.3.11(typescript@5.3.2) + vue-demi: 0.14.6(vue@3.3.11) + dev: false + /pino-abstract-transport@0.5.0: resolution: {integrity: sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==} dependencies: @@ -20755,6 +20856,21 @@ packages: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} dev: true + /vue-demi@0.14.6(vue@3.3.11): + resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + dependencies: + vue: 3.3.11(typescript@5.3.2) + dev: false + /vue-router@4.2.5(vue@3.3.11): resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==} peerDependencies: