add flood swe module and 2km building bundles

This commit is contained in:
2026-02-04 01:05:20 +01:00
parent 2c77c0d215
commit ff5af7a63a
57 changed files with 5369 additions and 44 deletions

View File

@@ -15,6 +15,7 @@ public class GeoTilePrefabImporter : EditorWindow
private string tilesCsvPath = "Assets/GeoData/tile_index.csv";
private string heightmapsDir = "Assets/GeoData/height_png16";
private string orthoDir = "Assets/GeoData/ortho_jpg";
private string orthoDirFallback = "Assets/GeoData/ortho_jpg_river";
private string buildingsDir = "Assets/GeoData/buildings_tiles";
private string treesDir = "Assets/GeoData/trees_tiles";
private string furnitureDir = "Assets/GeoData/street_furniture";
@@ -23,6 +24,9 @@ public class GeoTilePrefabImporter : EditorWindow
// Output settings
private string prefabOutputDir = "Assets/TilePrefabs";
private bool overwriteExisting = false;
private string buildingPrefabsDir = "Assets/TilePrefabs_Buildings";
private bool exportBuildingPrefabs = true;
private bool overwriteBuildingPrefabs = false;
// Terrain settings
private float tileSizeMeters = 1000f;
@@ -31,6 +35,7 @@ public class GeoTilePrefabImporter : EditorWindow
// Component toggles
private bool applyOrthoTextures = true;
private bool includeBuildings = true;
private bool includeBuildingsEvenTilesOnly = true;
private bool includeTrees = true;
private bool includeFurniture = false;
private bool includeEnhancedTrees = false;
@@ -87,7 +92,8 @@ public class GeoTilePrefabImporter : EditorWindow
GUILayout.Label("Input Paths", EditorStyles.boldLabel);
tilesCsvPath = EditorGUILayout.TextField("tile_index.csv", tilesCsvPath);
heightmapsDir = EditorGUILayout.TextField("height_png16 dir", heightmapsDir);
orthoDir = EditorGUILayout.TextField("ortho_jpg dir", orthoDir);
orthoDir = EditorGUILayout.TextField("ortho_jpg dir (primary)", orthoDir);
orthoDirFallback = EditorGUILayout.TextField("ortho_jpg dir (fallback)", orthoDirFallback);
buildingsDir = EditorGUILayout.TextField("buildings_tiles dir", buildingsDir);
treesDir = EditorGUILayout.TextField("trees_tiles dir", treesDir);
furnitureDir = EditorGUILayout.TextField("street_furniture dir", furnitureDir);
@@ -97,6 +103,9 @@ public class GeoTilePrefabImporter : EditorWindow
GUILayout.Label("Output Settings", EditorStyles.boldLabel);
prefabOutputDir = EditorGUILayout.TextField("Prefab output dir", prefabOutputDir);
overwriteExisting = EditorGUILayout.ToggleLeft("Overwrite existing prefabs", overwriteExisting);
buildingPrefabsDir = EditorGUILayout.TextField("Building prefab output dir", buildingPrefabsDir);
exportBuildingPrefabs = EditorGUILayout.ToggleLeft("Export building-only prefabs (2km blocks)", exportBuildingPrefabs);
overwriteBuildingPrefabs = EditorGUILayout.ToggleLeft("Overwrite building prefabs", overwriteBuildingPrefabs);
GUILayout.Space(10);
GUILayout.Label("Terrain Settings", EditorStyles.boldLabel);
@@ -107,6 +116,7 @@ public class GeoTilePrefabImporter : EditorWindow
GUILayout.Label("Include Components", EditorStyles.boldLabel);
applyOrthoTextures = EditorGUILayout.ToggleLeft("Apply ortho textures", applyOrthoTextures);
includeBuildings = EditorGUILayout.ToggleLeft("Include buildings (GLB)", includeBuildings);
includeBuildingsEvenTilesOnly = EditorGUILayout.ToggleLeft("Include 2km buildings once (even X/Y tiles only)", includeBuildingsEvenTilesOnly);
includeTrees = EditorGUILayout.ToggleLeft("Include trees (GLB chunks)", includeTrees);
includeFurniture = EditorGUILayout.ToggleLeft("Include street furniture (CSV)", includeFurniture);
includeEnhancedTrees = EditorGUILayout.ToggleLeft("Include enhanced trees (CSV)", includeEnhancedTrees);
@@ -249,6 +259,8 @@ public class GeoTilePrefabImporter : EditorWindow
EnsureDirectoryExists(prefabOutputDir);
EnsureDirectoryExists($"{prefabOutputDir}/TerrainData");
EnsureDirectoryExists($"{prefabOutputDir}/TerrainLayers");
if (exportBuildingPrefabs)
EnsureDirectoryExists(buildingPrefabsDir);
// Parse CSV
RefreshTileIndexCache();
@@ -269,6 +281,7 @@ public class GeoTilePrefabImporter : EditorWindow
Debug.Log($"[GeoTilePrefabImporter] Found {selectedTiles.Count} tiles to process.");
int created = 0, skipped = 0, failed = 0;
int buildingsCreated = 0, buildingsSkipped = 0, buildingsFailed = 0;
for (int i = 0; i < selectedTiles.Count; i++)
{
@@ -279,19 +292,33 @@ public class GeoTilePrefabImporter : EditorWindow
(float)i / selectedTiles.Count);
string prefabPath = $"{prefabOutputDir}/{tile.TileId}.prefab";
if (File.Exists(prefabPath) && !overwriteExisting)
bool skipTerrain = File.Exists(prefabPath) && !overwriteExisting;
if (skipTerrain)
{
Debug.Log($"[GeoTilePrefabImporter] Skipping existing: {tile.TileId}");
Debug.Log($"[GeoTilePrefabImporter] Skipping existing terrain prefab: {tile.TileId}");
skipped++;
continue;
}
try
{
if (CreateTilePrefab(tile))
created++;
else
failed++;
if (!skipTerrain)
{
if (CreateTilePrefab(tile))
created++;
else
failed++;
}
if (exportBuildingPrefabs)
{
var result = CreateBuildingPrefab(tile);
if (result == BuildResult.Created)
buildingsCreated++;
else if (result == BuildResult.Skipped)
buildingsSkipped++;
else
buildingsFailed++;
}
}
catch (Exception e)
{
@@ -304,7 +331,8 @@ public class GeoTilePrefabImporter : EditorWindow
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"[GeoTilePrefabImporter] DONE. Created={created}, Skipped={skipped}, Failed={failed}");
Debug.Log($"[GeoTilePrefabImporter] DONE. Created={created}, Skipped={skipped}, Failed={failed}" +
(exportBuildingPrefabs ? $", Buildings Created={buildingsCreated}, Skipped={buildingsSkipped}, Failed={buildingsFailed}" : ""));
}
private void RefreshTileIndexCache()
@@ -618,6 +646,21 @@ public class GeoTilePrefabImporter : EditorWindow
public int Y;
}
private static bool ShouldIncludeBuildings(TileMetadata tile, bool evenTilesOnly)
{
if (!evenTilesOnly)
return true;
return (tile.XKey % 2 == 0) && (tile.YKey % 2 == 0);
}
private enum BuildResult
{
Created,
Skipped,
Failed
}
private bool CreateTilePrefab(TileMetadata tile)
{
// Validate height range
@@ -736,9 +779,53 @@ public class GeoTilePrefabImporter : EditorWindow
return true;
}
private BuildResult CreateBuildingPrefab(TileMetadata tile)
{
if (!exportBuildingPrefabs)
return BuildResult.Skipped;
if (!ShouldIncludeBuildings(tile, includeBuildingsEvenTilesOnly))
return BuildResult.Skipped;
string glbPath = Path.Combine(buildingsDir, $"{tile.TileId}.glb").Replace("\\", "/");
if (!File.Exists(glbPath))
return BuildResult.Skipped;
string prefabPath = $"{buildingPrefabsDir}/{tile.TileId}.prefab";
if (File.Exists(prefabPath))
{
if (!overwriteBuildingPrefabs)
return BuildResult.Skipped;
AssetDatabase.DeleteAsset(prefabPath);
}
var root = new GameObject(tile.TileId);
var metadata = root.AddComponent<GeoTileMetadata>();
metadata.tileKey = tile.TileKey;
metadata.tileId = tile.TileId;
metadata.xmin = tile.Xmin;
metadata.ymin = tile.Ymin;
metadata.globalMin = tile.GlobalMin;
metadata.globalMax = tile.GlobalMax;
metadata.tileMin = tile.TileMin;
metadata.tileMax = tile.TileMax;
AddBuildings(root, tile);
PrefabUtility.SaveAsPrefabAsset(root, prefabPath);
Debug.Log($"[GeoTilePrefabImporter] Created building prefab: {prefabPath}");
DestroyImmediate(root);
return BuildResult.Created;
}
private void ApplyOrthoTexture(TerrainData terrainData, string tileId)
{
string orthoPath = Path.Combine(orthoDir, $"{tileId}.jpg").Replace("\\", "/");
if (!File.Exists(orthoPath) && !string.IsNullOrWhiteSpace(orthoDirFallback))
{
string fallbackPath = Path.Combine(orthoDirFallback, $"{tileId}.jpg").Replace("\\", "/");
if (File.Exists(fallbackPath))
orthoPath = fallbackPath;
}
if (!File.Exists(orthoPath))
{
Debug.LogWarning($"[GeoTilePrefabImporter] Ortho texture missing for {tileId}: {orthoPath}");
@@ -779,6 +866,9 @@ public class GeoTilePrefabImporter : EditorWindow
private void AddBuildings(GameObject root, TileMetadata tile)
{
if (!ShouldIncludeBuildings(tile, includeBuildingsEvenTilesOnly))
return;
string glbPath = Path.Combine(buildingsDir, $"{tile.TileId}.glb").Replace("\\", "/");
if (!File.Exists(glbPath))
return;