技能主要更新,修复卡顿并加入动画,以及各种其他更新。
This commit is contained in:
@@ -0,0 +1,293 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class UI_FunctionHoverEntry
|
||||
{
|
||||
public string path;
|
||||
[TextArea(2, 6)]
|
||||
public string text;
|
||||
public string iconPath;
|
||||
public Sprite icon;
|
||||
}
|
||||
|
||||
[CreateAssetMenu(menuName = "UI/Function Hover Config", fileName = "UI_FunctionHoverConfig")]
|
||||
public class UI_FunctionHoverConfig : ScriptableObject
|
||||
{
|
||||
public List<UI_FunctionHoverEntry> entries = new List<UI_FunctionHoverEntry>();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[ContextMenu("Import From 素材/指向")]
|
||||
private void ImportFromDefaultFile()
|
||||
{
|
||||
ImportFromFile("素材/指向");
|
||||
}
|
||||
|
||||
[ContextMenu("Import From UI_FunctionHoverConfig.json")]
|
||||
private void ImportFromDefaultJson()
|
||||
{
|
||||
ImportFromJsonFile("Assets/Resources/UI_FunctionHoverConfig.json");
|
||||
}
|
||||
|
||||
public void ImportFromFile(string relativePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(relativePath)) return;
|
||||
string fullPath = Path.Combine(Application.dataPath, "..", relativePath);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
Debug.LogWarning("UI_FunctionHoverConfig: file not found: " + fullPath);
|
||||
return;
|
||||
}
|
||||
|
||||
string content = File.ReadAllText(fullPath, Encoding.UTF8);
|
||||
var parsed = ParseConfig(content);
|
||||
if (parsed.Count > 0)
|
||||
{
|
||||
entries = parsed;
|
||||
EditorUtility.SetDirty(this);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
public void ImportFromJsonFile(string relativePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(relativePath)) return;
|
||||
string fullPath = Path.Combine(Application.dataPath, "..", relativePath);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
Debug.LogWarning("UI_FunctionHoverConfig: json not found: " + fullPath);
|
||||
return;
|
||||
}
|
||||
|
||||
string content = File.ReadAllText(fullPath, Encoding.UTF8);
|
||||
var parsed = ParseJson(content);
|
||||
if (parsed.Count > 0)
|
||||
{
|
||||
entries = parsed;
|
||||
EditorUtility.SetDirty(this);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private static List<UI_FunctionHoverEntry> ParseConfig(string content)
|
||||
{
|
||||
var result = new List<UI_FunctionHoverEntry>();
|
||||
if (string.IsNullOrEmpty(content)) return result;
|
||||
|
||||
var blocks = content.Split(new[] { "\r\n\r\n", "\n\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
string pathLine = null;
|
||||
string textLine = null;
|
||||
string iconLine = null;
|
||||
var lines = block.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line.StartsWith("路径")) pathLine = line;
|
||||
else if (line.StartsWith("文本")) textLine = line;
|
||||
else if (line.StartsWith("显示icon")) iconLine = line;
|
||||
}
|
||||
|
||||
if (pathLine == null || textLine == null) continue;
|
||||
|
||||
string pathsRaw = GetValueAfterColon(pathLine);
|
||||
string text = GetValueAfterColon(textLine);
|
||||
string iconPath = iconLine != null ? GetValueAfterColon(iconLine) : null;
|
||||
|
||||
var paths = SplitPaths(pathsRaw);
|
||||
var icon = LoadIcon(iconPath);
|
||||
foreach (var p in paths)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(p)) continue;
|
||||
result.Add(new UI_FunctionHoverEntry
|
||||
{
|
||||
path = p.Trim(),
|
||||
text = text,
|
||||
iconPath = iconPath,
|
||||
icon = icon
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private class JsonRoot
|
||||
{
|
||||
public List<JsonEntry> entries;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private class JsonEntry
|
||||
{
|
||||
public List<string> paths;
|
||||
public string text;
|
||||
public string icon;
|
||||
}
|
||||
|
||||
private static List<UI_FunctionHoverEntry> ParseJson(string content)
|
||||
{
|
||||
var result = new List<UI_FunctionHoverEntry>();
|
||||
if (string.IsNullOrEmpty(content)) return result;
|
||||
|
||||
JsonRoot root = null;
|
||||
try
|
||||
{
|
||||
root = JsonUtility.FromJson<JsonRoot>(content);
|
||||
}
|
||||
catch
|
||||
{
|
||||
root = null;
|
||||
}
|
||||
|
||||
if (root == null || root.entries == null) return result;
|
||||
|
||||
for (int i = 0; i < root.entries.Count; i++)
|
||||
{
|
||||
var entry = root.entries[i];
|
||||
if (entry == null || entry.paths == null) continue;
|
||||
Sprite icon = LoadIcon(entry.icon);
|
||||
for (int p = 0; p < entry.paths.Count; p++)
|
||||
{
|
||||
var path = entry.paths[p];
|
||||
if (string.IsNullOrWhiteSpace(path)) continue;
|
||||
result.Add(new UI_FunctionHoverEntry
|
||||
{
|
||||
path = path.Trim(),
|
||||
text = entry.text,
|
||||
iconPath = entry.icon,
|
||||
icon = icon
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetValueAfterColon(string line)
|
||||
{
|
||||
int idx = line.IndexOf(':');
|
||||
if (idx < 0) idx = line.IndexOf(':');
|
||||
if (idx < 0) return line.Trim();
|
||||
return line.Substring(idx + 1).Trim();
|
||||
}
|
||||
|
||||
private static string[] SplitPaths(string raw)
|
||||
{
|
||||
if (string.IsNullOrEmpty(raw)) return Array.Empty<string>();
|
||||
string tmp = raw.Replace("和", "|")
|
||||
.Replace("、", "|")
|
||||
.Replace(",", "|")
|
||||
.Replace(",", "|")
|
||||
.Replace(";", "|")
|
||||
.Replace(";", "|");
|
||||
return tmp.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
private static Sprite LoadIcon(string iconPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(iconPath)) return null;
|
||||
string path = NormalizeAssetPath(iconPath);
|
||||
if (!path.StartsWith("Assets", StringComparison.OrdinalIgnoreCase))
|
||||
path = "Assets/" + path;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Sprite direct = TryLoadByPath(path);
|
||||
if (direct != null) return direct;
|
||||
|
||||
string name = Path.GetFileName(path);
|
||||
string folder = Path.GetDirectoryName(path);
|
||||
List<string> searchFolders = new List<string>();
|
||||
if (!string.IsNullOrEmpty(folder) && Directory.Exists(Path.Combine(Application.dataPath, "..", folder)))
|
||||
searchFolders.Add(folder);
|
||||
|
||||
string uiUiFolder = "Assets/artworks/UI_UI";
|
||||
if (Directory.Exists(Path.Combine(Application.dataPath, "..", uiUiFolder)))
|
||||
searchFolders.Add(uiUiFolder);
|
||||
|
||||
string artworksFolder = "Assets/artworks";
|
||||
if (Directory.Exists(Path.Combine(Application.dataPath, "..", artworksFolder)))
|
||||
searchFolders.Add(artworksFolder);
|
||||
|
||||
string[] folders = searchFolders.Count > 0 ? searchFolders.ToArray() : null;
|
||||
var guids = AssetDatabase.FindAssets(name + " t:Sprite", folders);
|
||||
if (guids.Length == 0)
|
||||
guids = AssetDatabase.FindAssets(name + " t:Texture2D", folders);
|
||||
if (guids.Length > 0)
|
||||
{
|
||||
string best = PickBestAssetPath(guids, name, folder);
|
||||
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(best);
|
||||
if (sprite != null) return sprite;
|
||||
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(best);
|
||||
if (tex != null)
|
||||
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
|
||||
}
|
||||
#endif
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string NormalizeAssetPath(string raw)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(raw)) return string.Empty;
|
||||
string path = raw.Replace('>', '/').Replace('\\', '/').Trim();
|
||||
path = path.Replace("Ul_Ul", "UI_UI");
|
||||
path = path.Replace("(", " (").Replace(")", ")");
|
||||
path = path.Replace(" ", " ").Trim();
|
||||
return path;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private static Sprite TryLoadByPath(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path)) return null;
|
||||
string[] candidates = path.IndexOf('.') >= 0
|
||||
? new[] { path }
|
||||
: new[]
|
||||
{
|
||||
path + ".png",
|
||||
path + ".jpg",
|
||||
path + ".jpeg"
|
||||
};
|
||||
|
||||
for (int i = 0; i < candidates.Length; i++)
|
||||
{
|
||||
string p = candidates[i];
|
||||
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(p);
|
||||
if (sprite != null) return sprite;
|
||||
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(p);
|
||||
if (tex != null)
|
||||
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string PickBestAssetPath(string[] guids, string name, string preferredFolder)
|
||||
{
|
||||
if (guids == null || guids.Length == 0) return null;
|
||||
string best = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
if (guids.Length == 1) return best;
|
||||
|
||||
string preferredLower = (preferredFolder ?? string.Empty).Replace('\\', '/').ToLowerInvariant();
|
||||
string uiUiFolder = "assets/artworks/ui_ui";
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
if (string.IsNullOrEmpty(path)) continue;
|
||||
string lower = path.ToLowerInvariant();
|
||||
if (!string.IsNullOrEmpty(preferredLower) && lower.Contains(preferredLower))
|
||||
return path;
|
||||
if (lower.Contains(uiUiFolder))
|
||||
best = path;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user