@yangyongtao/gaea 1.1.23 → 1.1.25

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yangyongtao/gaea",
3
- "version": "1.1.23",
3
+ "version": "1.1.25",
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",
@@ -164,6 +164,8 @@ const defaultConfig = {
164
164
  dataHubApiUrl: '',
165
165
  /** 是否显示图层树按钮(右上角重置按钮旁边) */
166
166
  showLayerTreeBtn: false,
167
+ /** 默认隐藏的分类 key 列表,如 ['rainStations', 'rescue'] */
168
+ defaultHiddenCategories: [],
167
169
  /** 图层树分类数据(默认数据,接口数据会合并进来) */
168
170
  layerCategories: [
169
171
  { key: 'seawall', text: '海塘', visible: true, children: [
@@ -287,6 +289,8 @@ export class GaeaApp {
287
289
  this.layerCategories = this.config.layerCategories || [];
288
290
  this._screenIconList = [];
289
291
  this._hiddenCategories = new Set();
292
+ this._tilesetMap = {}; // 已加载的 3D Tiles 引用,key 为 tileset 名称
293
+ this._flattenTool = null; // 压平绘制工具
290
294
  this._secIsClickArr = [];
291
295
  this._secScreenIconKeyValue = {};
292
296
  this._groundPolygonElements = [];
@@ -401,6 +405,14 @@ export class GaeaApp {
401
405
  // 8. 初始化屏幕图标
402
406
  this._initScreenIcons();
403
407
 
408
+ // 应用默认隐藏的分类
409
+ const hiddenCats = this.config.defaultHiddenCategories || []
410
+ hiddenCats.forEach(key => {
411
+ const cat = this.layerCategories.find(c => c.key === key)
412
+ if (cat) cat.visible = false
413
+ this.setCategoryVisible(key, false)
414
+ })
415
+
404
416
  console.log('[GaeaApp] 后台资源加载完成');
405
417
  } catch (e) {
406
418
  console.error('[GaeaApp] 后台资源加载出错:', e);
@@ -1170,6 +1182,7 @@ export class GaeaApp {
1170
1182
  const tilesetUrl = typeof item === 'string' ? item : item.jsonUrl
1171
1183
  const name = typeof item === 'string' ? '' : (item.tilName || '')
1172
1184
  const height = typeof item === 'string' ? 0 : (item.height || 0)
1185
+ const enableFlatten = typeof item === 'object' ? (item.enableFlatten || false) : false
1173
1186
  const tileset = new Gaea.Gaea3DTileset()
1174
1187
  tileset.Name = name
1175
1188
  tileset.TilesetUrl = tilesetUrl
@@ -1178,6 +1191,7 @@ export class GaeaApp {
1178
1191
  tileset.SkipLevelOfDetail = false
1179
1192
  tileset.IsZUp = true
1180
1193
  tileset.RecalculateNormals = true
1194
+ tileset.EnabledFlatten = enableFlatten
1181
1195
  tileset.BaseUrl = tilesetUrl.slice(0, tilesetUrl.lastIndexOf('/') + 1)
1182
1196
  tileset.InitTileSet(name, tilesetUrl)
1183
1197
  tileset.MaximumMemoryUsage = 512
@@ -1186,10 +1200,75 @@ export class GaeaApp {
1186
1200
  tileset.LocalOffset = new Gaea.Vector3(0, height, 0)
1187
1201
  }
1188
1202
  Gaea.World.Instance.RenderableObjectList.AddLast(tileset)
1189
- console.log('[GaeaApp] 3D Tiles 已加载:', name || tilesetUrl, height ? `高度: ${height}` : '')
1203
+ if (name) {
1204
+ this._tilesetMap[name] = tileset
1205
+ }
1206
+ console.log('[GaeaApp] 3D Tiles 已加载:', name || tilesetUrl, height ? `高度: ${height}` : '', enableFlatten ? '(压平已启用)' : '')
1190
1207
  return tileset
1191
1208
  };
1192
1209
 
1210
+ // ---- 倾斜摄影压平 ----
1211
+
1212
+ /**
1213
+ * 进入倾斜摄影压平绘制模式
1214
+ * 调用后可以在 3D Tiles 上绘制多边形,多边形区域内将被压平
1215
+ * @param {string} [tilesetName] - 目标 3D Tiles 名称(不传则默认使用第一个已加载的 tileset)
1216
+ */
1217
+ startFlattenDraw = (tilesetName) => {
1218
+ // 查找目标 tileset
1219
+ let tileset = null
1220
+ if (tilesetName) {
1221
+ tileset = this._tilesetMap[tilesetName]
1222
+ if (!tileset) {
1223
+ console.warn(`[GaeaApp] startFlattenDraw: 未找到 tileset "${tilesetName}"`)
1224
+ return
1225
+ }
1226
+ } else {
1227
+ // 取第一个有名字的 tileset
1228
+ const keys = Object.keys(this._tilesetMap)
1229
+ if (keys.length === 0) {
1230
+ console.warn('[GaeaApp] startFlattenDraw: 没有已加载的 3D Tiles')
1231
+ return
1232
+ }
1233
+ tileset = this._tilesetMap[keys[0]]
1234
+ }
1235
+
1236
+ tileset.EnabledFlatten = true
1237
+
1238
+ if (!this._flattenTool) {
1239
+ this._flattenTool = new Gaea.FlattenTool()
1240
+ this._flattenTool.NeedIntersectWithMesh = false
1241
+ this._flattenTool.IsMovingIntersectWithMesh = false
1242
+ }
1243
+
1244
+ Gaea.World.Instance.SetCurrentTool(this._flattenTool)
1245
+ Gaea.World.Instance.CurrentTool = this._flattenTool
1246
+ console.log('[GaeaApp] 压平绘制模式已启动:', tileset.Name || tileset.TilesetUrl)
1247
+ };
1248
+
1249
+ /**
1250
+ * 设置压平高度
1251
+ * @param {number} height - 压平目标高度
1252
+ */
1253
+ setFlattenHeight = (height) => {
1254
+ if (!this._flattenTool) {
1255
+ console.warn('[GaeaApp] setFlattenHeight: 尚未启用压平绘制模式,请先调用 startFlattenDraw()')
1256
+ return
1257
+ }
1258
+ this._flattenTool.Gdtvalue = height
1259
+ console.log('[GaeaApp] 压平高度已设置为:', height)
1260
+ };
1261
+
1262
+ /**
1263
+ * 结束压平绘制模式(保留已绘制的压平效果)
1264
+ */
1265
+ stopFlattenDraw = () => {
1266
+ Gaea.World.Instance.SetCurrentTool(null)
1267
+ Gaea.World.Instance.CurrentTool = null
1268
+ this._flattenTool = null
1269
+ console.log('[GaeaApp] 压平绘制模式已退出')
1270
+ };
1271
+
1193
1272
  /**
1194
1273
  * 根据经纬度飞到指定位置
1195
1274
  * @param {number} lat - 纬度
@@ -1483,7 +1562,14 @@ export class GaeaApp {
1483
1562
  position: { x: lat, y: lng, z },
1484
1563
  method,
1485
1564
  offset,
1486
- onClick,
1565
+ onClick: (clickedName, data) => {
1566
+ // 派发全局自定义事件,父组件可通过 document.addEventListener 监听
1567
+ document.dispatchEvent(new CustomEvent('gaea-marker-click', {
1568
+ detail: { name: clickedName, text: data.text, position: data.position, category },
1569
+ bubbles: true
1570
+ }))
1571
+ if (onClick) onClick(clickedName, data)
1572
+ },
1487
1573
  category,
1488
1574
  type: 'marker'
1489
1575
  })
@@ -2038,8 +2124,14 @@ export class GaeaApp {
2038
2124
  * @param {Object} opts.Position - { x: 纬度, y: 经度, z: 高程 }
2039
2125
  * @param {Array<number>} opts.rotate - [tilt, heading, bank] 旋转角度
2040
2126
  * @param {Array<number>} opts.scale - [sx, sy, sz] 缩放
2127
+ * @param {Array<number>} [opts.colorDeep=[0,157,187]] - 深水区颜色 [r, g, b](0-255)
2128
+ * @param {number} [opts.flowSpeed=0.1] - 流速
2041
2129
  */
2042
- addWaterHandle = async ({ gltfUrl, Position, rotate, scale }) => {
2130
+ addWaterHandle = async ({
2131
+ gltfUrl, Position, rotate, scale,
2132
+ colorDeep = [0, 157, 187],
2133
+ flowSpeed = 0.1
2134
+ }) => {
2043
2135
  const waterMtl = Gaea.GaeaResourceLoader.Instance.LoadLoaclResource('res://assets/material/river.tres')
2044
2136
  const material = Gaea.ShaderMaterial.ConvertBy(waterMtl)
2045
2137
 
@@ -2060,9 +2152,9 @@ export class GaeaApp {
2060
2152
  element.TiltHeadingBank = new Gaea.Vector3(rotate[0], rotate[1], rotate[2])
2061
2153
 
2062
2154
  Gaea.World.Instance.SetMtlVector3(material, 'uv_scale', new Gaea.Vector3(-7, -7, 1))
2063
- Gaea.World.Instance.SetMtlFloat(material, 'flow_speed', 0.1)
2155
+ Gaea.World.Instance.SetMtlFloat(material, 'flow_speed', flowSpeed)
2064
2156
  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))
2157
+ Gaea.World.Instance.SetMtlColor(material, 'color_deep', new Gaea.Color(colorDeep[0] / 255, colorDeep[1] / 255, colorDeep[2] / 255, 1))
2066
2158
  Gaea.World.Instance.SetMtlFloat(material, 'transparency_clarity', 3)
2067
2159
  Gaea.World.Instance.SetMtlFloat(material, 'foam_amount', 0.9)
2068
2160
  })
@@ -44,6 +44,8 @@ import vDrag from '../directives/vDrag.js';
44
44
 
45
45
  const props = defineProps({
46
46
  appInstance: { type: Object, required: true },
47
+ /** 需要隐藏的分类 key 列表 */
48
+ hiddenCategories: { type: Array, default: () => [] }
47
49
  });
48
50
 
49
51
  const emit = defineEmits(['close', 'node-click']);
@@ -78,7 +80,10 @@ function onCategoryToggle(categoryKey, checked) {
78
80
 
79
81
  const filteredData = computed(() => {
80
82
  const kw = searchKey.value.trim().toLowerCase();
81
- return categories.value.map(rootNode => {
83
+ const hidden = new Set(props.hiddenCategories);
84
+ return categories.value
85
+ .filter(rootNode => rootNode.visible !== false && !hidden.has(rootNode.key))
86
+ .map(rootNode => {
82
87
  if (!kw) {
83
88
  rootNode.filteredChildren = rootNode.children || [];
84
89
  return rootNode;