@yangyongtao/gaea 1.1.26 → 1.1.27

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.27] - 2026-09-01
4
+
5
+ ### Added
6
+ - 新增 `loadingText` 配置项,可通过 `setConfig({ loadingText })` 自定义引擎加载提示文字(默认 `GAEA 引擎加载中...`)
7
+
3
8
  ## [1.1.19] - 2026-07-13
4
9
 
5
10
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yangyongtao/gaea",
3
- "version": "1.1.26",
3
+ "version": "1.1.27",
4
4
  "description": "Gaea 3D visualization component library - Vue 3 components based on Godot WASM engine. Includes WMTS layer loading, camera view control, Vite plugin auto-injection, etc.",
5
5
  "type": "module",
6
6
  "main": "src/index.cjs",
@@ -105,7 +105,7 @@ function showLoading() {
105
105
  if (document.getElementById('gaea-loading-overlay')) return;
106
106
  const overlay = document.createElement('div');
107
107
  overlay.id = 'gaea-loading-overlay';
108
- overlay.innerHTML = '<div class="gaea-spinner"></div><div class="gaea-text">GAEA 引擎加载中...</div>';
108
+ overlay.innerHTML = `<div class="gaea-spinner"></div><div class="gaea-text">${_config.loadingText}</div>`;
109
109
  document.body.appendChild(overlay);
110
110
  }
111
111
 
