@yangyongtao/gaea 1.1.21 → 1.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -137,7 +137,7 @@ const defaultConfig = {
137
137
  /** 天地图 token(在线模式使用) */
138
138
  tiandituToken: '63201cfd7df1e1bff7d88bb8baa32151',
139
139
  /** 天地图最小/最大层级 */
140
- tiandituLevelRange: [0, 18],
140
+ tiandituLevelRange: [0, 21],
141
141
  /** 默认加载的影像图层(服务平台模式生效) */
142
142
  defaultLayers: [
143
143
  { layerName: 'earthland', forMat: 'image/png', min: 0, max: 18, transparency: 0.3 },
@@ -527,7 +527,7 @@ export class GaeaApp {
527
527
  labelStore.ImageExtension = Gaea.ImageExtensionEnum.PNG;
528
528
  labelStore.TK = cfg.tiandituToken;
529
529
  labelStore.Name = '天地图注记';
530
- labelStore.LevelRange = new Gaea.Vector2(9, 15);
530
+ labelStore.LevelRange = new Gaea.Vector2(cfg.tiandituLevelRange[0], cfg.tiandituLevelRange[1]);
531
531
  Gaea.World.Instance.DefaultPyramidTileSet.AddImageStore(labelStore);
532
532
  console.log('天地图注记加载成功');
533
533
 
@@ -603,13 +603,8 @@ export class GaeaApp {
603
603
  { name: 'YPDP0+750', position: { x: 27.220289, y: 120.459753, z: -44 }, rotate: [0, 226, 0], size: [1, 1, 1], show: true, url: 'gltf/大坝断面750.gltf' },
604
604
  { name: 'YPDP0+100', position: { x: 27.223027, y: 120.454653, z: -44 }, rotate: [0, 222, 0], size: [1, 1, 1], show: true, url: 'gltf/大坝断面100.gltf' },
605
605
  { name: 'YPDP0+200', position: { x: 27.222541, y: 120.455453, z: -44 }, rotate: [0, 246, 0], size: [1, 1, 1], show: true, url: 'gltf/大坝断面200.gltf' },
606
- { name: '沿浦水闸', position: { x: 27.222866, y: 120.453113, z: 13.25 }, rotate: [0, -30, 0], size: [1, 1, 1], show: false, url: 'gltf/沿浦水闸.gltf', enablePick: true },
607
606
  { name: '沿浦泵站', position: { x: 27.222001, y: 120.452509, z: 17 }, rotate: [0, -38, 0], size: [1, 1, 1], show: true, url: 'gltf/沿浦泵站.gltf', enablePick: true },
608
- { name: '下在水闸', position: { x: 27.221816, y: 120.445182, z: 20 }, rotate: [0, 0, 0], size: [1, 1, 1], show: false, url: 'gltf/下在水闸.gltf', enablePick: true },
609
607
  { name: '下在海塘纳排闸', position: { x: 27.219978, y: 120.445672, z: 15 }, rotate: [0, 0, 0], size: [1, 1, 1], show: true, url: 'gltf/下在海塘纳排闸.gltf', enablePick: true },
610
- { name: '联盟水闸', position: { x: 27.200462, y: 120.465635, z: 20 }, rotate: [0, 0, 0], size: [1, 1, 1], show: false, url: 'gltf/联盟水闸.gltf', enablePick: true },
611
- { name: '岭尾水闸', position: { x: 27.215762, y: 120.462235, z: 30 }, rotate: [0, -63, 0], size: [1, 1, 1], show: false, url: 'gltf/岭尾水闸.gltf', enablePick: true },
612
- { name: '岭尾新闸', position: { x: 27.210369, y: 120.458532, z: 0.5 }, rotate: [0, -153, 0], size: [1, 1, 1], show: false, url: 'gltf/岭尾新闸.gltf' },
613
608
  { name: '盒子模型', position: { x: 27.241836, y: 120.462750, z: 50 }, rotate: [0, 90, 0], size: [10, 10, 10], show: true, url: 'gltf/box.gltf' },
614
609
  { name: 'YPDP0+600游览模型', position: { x: 27.217433, y: 120.461448, z: 32 }, rotate: [0, 90, 0], size: [1, 1, 1], show: true, url: 'gltf/box.gltf' },
615
610
  { name: 'YPDP0+750游览模型', position: { x: 27.220072, y: 120.459602, z: 30 }, rotate: [0, 90, 0], size: [1, 1, 1], show: true, url: 'gltf/box.gltf' },
@@ -2033,6 +2028,135 @@ export class GaeaApp {
2033
2028
  if (el) el.style.display = 'none'
2034
2029
  })
2035
2030
  };
2031
+
2032
+ // ---- 水面加载 ----
2033
+
2034
+ /**
2035
+ * 加载水面
2036
+ * @param {Object} opts
2037
+ * @param {string} opts.gltfUrl - GLTF 模型路径
2038
+ * @param {Object} opts.Position - { x: 纬度, y: 经度, z: 高程 }
2039
+ * @param {Array<number>} opts.rotate - [tilt, heading, bank] 旋转角度
2040
+ * @param {Array<number>} opts.scale - [sx, sy, sz] 缩放
2041
+ */
2042
+ addWaterHandle = async ({ gltfUrl, Position, rotate, scale }) => {
2043
+ const waterMtl = Gaea.GaeaResourceLoader.Instance.LoadLoaclResource('res://assets/material/river.tres')
2044
+ const material = Gaea.ShaderMaterial.ConvertBy(waterMtl)
2045
+
2046
+ const element = new Gaea.GLTFElement()
2047
+ element.ResourceName = gltfUrl
2048
+ element.GeographyPosition = new Gaea.Vector3(Position.x, Position.y, Position.z)
2049
+
2050
+ element.OnModelInit(() => {
2051
+ const n = element.GetChildCount()
2052
+ for (let i = 0; i < n; i++) {
2053
+ const meshInstance = Gaea.MeshInstance.ConvertBy(element.Root.GetChild(i))
2054
+ const count = meshInstance.Mesh.GetSurfaceCount()
2055
+ for (let j = 0; j < count; j++) {
2056
+ meshInstance.Mesh.SurfaceSetMaterial(j, material)
2057
+ }
2058
+ }
2059
+ element.Scale = new Gaea.Vector3(scale[0], scale[1], scale[2])
2060
+ element.TiltHeadingBank = new Gaea.Vector3(rotate[0], rotate[1], rotate[2])
2061
+
2062
+ Gaea.World.Instance.SetMtlVector3(material, 'uv_scale', new Gaea.Vector3(-7, -7, 1))
2063
+ Gaea.World.Instance.SetMtlFloat(material, 'flow_speed', 0.1)
2064
+ Gaea.World.Instance.SetMtlColor(material, 'color_shallow', new Gaea.Color(0 / 255, 157 / 255, 187 / 255, 1))
2065
+ Gaea.World.Instance.SetMtlColor(material, 'color_deep', new Gaea.Color(0 / 255, 157 / 255, 187 / 255, 1))
2066
+ Gaea.World.Instance.SetMtlFloat(material, 'transparency_clarity', 3)
2067
+ Gaea.World.Instance.SetMtlFloat(material, 'foam_amount', 0.9)
2068
+ })
2069
+
2070
+ Gaea.World.Instance.RenderableObjectList.AddLast(element)
2071
+ return element
2072
+ };
2073
+
2074
+ // ---- 开门动画 ----
2075
+
2076
+ /**
2077
+ * 模型缓动动画(缩放/位移/旋转)
2078
+ * @param {Object} element - GLTF 元素
2079
+ * @param {Object} Scale - 目标缩放 { x, y, z }
2080
+ * @param {Object} Position - 目标位置 { x, y, z }
2081
+ * @param {Object} translation - 模型相对位移 { x, y, z }
2082
+ * @param {number} time - 动画时间(ms)
2083
+ * @param {Object} Door - 门旋转角度 { x, y, z }
2084
+ * @param {number} floor - 门在模型树中的层级索引
2085
+ */
2086
+ tweentest = (element, Scale = {}, Position = {}, translation = {}, time, Door = {}, floor = 0) => {
2087
+ const { Tween, Easing } = window.TWEEN
2088
+
2089
+ if (Object.values(Scale).length) {
2090
+ const scale = { x: element.Scale.x, y: element.Scale.y, z: element.Scale.z }
2091
+ const tweenScale = new Tween(scale)
2092
+ .to(Scale, time)
2093
+ .easing(Easing.Quadratic.InOut)
2094
+ .onUpdate(() => {
2095
+ element.Scale = new Gaea.Vector3(scale.x, scale.y, scale.z)
2096
+ })
2097
+ .start()
2098
+ .onStart(() => { if (Scale.x !== 0.1) element.Visible = true })
2099
+ .onComplete(() => { if (Scale.x === 0.1) element.Visible = false; this.tweenGroup.remove(tweenScale) })
2100
+ this.tweenGroup.add(tweenScale)
2101
+ }
2102
+
2103
+ if (Object.values(Position).length) {
2104
+ const pos = { x: element.GeographyPosition.x, y: element.GeographyPosition.y, z: element.GeographyPosition.z }
2105
+ const tweenPos = new Tween(pos)
2106
+ .to(Position, time)
2107
+ .easing(Easing.Quadratic.InOut)
2108
+ .onUpdate(() => { element.GeographyPosition = new Gaea.Vector3(pos.x, pos.y, pos.z) })
2109
+ .start()
2110
+ .onComplete(() => { this.tweenGroup.remove(tweenPos) })
2111
+ this.tweenGroup.add(tweenPos)
2112
+ }
2113
+
2114
+ if (Object.values(Door).length) {
2115
+ const doorMesh = element.Root.GetChild(floor)
2116
+ const meshInstance = new Gaea.MeshInstance()
2117
+ meshInstance.InstanceID = doorMesh.InstanceID
2118
+ const doorAngle = { x: meshInstance.RotationDegrees.x, y: meshInstance.RotationDegrees.y, z: meshInstance.RotationDegrees.z }
2119
+ const tweenDoor = new Tween(doorAngle)
2120
+ .to(Door, time)
2121
+ .easing(Easing.Quadratic.InOut)
2122
+ .onUpdate(() => { meshInstance.RotationDegrees = new Gaea.Vector3(doorAngle.x, doorAngle.y, doorAngle.z) })
2123
+ .start()
2124
+ .onComplete(() => { this.tweenGroup.remove(tweenDoor) })
2125
+ this.tweenGroup.add(tweenDoor)
2126
+ }
2127
+
2128
+ if (Object.values(translation).length) {
2129
+ const trans = element.Root
2130
+ ? { x: element.Root.Translation.x, y: element.Root.Translation.y, z: element.Root.Translation.z }
2131
+ : { x: element.Translation.x, y: element.Translation.y, z: element.Translation.z }
2132
+ const tweenTrans = new Tween(trans)
2133
+ .to(translation, time)
2134
+ .easing(Easing.Quadratic.InOut)
2135
+ .onUpdate(() => {
2136
+ if (element.Root) element.Root.Translation = new Gaea.Vector3(trans.x, trans.y, trans.z)
2137
+ else element.Translation = new Gaea.Vector3(trans.x, trans.y, trans.z)
2138
+ })
2139
+ .start()
2140
+ .onComplete(() => { this.tweenGroup.remove(tweenTrans) })
2141
+ this.tweenGroup.add(tweenTrans)
2142
+ }
2143
+ };
2144
+
2145
+ // ---- 模型内置动画 ----
2146
+
2147
+ /**
2148
+ * 执行模型内置动画(如开闸/关闸动画)
2149
+ * @param {Object} opts
2150
+ * @param {string} opts.animationPath - 动画路径,如 '沿浦水闸/AnimationPlayer'
2151
+ * @param {string} opts.animationName - 动画名称,如 '开闸'
2152
+ * @param {number} [opts.speed=1.0] - 动画速度
2153
+ * @param {boolean} [opts.isReversePlay=false] - 是否反向播放
2154
+ */
2155
+ executeModelAnimation = ({ animationPath, animationName, speed = 1.0, isReversePlay = false }) => {
2156
+ const node = Gaea.World.Instance.GetNode(animationPath)
2157
+ const nodeAnimate = Gaea.AnimationPlayer.ConvertBy(node)
2158
+ nodeAnimate.Play(animationName, -1, speed, isReversePlay)
2159
+ };
2036
2160
  }
2037
2161
 
2038
2162
  export default GaeaApp;
@@ -41,13 +41,19 @@ export default function gaeaVitePlugin() {
41
41
  name: 'vite-plugin-gaea',
42
42
  enforce: 'pre',
43
43
 
44
- config() {
45
- return {
46
- server: { headers: COEP_HEADERS },
47
- };
48
- },
49
-
50
44
  configureServer(server) {
45
+ // COEP/COOP 头只对非 WebSocket 请求设置,避免破坏 Vite HMR
46
+ server.middlewares.stack.unshift({
47
+ route: '',
48
+ handle: function coepMiddleware(req, res, next) {
49
+ if (req.headers.upgrade) return next(); // 跳过 WebSocket 升级请求
50
+ for (const [key, val] of Object.entries(COEP_HEADERS)) {
51
+ res.setHeader(key, val);
52
+ }
53
+ next();
54
+ },
55
+ });
56
+
51
57
  server.middlewares.stack.unshift({
52
58
  route: '',
53
59
  handle: function gaeaServe(req, res, next) {