260 lines
10 KiB
C#
260 lines
10 KiB
C#
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace Logic.Editor
|
|
{
|
|
public class VisualSpriteVariantMapEditorWindow : EditorWindow
|
|
{
|
|
private const string DefaultMapAssetPath = "Assets/BundleResources/DataAssets/VisualSpriteVariantMap.asset";
|
|
private const string GridAndResourceAssetPath = "Assets/BundleResources/Export/GridAndResourceDataAssets.asset";
|
|
private const string EyeComfortGroundFolder = "Assets/BundleResources/ArtResources/TH1Grounds/EyeComfort";
|
|
private const string EyeComfortMountainFolder = "Assets/BundleResources/ArtResources/TH1Mountains/EyeComfort";
|
|
private const string EyeComfortForestFolder = "Assets/BundleResources/ArtResources/TH1Forests/EyeComfort";
|
|
private const string GroundGroup = "GridObject/Ground";
|
|
private const string MountainGroup = "GridObject/Mountain";
|
|
private const string ForestGroup = "GridObject/Forest";
|
|
|
|
private VisualSpriteVariantMapAsset _mapAsset;
|
|
private GridAndResourceDataAssets _gridAsset;
|
|
private Vector2 _scroll;
|
|
|
|
[MenuItem("Tools/TH1/Visual Sprite Variant Map")]
|
|
private static void OpenWindow()
|
|
{
|
|
var window = GetWindow<VisualSpriteVariantMapEditorWindow>();
|
|
window.titleContent = new GUIContent("Sprite Variants");
|
|
window.minSize = new Vector2(720, 420);
|
|
window.LoadAssets();
|
|
}
|
|
|
|
[MenuItem("Tools/TH1/Visual Sprite Variant Map/Rebuild Map Feature EyeComfort")]
|
|
private static void RebuildGroundFromMenu()
|
|
{
|
|
var window = CreateInstance<VisualSpriteVariantMapEditorWindow>();
|
|
window.LoadAssets();
|
|
window.RebuildMapFeatureMappings();
|
|
DestroyImmediate(window);
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
LoadAssets();
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
EditorGUILayout.LabelField("Visual Sprite Variant Map", EditorStyles.boldLabel);
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
_mapAsset = (VisualSpriteVariantMapAsset)EditorGUILayout.ObjectField("Map Asset", _mapAsset, typeof(VisualSpriteVariantMapAsset), false);
|
|
if (GUILayout.Button("Create/Load", GUILayout.Width(110)))
|
|
LoadOrCreateMapAsset();
|
|
}
|
|
|
|
_gridAsset = (GridAndResourceDataAssets)EditorGUILayout.ObjectField("Grid Asset", _gridAsset, typeof(GridAndResourceDataAssets), false);
|
|
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
if (GUILayout.Button("Rebuild Map Feature EyeComfort Mappings", GUILayout.Height(28)))
|
|
RebuildMapFeatureMappings();
|
|
if (GUILayout.Button("Select Asset", GUILayout.Width(110), GUILayout.Height(28)) && _mapAsset != null)
|
|
{
|
|
Selection.activeObject = _mapAsset;
|
|
EditorGUIUtility.PingObject(_mapAsset);
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.Space(8);
|
|
|
|
if (_mapAsset == null)
|
|
{
|
|
EditorGUILayout.HelpBox("Create or load VisualSpriteVariantMap.asset first.", MessageType.Info);
|
|
return;
|
|
}
|
|
|
|
int total = _mapAsset.Pairs?.Count ?? 0;
|
|
int mapped = _mapAsset.CountMappedPairs(VisualTheme.EyeComfort);
|
|
EditorGUILayout.LabelField($"Pairs: {total} EyeComfort mapped: {mapped}");
|
|
|
|
var serializedObject = new SerializedObject(_mapAsset);
|
|
var pairsProperty = serializedObject.FindProperty("Pairs");
|
|
_scroll = EditorGUILayout.BeginScrollView(_scroll);
|
|
EditorGUILayout.PropertyField(pairsProperty, true);
|
|
EditorGUILayout.EndScrollView();
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
private void LoadAssets()
|
|
{
|
|
_mapAsset = AssetDatabase.LoadAssetAtPath<VisualSpriteVariantMapAsset>(DefaultMapAssetPath);
|
|
_gridAsset = AssetDatabase.LoadAssetAtPath<GridAndResourceDataAssets>(GridAndResourceAssetPath);
|
|
}
|
|
|
|
private void LoadOrCreateMapAsset()
|
|
{
|
|
_mapAsset = LoadOrCreateMapAsset(DefaultMapAssetPath);
|
|
}
|
|
|
|
private static VisualSpriteVariantMapAsset LoadOrCreateMapAsset(string path)
|
|
{
|
|
var asset = AssetDatabase.LoadAssetAtPath<VisualSpriteVariantMapAsset>(path);
|
|
if (asset != null)
|
|
return asset;
|
|
|
|
var folder = System.IO.Path.GetDirectoryName(path)?.Replace("\\", "/");
|
|
if (!string.IsNullOrEmpty(folder) && !AssetDatabase.IsValidFolder(folder))
|
|
CreateFolders(folder);
|
|
|
|
asset = CreateInstance<VisualSpriteVariantMapAsset>();
|
|
AssetDatabase.CreateAsset(asset, path);
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
return asset;
|
|
}
|
|
|
|
private void RebuildMapFeatureMappings()
|
|
{
|
|
_mapAsset = LoadOrCreateMapAsset(DefaultMapAssetPath);
|
|
if (_gridAsset == null)
|
|
_gridAsset = AssetDatabase.LoadAssetAtPath<GridAndResourceDataAssets>(GridAndResourceAssetPath);
|
|
|
|
if (_gridAsset == null)
|
|
{
|
|
Debug.LogError($"[VisualSpriteVariantMap] Grid asset not found: {GridAndResourceAssetPath}");
|
|
return;
|
|
}
|
|
|
|
Undo.RecordObject(_mapAsset, "Rebuild Map Feature EyeComfort Mappings");
|
|
_mapAsset.Pairs.RemoveAll(pair => pair != null
|
|
&& (pair.Group == GroundGroup
|
|
|| pair.Group == MountainGroup
|
|
|| pair.Group == ForestGroup));
|
|
|
|
int groundMapped = AddMappings(GroundGroup, CollectGroundSprites(_gridAsset), EyeComfortGroundFolder);
|
|
int mountainMapped = AddMappings(MountainGroup, CollectMountainSprites(_gridAsset), EyeComfortMountainFolder);
|
|
int forestMapped = AddMappings(ForestGroup, CollectForestSprites(_gridAsset), EyeComfortForestFolder);
|
|
|
|
_mapAsset.RebuildCache();
|
|
EditorUtility.SetDirty(_mapAsset);
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
Debug.Log($"[VisualSpriteVariantMap] Rebuilt map feature pairs. Ground={groundMapped}, Mountain={mountainMapped}, Forest={forestMapped} matched EyeComfort sprites.");
|
|
}
|
|
|
|
private int AddMappings(string group, List<Sprite> sourceSprites, string replacementFolder)
|
|
{
|
|
var replacementByName = LoadSpritesByName(replacementFolder);
|
|
int mapped = 0;
|
|
foreach (var source in sourceSprites)
|
|
{
|
|
replacementByName.TryGetValue(source.name, out var replacement);
|
|
if (replacement != null)
|
|
mapped++;
|
|
|
|
_mapAsset.Pairs.Add(new VisualSpriteVariantPair
|
|
{
|
|
Group = group,
|
|
Source = source,
|
|
EyeComfort = replacement
|
|
});
|
|
}
|
|
|
|
return mapped;
|
|
}
|
|
|
|
private static List<Sprite> CollectGroundSprites(GridAndResourceDataAssets gridAsset)
|
|
{
|
|
var result = new List<Sprite>();
|
|
var seen = new HashSet<Sprite>();
|
|
|
|
if (gridAsset?.TerrainInfoList == null)
|
|
return result;
|
|
|
|
foreach (var terrain in gridAsset.TerrainInfoList)
|
|
{
|
|
if (terrain == null || terrain.TerrainType != TerrainType.Land)
|
|
continue;
|
|
|
|
AddSprite(result, seen, terrain.Sprite);
|
|
if (terrain.SpriteList == null)
|
|
continue;
|
|
|
|
foreach (var spriteInfo in terrain.SpriteList)
|
|
AddSprite(result, seen, spriteInfo?.Sprite);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static List<Sprite> CollectMountainSprites(GridAndResourceDataAssets gridAsset)
|
|
{
|
|
var result = new List<Sprite>();
|
|
var seen = new HashSet<Sprite>();
|
|
|
|
if (gridAsset?.MountainInfo?.SpriteList == null)
|
|
return result;
|
|
|
|
foreach (var spriteInfo in gridAsset.MountainInfo.SpriteList)
|
|
AddSprite(result, seen, spriteInfo?.Sprite);
|
|
|
|
return result;
|
|
}
|
|
|
|
private static List<Sprite> CollectForestSprites(GridAndResourceDataAssets gridAsset)
|
|
{
|
|
var result = new List<Sprite>();
|
|
var seen = new HashSet<Sprite>();
|
|
|
|
if (gridAsset?.VegetationInfo?.SpriteList == null)
|
|
return result;
|
|
|
|
foreach (var spriteInfo in gridAsset.VegetationInfo.SpriteList)
|
|
AddSprite(result, seen, spriteInfo?.Sprite);
|
|
|
|
return result;
|
|
}
|
|
|
|
private static void AddSprite(List<Sprite> result, HashSet<Sprite> seen, Sprite sprite)
|
|
{
|
|
if (sprite == null || seen.Contains(sprite))
|
|
return;
|
|
|
|
seen.Add(sprite);
|
|
result.Add(sprite);
|
|
}
|
|
|
|
private static Dictionary<string, Sprite> LoadSpritesByName(string folder)
|
|
{
|
|
var result = new Dictionary<string, Sprite>();
|
|
var guids = AssetDatabase.FindAssets("t:Sprite", new[] { folder });
|
|
foreach (var guid in guids)
|
|
{
|
|
var path = AssetDatabase.GUIDToAssetPath(guid);
|
|
var sprites = AssetDatabase.LoadAllAssetsAtPath(path);
|
|
foreach (var asset in sprites)
|
|
{
|
|
if (asset is Sprite sprite && !result.ContainsKey(sprite.name))
|
|
result[sprite.name] = sprite;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static void CreateFolders(string folder)
|
|
{
|
|
var parts = folder.Split('/');
|
|
var current = parts[0];
|
|
for (int i = 1; i < parts.Length; i++)
|
|
{
|
|
var next = $"{current}/{parts[i]}";
|
|
if (!AssetDatabase.IsValidFolder(next))
|
|
AssetDatabase.CreateFolder(current, parts[i]);
|
|
current = next;
|
|
}
|
|
}
|
|
}
|
|
}
|