@@ -160,6 +160,8 @@ const defaultConfig = {
160
160
  defaultCameraPosition: '27.3680928977018,120.414139621887,0,109379.690132486,0,0',
161
161
  /** 引擎加载进度回调 */
162
162
  onProgress: null,
163
+ /** 引擎加载提示文字 */
164
+ loadingText: 'GAEA 引擎加载中...',
163
165
  /** DataHub API 地址(图层树数据接口),为空则只用默认数据 */
164
166
  dataHubApiUrl: '',
165
167
  /** 是否显示图层树按钮(右上角重置按钮旁边) */
@@ -290,8 +292,6 @@ export class GaeaApp {
290
292
  this._screenIconList = [];
291
293
  this._hiddenCategories = new Set();
292
294
  this._tilesetMap = {}; // 已加载的 3D Tiles 引用,key 为 tileset 名称
293
- this._flattenTool = null; // 压平工具
294
- this._flattenPolygon = null; // 压平多边形元素
295
295
  this._secIsClickArr = [];
296
296
  this._secScreenIconKeyValue = {};
297
297
  this._groundPolygonElements = [];
@@ -630,6 +630,7 @@ export class GaeaApp {
630
630
  { name: '岭尾水闸游览模型', position: { x: 27.215661, y: 120.462325, z: 34 }, rotate: [0, -66, 0], size: [1, 1, 1], show: false, url: 'gltf/box.gltf' },
631
631
  { name: '岭尾新闸游览模型', position: { x: 27.21038, y: 120.458513, z: 4 }, rotate: [0, 30, 0], size: [1, 1, 1], show: false, url: 'gltf/box.gltf' },
632
632
  { name: '盒子模型-yanpu', position: { x: 27.231665, y: 120.456095, z: 48.608 }, rotate: [0, 90, 0], size: [10, 10, 10], show: true, url: 'gltf/box.gltf' },
633
+ { name: '防汛沙袋', position: { x: 27.218723, y: 120.460473, z: 18 }, rotate: [0, 0, 0], size: [1, 1, 1], show: false, url: 'gltf/sanddai.glb' },
633
634
  ];
634
635
 
635
636
  this._gltfCfgMap = {};
@@ -1183,7 +1184,7 @@ export class GaeaApp {
1183
1184
  const tilesetUrl = typeof item === 'string' ? item : item.jsonUrl
1184
1185
  const name = typeof item === 'string' ? '' : (item.tilName || '')
1185
1186
  const height = typeof item === 'string' ? 0 : (item.height || 0)
1186
- const enableFlatten = typeof item === 'object' ? (item.enableFlatten || false) : false
1187
+ const enabledClip = typeof item === 'object' ? (item.enabledClip || false) : false
1187
1188
  const tileset = new Gaea.Gaea3DTileset()
1188
1189
  tileset.Name = name
1189
1190
  tileset.TilesetUrl = tilesetUrl
@@ -1192,7 +1193,7 @@ export class GaeaApp {
1192
1193
  tileset.SkipLevelOfDetail = false
1193
1194
  tileset.IsZUp = true
1194
1195
  tileset.RecalculateNormals = true
1195
- tileset.EnabledFlatten = enableFlatten
1196
+ tileset.EnabledClip = enabledClip
1196
1197
  tileset.BaseUrl = tilesetUrl.slice(0, tilesetUrl.lastIndexOf('/') + 1)
1197
1198
  tileset.InitTileSet(name, tilesetUrl)
1198
1199
  tileset.MaximumMemoryUsage = 512
@@ -1204,109 +1205,352 @@ export class GaeaApp {
1204
1205
  if (name) {
1205
1206
  this._tilesetMap[name] = tileset
1206
1207
  }
1207
- console.log('[GaeaApp] 3D Tiles 已加载:', name || tilesetUrl, height ? `高度: ${height}` : '', enableFlatten ? '(压平已启用)' : '')
1208
+ console.log('[GaeaApp] 3D Tiles 已加载:', name || tilesetUrl, height ? `高度: ${height}` : '', enabledClip ? '(裁剪已启用)' : '')
1208
1209
  return tileset
1209
1210
  };
1210
1211
 
1211
- // ---- 倾斜摄影压平 ----
1212
+ // ---- 倾斜挖方 ----
1212
1213
 
1213
1214
  /**
1214
- * 传入多边形坐标直接对倾斜摄影执行压平
1215
- * @param {Object} opts
1216
- * @param {string} [opts.tilesetName] - 目标 3D Tiles 名称(不传则默认使用第一个已加载的 tileset)
1217
- * @param {Array<{lat: number, lng: number}>} opts.polygon - 多边形顶点坐标数组,会自动闭合
1218
- * @param {number} opts.height - 压平目标高度
1215
+ * 根据多边形坐标裁剪地形(倾斜挖方)
1216
+ * @param {Array<{x: number, y: number, z: number}>} pointList - 多边形顶点坐标数组 [{x: 纬度, y: 经度, z: 高程}, ...]
1217
+ * @param {number} height - 裁剪深度/高度
1218
+ * @param {Function} [callback] - 完成后的回调函数,接收 _Holeitem
1219
+ * @returns {boolean} 是否成功
1219
1220
  * @example
1220
- * app.flatten3DTiles({
1221
- * tilesetName: '沿浦海塘倾斜',
1222
- * polygon: [
1223
- * { lat: 27.2205, lng: 120.456 },
1224
- * { lat: 27.2210, lng: 120.458 },
1225
- * { lat: 27.2195, lng: 120.458 },
1226
- * { lat: 27.2190, lng: 120.456 }
1227
- * ],
1228
- * height: 30
1229
- * })
1221
+ * app.editTerrainTool([
1222
+ * { x: 27.2205, y: 120.456, z: 10 },
1223
+ * { x: 27.2210, y: 120.458, z: 10 },
1224
+ * { x: 27.2195, y: 120.458, z: 10 }
1225
+ * ], 50, (item) => { console.log('挖方完成', item) })
1230
1226
  */
1231
- flatten3DTiles = ({ tilesetName, polygon, height }) => {
1232
- if (!polygon || polygon.length < 3) {
1233
- console.warn('[GaeaApp] flatten3DTiles: polygon 至少需要3个顶点')
1234
- return
1227
+ editTerrainTool = (pointList, height, callback) => {
1228
+ if (!pointList || pointList.length === 0) {
1229
+ console.warn('[GaeaApp] editTerrainTool: pointList 不能为空')
1230
+ return false
1235
1231
  }
1236
1232
 
1237
- // 查找目标 tileset
1238
- let tileset = null
1239
- if (tilesetName) {
1240
- tileset = this._tilesetMap[tilesetName]
1241
- if (!tileset) {
1242
- console.warn(`[GaeaApp] flatten3DTiles: 未找到 tileset "${tilesetName}"`)
1243
- return
1244
- }
1245
- } else {
1246
- const keys = Object.keys(this._tilesetMap)
1247
- if (keys.length === 0) {
1248
- console.warn('[GaeaApp] flatten3DTiles: 没有已加载的 3D Tiles')
1249
- return
1233
+ const Position = pointList.map(point => new Gaea.Vector3(point.x, point.y, point.z))
1234
+
1235
+ // 经纬度 → 笛卡尔坐标
1236
+ const originPoint = pointList.map(p => Gaea.GaeaMath.SphericalToCartesianDeg(new Gaea.Vector3(p.x, p.y, p.z)))
1237
+
1238
+ // 启用 QueryServer
1239
+ Gaea.QueryServer.Instance.Enable = true
1240
+
1241
+ // 清旧挖方
1242
+ if (this._holeItem) {
1243
+ Gaea.ExcavationManager.Instance.RemoveItem(this._holeItem)
1244
+ }
1245
+
1246
+ // 创建挖方对象 (坐标点, 插值距离, 深度, UV缩放, 是否法线材质, 是否需要edge)
1247
+ this._holeItem = Gaea.ExcavationManager.Instance.CreateItem(originPoint, 100, height, 100, true, true)
1248
+ Gaea.ExcavationManager.Instance.ExposureLength = 0
1249
+ Gaea.ExcavationManager.Instance.AddItem(this._holeItem)
1250
+ Gaea.ExcavationManager.Instance.NeedFence = true
1251
+
1252
+ if (Gaea.QueryServer.Instance != null) {
1253
+ Gaea.ExcavationManager.Instance.FenceHeight = 10
1254
+ const box = Gaea.World.Instance.SimplePolygonGenerater(originPoint, false, false, false, false, Gaea.ExcavationManager.Instance.FenceHeight, 0, 2, Gaea.ExcavationManager.Instance.FenceHeight)
1255
+ Gaea.World.Instance.AddChild(box, false)
1256
+ Gaea.QueryServer.Instance.ClipBox = box
1257
+ }
1258
+
1259
+ console.log('[GaeaApp] 挖方已执行:', `深度: ${height}`, `顶点数: ${pointList.length}`)
1260
+
1261
+ setTimeout(() => {
1262
+ if (typeof callback === 'function') {
1263
+ callback(this._holeItem)
1250
1264
  }
1251
- tileset = this._tilesetMap[keys[0]]
1265
+ }, 1000)
1266
+ };
1267
+
1268
+ /**
1269
+ * 还原地形(清除所有挖方效果)
1270
+ */
1271
+ restoreTerrain = () => {
1272
+ if (this._holeItem) {
1273
+ Gaea.ExcavationManager.Instance.RemoveItem(this._holeItem)
1274
+ this._holeItem = null
1275
+ }
1276
+ Gaea.ExcavationManager.Instance.Clear()
1277
+ Gaea.World.Instance.SetCurrentTool(null)
1278
+ if (Gaea.QueryServer.Instance != null && Gaea.QueryServer.Instance.ClipBox != null) {
1279
+ Gaea.QueryServer.Instance.ClipBox.QueueFree()
1280
+ Gaea.QueryServer.Instance.ClipBox = null
1281
+ }
1282
+ console.log('[GaeaApp] 地形已还原')
1283
+ };
1284
+
1285
+ /**
1286
+ * 监听画布鼠标点击,获取点击位置的经纬度坐标
1287
+ * @example
1288
+ * app.addMouseClick((pos) => {
1289
+ * console.log('点击位置:', pos) // { x: 纬度, y: 经度, z: 高程 }
1290
+ * })
1291
+ */
1292
+ addMouseClick = (callback) => {
1293
+ const canvas = document.getElementById('canvas')
1294
+ if (!canvas) {
1295
+ console.warn('[GaeaApp] addMouseClick: canvas 元素未找到')
1296
+ return
1252
1297
  }
1298
+ canvas.addEventListener('mousedown', (event) => {
1299
+ const result = Gaea.GaeaMath.ProjectPosition(new Gaea.Vector2(event.offsetX, event.offsetY))
1300
+ const lonlat = Gaea.GaeaMath.CartesianToSphericalDeg(result)
1301
+ const pos = { x: lonlat.x, y: lonlat.y, z: lonlat.z }
1302
+ console.log('[GaeaApp] 点击位置:', pos)
1303
+ if (typeof callback === 'function') {
1304
+ callback(pos)
1305
+ }
1306
+ })
1307
+ };
1253
1308
 
1254
- tileset.EnabledFlatten = true
1309
+ /**
1310
+ * 获取已加载的模型元素
1311
+ * @param {string} name - 模型名称
1312
+ * @returns {object} GLTFElement 或 null
1313
+ */
1314
+ getModel = (name) => {
1315
+ return this._gltfElements[name] || null
1316
+ };
1255
1317
 
1256
- // 创建/更新压平工具
1257
- if (!this._flattenTool) {
1258
- this._flattenTool = new Gaea.FlattenTool()
1259
- this._flattenTool.NeedIntersectWithMesh = false
1260
- this._flattenTool.IsMovingIntersectWithMesh = false
1318
+ /**
1319
+ * 获取模型当前状态(位置、旋转、缩放)
1320
+ * @param {string} name - 模型名称
1321
+ * @returns {object|null} { position, rotate, scale, visible }
1322
+ */
1323
+ getModelInfo = (name) => {
1324
+ const el = this._gltfElements[name]
1325
+ if (!el) return null
1326
+ return {
1327
+ position: { x: el.GeographyPosition.x, y: el.GeographyPosition.y, z: el.GeographyPosition.z },
1328
+ rotate: { x: el.TiltHeadingBank.x, y: el.TiltHeadingBank.y, z: el.TiltHeadingBank.z },
1329
+ scale: { x: el.Root.Scale.x, y: el.Root.Scale.y, z: el.Root.Scale.z },
1330
+ visible: el.Root.Visible,
1261
1331
  }
1262
- this._flattenTool.Gdtvalue = height
1332
+ };
1263
1333
 
1264
- // 构建多边形坐标(经纬度 → Vector3,闭合多边形)
1265
- const positions = polygon.map(p => new Gaea.Vector3(p.lat, p.lng, height))
1266
- positions.push(new Gaea.Vector3(polygon[0].lat, polygon[0].lng, height))
1334
+ /**
1335
+ * 设置模型位置(经纬度 + 高程)
1336
+ * @param {string} name - 模型名称
1337
+ * @param {object} position - { x: 纬度, y: 经度, z: 高程 }
1338
+ */
1339
+ setModelPosition = (name, position) => {
1340
+ const el = this._gltfElements[name]
1341
+ if (!el) { console.warn(`[GaeaApp] 模型 "${name}" 未找到`); return }
1342
+ el.GeographyPosition = new Gaea.Vector3(position.x, position.y, position.z)
1343
+ };
1267
1344
 
1268
- // 创建几何体
1269
- const geometry = Gaea.Geometry.Create1(Gaea.GeometryType.Polygon, positions)
1270
- const polygonElement = new Gaea.PolygonGeometryElement()
1271
- polygonElement.Shape = geometry
1272
- polygonElement.EnablePick = false
1273
- polygonElement.EnableEdit = false
1274
- polygonElement.NeedIntersectWithMesh = true
1275
- polygonElement.EnableVirtualPoint = true
1276
- Gaea.SimpleFillSymbol.ConvertBy(polygonElement.Symbol).HasOutLine = true
1345
+ /**
1346
+ * 设置模型旋转
1347
+ * @param {string} name - 模型名称
1348
+ * @param {number[]} rotate - [pitch, yaw, roll]
1349
+ */
1350
+ setModelRotation = (name, rotate) => {
1351
+ const el = this._gltfElements[name]
1352
+ if (!el) { console.warn(`[GaeaApp] 模型 "${name}" 未找到`); return }
1353
+ el.TiltHeadingBank = new Gaea.Vector3(rotate[0], rotate[1], rotate[2])
1354
+ };
1355
+
1356
+ /**
1357
+ * 设置模型缩放
1358
+ * @param {string} name - 模型名称
1359
+ * @param {number[]} size - [sx, sy, sz]
1360
+ */
1361
+ setModelScale = (name, size) => {
1362
+ const el = this._gltfElements[name]
1363
+ if (!el) { console.warn(`[GaeaApp] 模型 "${name}" 未找到`); return }
1364
+ el.Root.Scale = new Gaea.Vector3(size[0], size[1], size[2])
1365
+ };
1277
1366
 
1278
- // 移除旧的压平多边形
1279
- if (this._flattenPolygon) {
1280
- try { Gaea.World.Instance.RenderableObjectList.RemoveChild(this._flattenPolygon) } catch (e) { /* ignore */ }
1367
+ /**
1368
+ * 设置模型可见性
1369
+ * @param {string} name - 模型名称
1370
+ * @param {boolean} visible
1371
+ */
1372
+ setModelVisible = (name, visible) => {
1373
+ const el = this._gltfElements[name]
1374
+ if (!el) { console.warn(`[GaeaApp] 模型 "${name}" 未找到`); return }
1375
+ el.Root.Visible = visible
1376
+ };
1377
+
1378
+ /**
1379
+ * 移除模型(参考 ht_3dview removeGltf)
1380
+ * @param {string} name - 模型名称
1381
+ */
1382
+ removeGltf = (name) => {
1383
+ const el = this._gltfElements[name]
1384
+ if (!el) { console.warn(`[GaeaApp] 模型 "${name}" 未找到`); return }
1385
+ Gaea.World.Instance.RenderableObjectList.Remove(el)
1386
+ delete this._gltfElements[name]
1387
+ delete this._gltfCfgMap[name]
1388
+ };
1389
+
1390
+ /**
1391
+ * 修改模型配置(位置/旋转/缩放一起设置,参考 ht_3dview updateElementPosition)
1392
+ * @param {object} options
1393
+ * @param {string} options.name - 模型名称
1394
+ * @param {object} options.position - { x: 纬度, y: 经度, z: 高程 }
1395
+ * @param {number[]} [options.rotate] - [pitch, yaw, roll]
1396
+ * @param {number[]} [options.size] - [sx, sy, sz]
1397
+ */
1398
+ updateElementPosition = ({ name, position, rotate, size }) => {
1399
+ const el = this._gltfElements[name]
1400
+ if (!el) { console.warn(`[GaeaApp] 模型 "${name}" 未找到`); return }
1401
+ if (position) {
1402
+ el.GeographyPosition = new Gaea.Vector3(position.x, position.y, position.z)
1403
+ }
1404
+ if (rotate && rotate.length > 0) {
1405
+ el.TiltHeadingBank = new Gaea.Vector3(rotate[0], rotate[1], rotate[2])
1281
1406
  }
1407
+ if (size && size.length > 0) {
1408
+ el.Root.Scale = new Gaea.Vector3(size[0], size[1], size[2])
1409
+ }
1410
+ };
1282
1411
 
1283
- Gaea.World.Instance.RenderableObjectList.AddLast(polygonElement)
1284
- this._flattenPolygon = polygonElement
1285
- console.log('[GaeaApp] 压平已执行:', tileset.Name || tileset.TilesetUrl, `高度: ${height}`, `顶点数: ${polygon.length}`)
1412
+ /**
1413
+ * 添加鼠标移动监听(参考 ht_3dview addMouseMove,使用 Gaea 引擎事件)
1414
+ * 回调返回当前鼠标所在位置的经纬度坐标
1415
+ * @param {function} cb - (pos: {x,y,z}) => void
1416
+ * @returns {function} 调用可取消监听
1417
+ */
1418
+ addMouseMove = (cb = null) => {
1419
+ const handle = Gaea.World.Instance.OnMouseMove((p, b) => {
1420
+ const screenpos = new Gaea.Vector2(p.x, p.y)
1421
+ const spacepos = Gaea.GaeaMath.ProjectPosition(screenpos)
1422
+ const latlonalt = Gaea.GaeaMath.CartesianToSphericalDeg(spacepos)
1423
+ const pos = { x: latlonalt.x, y: latlonalt.y, z: latlonalt.z }
1424
+ if (typeof cb === 'function') cb(pos)
1425
+ })
1426
+ this._mouseMoveHandle = handle
1427
+ return () => {
1428
+ if (handle) Gaea.World.Instance.ClearEvent(handle)
1429
+ this._mouseMoveHandle = null
1430
+ }
1286
1431
  };
1287
1432
 
1288
1433
  /**
1289
- * 清除倾斜摄影压平效果
1290
- * @param {string} [tilesetName] - 目标 tileset 名称(不传则清除压平多边形并重置工具)
1434
+ * 移除鼠标移动监听
1291
1435
  */
1292
- clearFlatten = (tilesetName) => {
1293
- // 移除压平多边形
1294
- if (this._flattenPolygon) {
1295
- try { Gaea.World.Instance.RenderableObjectList.RemoveChild(this._flattenPolygon) } catch (e) { /* ignore */ }
1296
- this._flattenPolygon = null
1436
+ removeMouseMove = () => {
1437
+ if (this._mouseMoveHandle) {
1438
+ Gaea.World.Instance.ClearEvent(this._mouseMoveHandle)
1439
+ this._mouseMoveHandle = null
1297
1440
  }
1441
+ };
1298
1442
 
1299
- // 重置压平工具状态
1300
- this._flattenTool = null
1301
- Gaea.World.Instance.SetCurrentTool(null)
1302
- Gaea.World.Instance.CurrentTool = null
1443
+ /**
1444
+ * 添加鼠标抬起监听(参考 ht_3dview,使用 Gaea 引擎 OnMouseUp 事件)
1445
+ * 回调返回点击位置的经纬度坐标
1446
+ * @param {function} cb - (pos: {x,y,z}) => void
1447
+ * @returns {function} 调用可取消监听
1448
+ */
1449
+ addMouseUp = (cb = null) => {
1450
+ const handle = Gaea.World.Instance.OnMouseUp((p, b) => {
1451
+ if (b !== 1) return // 仅左键
1452
+ const screenpos = new Gaea.Vector2(p.x, p.y)
1453
+ const spacepos = Gaea.GaeaMath.ProjectPosition(screenpos)
1454
+ const latlonalt = Gaea.GaeaMath.CartesianToSphericalDeg(spacepos)
1455
+ const pos = { x: latlonalt.x, y: latlonalt.y, z: latlonalt.z }
1456
+ if (typeof cb === 'function') cb(pos)
1457
+ })
1458
+ this._mouseUpHandle = handle
1459
+ return () => {
1460
+ if (handle) Gaea.World.Instance.ClearEvent(handle)
1461
+ this._mouseUpHandle = null
1462
+ }
1463
+ };
1303
1464
 
1304
- // 可选:禁用特定 tileset 的压平
1305
- if (tilesetName && this._tilesetMap[tilesetName]) {
1306
- this._tilesetMap[tilesetName].EnabledFlatten = false
1465
+ /**
1466
+ * 移除鼠标抬起监听
1467
+ */
1468
+ removeMouseUp = () => {
1469
+ if (this._mouseUpHandle) {
1470
+ Gaea.World.Instance.ClearEvent(this._mouseUpHandle)
1471
+ this._mouseUpHandle = null
1307
1472
  }
1473
+ };
1308
1474
 
1309
- console.log('[GaeaApp] 压平效果已清除')
1475
+ /**
1476
+ * 交互式拾取坐标(点击地图获取经纬度,参考 ht_3dview 选择坐标流程)
1477
+ * 点击地图后回调返回坐标,自动取消监听
1478
+ * @param {function} cb - (pos: {x,y,z}) => void
1479
+ * @returns {function} 调用可取消拾取
1480
+ */
1481
+ pickPosition = (cb) => {
1482
+ const cancel = this.addMouseUp((pos) => {
1483
+ cancel()
1484
+ if (typeof cb === 'function') cb(pos)
1485
+ })
1486
+ return cancel
1487
+ };
1488
+
1489
+ /**
1490
+ * 交互式拾取模型,返回模型信息
1491
+ * @param {function} callback - (modelInfo) => void
1492
+ * @returns {function} 调用可取消拾取
1493
+ */
1494
+ pickModel = (callback) => {
1495
+ const canvas = document.getElementById('canvas')
1496
+ if (!canvas) return () => {}
1497
+
1498
+ const onClick = (event) => {
1499
+ const hit = Gaea.World.Instance.Pick(new Gaea.Vector2(event.offsetX, event.offsetY))
1500
+ if (hit && hit.Element && hit.Element.Root) {
1501
+ const modelName = hit.Element.Root.Name
1502
+ const info = this.getModelInfo(modelName)
1503
+ if (info) {
1504
+ info.name = modelName
1505
+ callback(info)
1506
+ }
1507
+ }
1508
+ }
1509
+
1510
+ canvas.addEventListener('click', onClick)
1511
+ return () => canvas.removeEventListener('click', onClick)
1512
+ };
1513
+
1514
+ /**
1515
+ * 获取所有可选模型列表(用于面板下拉选择,参考 ht_3dview gaeaData.gltfList)
1516
+ * @returns {Array<{name: string, url: string, position?: object}>}
1517
+ */
1518
+ getGltfList = () => {
1519
+ return Object.values(this._gltfCfgMap).map(cfg => ({
1520
+ name: cfg.name,
1521
+ url: cfg.url,
1522
+ }));
1523
+ };
1524
+
1525
+ /**
1526
+ * 加载用户自定义模型(参考 ht_3dview addGltf)
1527
+ * 新增模型到场景并记录到配置表
1528
+ * @param {object} cfg
1529
+ * @param {string} cfg.name - 模型实例名(不能重复)
1530
+ * @param {string} cfg.url - 模型 URL
1531
+ * @param {object} cfg.position - { x: 纬度, y: 经度, z: 高程 }
1532
+ * @param {number[]} cfg.rotate - [pitch, yaw, roll]
1533
+ * @param {number[]} cfg.size - [sx, sy, sz]
1534
+ * @param {boolean} [cfg.show=true]
1535
+ * @param {boolean} [cfg.enablePick=true]
1536
+ * @returns {Promise<object>} gltf element
1537
+ */
1538
+ addGltf = async (cfg) => {
1539
+ const { name, url, position, rotate, size, show = true, enablePick = true } = cfg;
1540
+ if (!name || !url || !position || !rotate || !size) {
1541
+ console.warn('[GaeaApp] addGltf: 缺少必要参数', cfg);
1542
+ return null;
1543
+ }
1544
+ // 记录到配置表,供后续面板编辑
1545
+ this._gltfCfgMap[name] = {
1546
+ name, url, position: { ...position }, rotate: [...rotate], size: [...size],
1547
+ show, enablePick, isUserAdd: true
1548
+ };
1549
+ const element = await this.AddGltf({
1550
+ name, url, position, rotate, size, show, enablePick, useAbsoluteHeight: true,
1551
+ });
1552
+ if (element) this._gltfElements[name] = element;
1553
+ return element;
1310
1554
  };
1311
1555
 
1312
1556
  /**
@@ -2195,8 +2439,9 @@ export class GaeaApp {
2195
2439
  Gaea.World.Instance.SetMtlFloat(material, 'flow_speed', flowSpeed)
2196
2440
  Gaea.World.Instance.SetMtlColor(material, 'color_shallow', new Gaea.Color(0 / 255, 157 / 255, 187 / 255, 1))
2197
2441
  Gaea.World.Instance.SetMtlColor(material, 'color_deep', new Gaea.Color(colorDeep[0] / 255, colorDeep[1] / 255, colorDeep[2] / 255, 1))
2198
- Gaea.World.Instance.SetMtlFloat(material, 'transparency_clarity', 3)
2199
- Gaea.World.Instance.SetMtlFloat(material, 'foam_amount', 0.9)
2442
+ Gaea.World.Instance.SetMtlFloat(material, 'transparency_clarity', 0)
2443
+ Gaea.World.Instance.SetMtlFloat(material, "transparency_refraction", 0); // 折射度
2444
+ Gaea.World.Instance.SetMtlFloat(material, "foam_amount", 0.8); // 气泡大小
2200
2445
  })
2201
2446
 
2202
2447
  Gaea.World.Instance.RenderableObjectList.AddLast(element)