add flood swe module and 2km building bundles
This commit is contained in:
@@ -12,10 +12,15 @@ using UnityEngine;
|
||||
public static class GeoTileAddressablesBuilder
|
||||
{
|
||||
private const string TilePrefabsDir = "Assets/TilePrefabs";
|
||||
private const string BuildingPrefabsDir = "Assets/TilePrefabs_Buildings";
|
||||
private const string TileIndexCsvPath = "Assets/GeoData/tile_index.csv";
|
||||
private const string GroupName = "TilePrefabs";
|
||||
private const string BuildingGroupName = "TileBuildings";
|
||||
private const string TileLabel = "tile";
|
||||
private const string BuildingLabel = "tile_building";
|
||||
private const string ManifestFileName = "TileManifest.json";
|
||||
private const string BuildingManifestFileName = "TileBuildingsManifest.json";
|
||||
private const string BuildingAddressSuffix = "_bldg";
|
||||
private const float DefaultTileSizeMeters = 1000f;
|
||||
private const float DefaultTileSizeX = 1000f;
|
||||
private const float DefaultTileSizeY = 1000f;
|
||||
@@ -61,6 +66,7 @@ public static class GeoTileAddressablesBuilder
|
||||
{
|
||||
public string TileIndexCsvPath;
|
||||
public string TilePrefabsDir;
|
||||
public string BuildingPrefabsDir;
|
||||
public string OutputRoot;
|
||||
public BuildTarget Target;
|
||||
public BuildTargetGroup TargetGroup;
|
||||
@@ -69,6 +75,8 @@ public static class GeoTileAddressablesBuilder
|
||||
public List<TileRecord> SelectedTiles;
|
||||
public bool OverwriteExisting;
|
||||
public bool Verbose;
|
||||
public bool IncludeBuildingPrefabs;
|
||||
public int BuildingBlockSizeInTiles;
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Geo Tiles/Build (Android)")]
|
||||
@@ -91,6 +99,7 @@ public static class GeoTileAddressablesBuilder
|
||||
{
|
||||
TileIndexCsvPath = TileIndexCsvPath,
|
||||
TilePrefabsDir = TilePrefabsDir,
|
||||
BuildingPrefabsDir = BuildingPrefabsDir,
|
||||
OutputRoot = "ServerData/TileBundles",
|
||||
Target = target,
|
||||
TargetGroup = group,
|
||||
@@ -98,7 +107,9 @@ public static class GeoTileAddressablesBuilder
|
||||
TileKeyConfig = TileKeyConfig.Default,
|
||||
SelectedTiles = null,
|
||||
OverwriteExisting = false,
|
||||
Verbose = false
|
||||
Verbose = false,
|
||||
IncludeBuildingPrefabs = true,
|
||||
BuildingBlockSizeInTiles = 2
|
||||
});
|
||||
}
|
||||
|
||||
@@ -106,8 +117,11 @@ public static class GeoTileAddressablesBuilder
|
||||
{
|
||||
var tileIndexCsvPath = string.IsNullOrWhiteSpace(request.TileIndexCsvPath) ? TileIndexCsvPath : request.TileIndexCsvPath;
|
||||
var tilePrefabsDir = string.IsNullOrWhiteSpace(request.TilePrefabsDir) ? TilePrefabsDir : request.TilePrefabsDir;
|
||||
var buildingPrefabsDir = string.IsNullOrWhiteSpace(request.BuildingPrefabsDir) ? BuildingPrefabsDir : request.BuildingPrefabsDir;
|
||||
var outputRoot = string.IsNullOrWhiteSpace(request.OutputRoot) ? "ServerData/TileBundles" : request.OutputRoot;
|
||||
var tileSizeMeters = request.TileSizeMeters > 0f ? request.TileSizeMeters : DefaultTileSizeMeters;
|
||||
var includeBuildingPrefabs = request.IncludeBuildingPrefabs;
|
||||
var buildingBlockSize = Math.Max(1, request.BuildingBlockSizeInTiles);
|
||||
var tileKeyConfig = request.TileKeyConfig;
|
||||
if (tileKeyConfig.TileSizeX <= 0f && tileKeyConfig.TileSizeY <= 0f &&
|
||||
tileKeyConfig.OverlapX == 0f && tileKeyConfig.OverlapY == 0f)
|
||||
@@ -120,6 +134,11 @@ public static class GeoTileAddressablesBuilder
|
||||
Debug.LogError($"[GeoTileAddressablesBuilder] Prefab directory missing: {tilePrefabsDir}");
|
||||
return false;
|
||||
}
|
||||
if (includeBuildingPrefabs && !Directory.Exists(buildingPrefabsDir))
|
||||
{
|
||||
Debug.LogWarning($"[GeoTileAddressablesBuilder] Building prefab directory missing: {buildingPrefabsDir}. Skipping building bundles.");
|
||||
includeBuildingPrefabs = false;
|
||||
}
|
||||
if (!File.Exists(tileIndexCsvPath))
|
||||
{
|
||||
Debug.LogError($"[GeoTileAddressablesBuilder] CSV missing: {tileIndexCsvPath}");
|
||||
@@ -145,7 +164,7 @@ public static class GeoTileAddressablesBuilder
|
||||
EnsureProfileVariable(settings, LoadPathVariable, LoadPathValue);
|
||||
EnsureRemoteCatalogPaths(settings);
|
||||
|
||||
var groupAsset = GetOrCreateGroup(settings);
|
||||
var groupAsset = GetOrCreateGroup(settings, GroupName);
|
||||
ConfigureGroup(settings, groupAsset);
|
||||
var assignedTileIds = AssignPrefabs(settings, groupAsset, tilePrefabsDir, tiles, true);
|
||||
|
||||
@@ -158,6 +177,18 @@ public static class GeoTileAddressablesBuilder
|
||||
return false;
|
||||
}
|
||||
|
||||
List<TileRecord> buildingTiles = null;
|
||||
if (includeBuildingPrefabs)
|
||||
{
|
||||
var buildingGroup = GetOrCreateGroup(settings, BuildingGroupName);
|
||||
ConfigureGroup(settings, buildingGroup);
|
||||
var anchors = tiles.Where(tile => IsBuildingAnchor(tile, buildingBlockSize)).ToList();
|
||||
var assignedBuildingIds = AssignBuildingPrefabs(settings, buildingGroup, buildingPrefabsDir, anchors, true);
|
||||
buildingTiles = anchors
|
||||
.Where(tile => !string.IsNullOrWhiteSpace(tile.TileId) && assignedBuildingIds.Contains(tile.TileId))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
settings.SetDirty(AddressableAssetSettings.ModificationEvent.BatchModification, null, true);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
@@ -191,14 +222,43 @@ public static class GeoTileAddressablesBuilder
|
||||
return false;
|
||||
}
|
||||
|
||||
var manifest = BuildManifest(request.Target.ToString(), catalogFile, catalogHashFile, filteredTiles, tileSizeMeters);
|
||||
var (originX, originY) = ComputeOrigin(filteredTiles);
|
||||
var manifest = BuildManifest(
|
||||
request.Target.ToString(),
|
||||
catalogFile,
|
||||
catalogHashFile,
|
||||
filteredTiles,
|
||||
tileSizeMeters,
|
||||
ResolveTileKey,
|
||||
originX,
|
||||
originY);
|
||||
var manifestPath = Path.Combine(outputPath, ManifestFileName);
|
||||
File.WriteAllText(manifestPath, JsonUtility.ToJson(manifest, true));
|
||||
|
||||
if (includeBuildingPrefabs && buildingTiles != null && buildingTiles.Count > 0)
|
||||
{
|
||||
var buildingManifest = BuildManifest(
|
||||
request.Target.ToString(),
|
||||
catalogFile,
|
||||
catalogHashFile,
|
||||
buildingTiles,
|
||||
tileSizeMeters,
|
||||
BuildBuildingAddress,
|
||||
originX,
|
||||
originY);
|
||||
var buildingManifestPath = Path.Combine(outputPath, BuildingManifestFileName);
|
||||
File.WriteAllText(buildingManifestPath, JsonUtility.ToJson(buildingManifest, true));
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
if (request.Verbose)
|
||||
Debug.Log($"[GeoTileAddressablesBuilder] Built {filteredTiles.Count} tiles (from {tiles.Count} selected). Output={outputPath}");
|
||||
{
|
||||
var buildingInfo = includeBuildingPrefabs && buildingTiles != null
|
||||
? $", Buildings={buildingTiles.Count}"
|
||||
: "";
|
||||
Debug.Log($"[GeoTileAddressablesBuilder] Built {filteredTiles.Count} tiles (from {tiles.Count} selected){buildingInfo}. Output={outputPath}");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -227,7 +287,7 @@ public static class GeoTileAddressablesBuilder
|
||||
continue;
|
||||
|
||||
var entry = settings.CreateOrMoveEntry(guid, group, false, false);
|
||||
entry.address = tile.TileKey;
|
||||
entry.address = ResolveTileKey(tile);
|
||||
entry.SetLabel(TileLabel, true, true);
|
||||
selectedGuids.Add(guid);
|
||||
assignedTileIds.Add(tileId);
|
||||
@@ -254,13 +314,64 @@ public static class GeoTileAddressablesBuilder
|
||||
return assignedTileIds;
|
||||
}
|
||||
|
||||
private static AddressableAssetGroup GetOrCreateGroup(AddressableAssetSettings settings)
|
||||
private static HashSet<string> AssignBuildingPrefabs(AddressableAssetSettings settings, AddressableAssetGroup group, string prefabsDir, List<TileRecord> tiles, bool removeUnselected)
|
||||
{
|
||||
var group = settings.FindGroup(GroupName);
|
||||
var tileById = new Dictionary<string, TileRecord>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(tile.TileId))
|
||||
tileById[tile.TileId] = tile;
|
||||
}
|
||||
|
||||
var assignedTileIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
var selectedGuids = new HashSet<string>();
|
||||
var prefabGuids = AssetDatabase.FindAssets("t:Prefab", new[] { prefabsDir });
|
||||
foreach (var guid in prefabGuids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid).Replace("\\", "/");
|
||||
var parentDir = Path.GetDirectoryName(path)?.Replace("\\", "/");
|
||||
if (!string.Equals(parentDir, prefabsDir, StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
|
||||
var tileId = Path.GetFileNameWithoutExtension(path);
|
||||
if (!tileById.TryGetValue(tileId, out var tile))
|
||||
continue;
|
||||
|
||||
var entry = settings.CreateOrMoveEntry(guid, group, false, false);
|
||||
entry.address = BuildBuildingAddress(tile);
|
||||
entry.SetLabel(BuildingLabel, true, true);
|
||||
selectedGuids.Add(guid);
|
||||
assignedTileIds.Add(tileId);
|
||||
}
|
||||
|
||||
if (!removeUnselected)
|
||||
return assignedTileIds;
|
||||
|
||||
var entries = group.entries.ToList();
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
if (entry == null || string.IsNullOrWhiteSpace(entry.AssetPath))
|
||||
continue;
|
||||
|
||||
var entryPath = entry.AssetPath.Replace("\\", "/");
|
||||
var entryDir = Path.GetDirectoryName(entryPath)?.Replace("\\", "/");
|
||||
if (!string.Equals(entryDir, prefabsDir, StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
|
||||
if (!selectedGuids.Contains(entry.guid))
|
||||
group.RemoveAssetEntry(entry);
|
||||
}
|
||||
|
||||
return assignedTileIds;
|
||||
}
|
||||
|
||||
private static AddressableAssetGroup GetOrCreateGroup(AddressableAssetSettings settings, string groupName)
|
||||
{
|
||||
var group = settings.FindGroup(groupName);
|
||||
if (group != null)
|
||||
return group;
|
||||
|
||||
group = settings.CreateGroup(GroupName, false, false, false, new List<AddressableAssetGroupSchema>());
|
||||
group = settings.CreateGroup(groupName, false, false, false, new List<AddressableAssetGroupSchema>());
|
||||
group.AddSchema<BundledAssetGroupSchema>();
|
||||
group.AddSchema<ContentUpdateGroupSchema>();
|
||||
return group;
|
||||
@@ -327,17 +438,37 @@ public static class GeoTileAddressablesBuilder
|
||||
}
|
||||
|
||||
private static TileManifest BuildManifest(string buildTarget, string catalogFile, string catalogHashFile, List<TileRecord> tiles, float tileSizeMeters)
|
||||
=> BuildManifest(buildTarget, catalogFile, catalogHashFile, tiles, tileSizeMeters, ResolveTileKey, null, null);
|
||||
|
||||
private static TileManifest BuildManifest(
|
||||
string buildTarget,
|
||||
string catalogFile,
|
||||
string catalogHashFile,
|
||||
List<TileRecord> tiles,
|
||||
float tileSizeMeters,
|
||||
Func<TileRecord, string> keyResolver,
|
||||
double? originX,
|
||||
double? originY)
|
||||
{
|
||||
if (tiles.Count == 0)
|
||||
throw new InvalidOperationException("No tiles selected for TileManifest.");
|
||||
|
||||
double minX = double.PositiveInfinity;
|
||||
double minY = double.PositiveInfinity;
|
||||
|
||||
foreach (var tile in tiles)
|
||||
double minX;
|
||||
double minY;
|
||||
if (originX.HasValue && originY.HasValue)
|
||||
{
|
||||
minX = Math.Min(minX, tile.Xmin);
|
||||
minY = Math.Min(minY, tile.Ymin);
|
||||
minX = originX.Value;
|
||||
minY = originY.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
minX = double.PositiveInfinity;
|
||||
minY = double.PositiveInfinity;
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
minX = Math.Min(minX, tile.Xmin);
|
||||
minY = Math.Min(minY, tile.Ymin);
|
||||
}
|
||||
}
|
||||
|
||||
var entries = new TileEntry[tiles.Count];
|
||||
@@ -346,7 +477,7 @@ public static class GeoTileAddressablesBuilder
|
||||
var tile = tiles[i];
|
||||
entries[i] = new TileEntry
|
||||
{
|
||||
tileKey = tile.TileKey,
|
||||
tileKey = keyResolver(tile),
|
||||
tileId = tile.TileId,
|
||||
offsetX = (float)(tile.Xmin - minX),
|
||||
offsetZ = (float)(tile.Ymin - minY),
|
||||
@@ -366,6 +497,28 @@ public static class GeoTileAddressablesBuilder
|
||||
};
|
||||
}
|
||||
|
||||
private static (double originX, double originY) ComputeOrigin(List<TileRecord> tiles)
|
||||
{
|
||||
double minX = double.PositiveInfinity;
|
||||
double minY = double.PositiveInfinity;
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
minX = Math.Min(minX, tile.Xmin);
|
||||
minY = Math.Min(minY, tile.Ymin);
|
||||
}
|
||||
|
||||
return (minX, minY);
|
||||
}
|
||||
|
||||
private static string ResolveTileKey(TileRecord tile)
|
||||
=> string.IsNullOrWhiteSpace(tile.TileKey) ? tile.TileId : tile.TileKey;
|
||||
|
||||
private static string BuildBuildingAddress(TileRecord tile)
|
||||
=> $"{ResolveTileKey(tile)}{BuildingAddressSuffix}";
|
||||
|
||||
private static bool IsBuildingAnchor(TileRecord tile, int blockSize)
|
||||
=> (tile.XKey % blockSize == 0) && (tile.YKey % blockSize == 0);
|
||||
|
||||
private static string GetRemoteCatalogBuildPath(AddressableAssetSettings settings, BuildTarget target)
|
||||
{
|
||||
var rawPath = settings.RemoteCatalogBuildPath.GetValue(settings);
|
||||
|
||||
Reference in New Issue
Block a user