拼ui 一些业务逻辑x实现
This commit is contained in:
@@ -0,0 +1,282 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using EasyChart;
|
||||
|
||||
namespace EasyChart.Editor
|
||||
{
|
||||
public partial class EasyChartLibraryWindow
|
||||
{
|
||||
private static string _profileClipboardJson;
|
||||
private static string _profileClipboardSourceName;
|
||||
|
||||
private static bool IsChartProfileAsset(string assetPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(assetPath)) return false;
|
||||
if (AssetDatabase.IsValidFolder(assetPath)) return false;
|
||||
if (!assetPath.EndsWith(".asset", StringComparison.OrdinalIgnoreCase)) return false;
|
||||
return AssetDatabase.LoadAssetAtPath<ChartProfile>(assetPath) != null;
|
||||
}
|
||||
|
||||
private static bool HasProfileInClipboard()
|
||||
{
|
||||
return !string.IsNullOrEmpty(_profileClipboardJson);
|
||||
}
|
||||
|
||||
private void CopyProfileToClipboard(string assetPath)
|
||||
{
|
||||
if (!IsChartProfileAsset(assetPath))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Copy", "Please select a ChartProfile asset.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
var profile = AssetDatabase.LoadAssetAtPath<ChartProfile>(assetPath);
|
||||
if (profile == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Copy", "Failed to load ChartProfile.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
_profileClipboardJson = EditorJsonUtility.ToJson(profile);
|
||||
_profileClipboardSourceName = profile.name;
|
||||
}
|
||||
|
||||
private void PasteProfileOverwriteFromClipboard(string targetAssetPath)
|
||||
{
|
||||
if (!HasProfileInClipboard())
|
||||
{
|
||||
EditorUtility.DisplayDialog("Paste", "Clipboard is empty.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsChartProfileAsset(targetAssetPath))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Paste", "Please select a ChartProfile asset to overwrite.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
var target = AssetDatabase.LoadAssetAtPath<ChartProfile>(targetAssetPath);
|
||||
if (target == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Paste", "Failed to load target ChartProfile.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
string srcName = string.IsNullOrEmpty(_profileClipboardSourceName) ? "(Clipboard)" : _profileClipboardSourceName;
|
||||
if (!EditorUtility.DisplayDialog(
|
||||
"Paste (Overwrite)",
|
||||
$"This will overwrite ALL properties of:\n\n {target.name}\n\nwith:\n\n {srcName}\n\nContinue?",
|
||||
"Overwrite",
|
||||
"Cancel"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Undo.RecordObject(target, "Paste ChartProfile");
|
||||
EditorJsonUtility.FromJsonOverwrite(_profileClipboardJson, target);
|
||||
EditorUtility.SetDirty(target);
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
// Refresh UI if we are overwriting current selection
|
||||
if (_selectedProfile == target)
|
||||
{
|
||||
if (_serializedProfile != null)
|
||||
{
|
||||
if (_serializedProfile.hasModifiedProperties) _serializedProfile.ApplyModifiedProperties();
|
||||
_serializedProfile.Update();
|
||||
}
|
||||
ScheduleRefreshSeriesList();
|
||||
ScheduleUpdatePreview();
|
||||
}
|
||||
|
||||
EditorGUIUtility.PingObject(target);
|
||||
OnTreeSelectionChanged(new object[] { targetAssetPath });
|
||||
}
|
||||
|
||||
private void PasteProfileAsNewFromClipboard(string targetFolder)
|
||||
{
|
||||
if (!HasProfileInClipboard())
|
||||
{
|
||||
EditorUtility.DisplayDialog("Paste", "Clipboard is empty.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(targetFolder) || !AssetDatabase.IsValidFolder(targetFolder))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Paste", "Target folder is invalid.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
string baseName = string.IsNullOrEmpty(_profileClipboardSourceName) ? "ChartProfile" : _profileClipboardSourceName;
|
||||
string destPath = AssetDatabase.GenerateUniqueAssetPath($"{targetFolder}/{baseName} Copy.asset");
|
||||
|
||||
var profile = ScriptableObject.CreateInstance<ChartProfile>();
|
||||
EditorJsonUtility.FromJsonOverwrite(_profileClipboardJson, profile);
|
||||
|
||||
AssetDatabase.CreateAsset(profile, destPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
RefreshTree();
|
||||
|
||||
EditorGUIUtility.PingObject(profile);
|
||||
OnTreeSelectionChanged(new object[] { destPath });
|
||||
}
|
||||
|
||||
private void CloneProfile(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) return;
|
||||
if (AssetDatabase.IsValidFolder(path)) return;
|
||||
|
||||
string folder = Path.GetDirectoryName(path)?.Replace('\\', '/');
|
||||
if (string.IsNullOrEmpty(folder) || !AssetDatabase.IsValidFolder(folder)) return;
|
||||
|
||||
string ext = Path.GetExtension(path);
|
||||
if (!ext.Equals(".asset", StringComparison.OrdinalIgnoreCase)) return;
|
||||
|
||||
string baseName = Path.GetFileNameWithoutExtension(path);
|
||||
if (string.IsNullOrEmpty(baseName)) return;
|
||||
|
||||
// Extract trailing number from baseName if present
|
||||
string prefix = baseName;
|
||||
int startNum = 1;
|
||||
int trailingNumStart = baseName.Length;
|
||||
while (trailingNumStart > 0 && char.IsDigit(baseName[trailingNumStart - 1]))
|
||||
{
|
||||
trailingNumStart--;
|
||||
}
|
||||
if (trailingNumStart < baseName.Length)
|
||||
{
|
||||
prefix = baseName.Substring(0, trailingNumStart);
|
||||
if (int.TryParse(baseName.Substring(trailingNumStart), out int parsed))
|
||||
{
|
||||
startNum = parsed + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = baseName + " ";
|
||||
}
|
||||
|
||||
string newPath = null;
|
||||
string newName = null;
|
||||
for (int i = startNum; i <= startNum + 9999; i++)
|
||||
{
|
||||
newName = $"{prefix}{i}";
|
||||
string candidate = $"{folder}/{newName}{ext}";
|
||||
if (!AssetPathExists(candidate))
|
||||
{
|
||||
newPath = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(newPath))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Failed to create a unique clone name.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok = AssetDatabase.CopyAsset(path, newPath);
|
||||
if (!ok)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Failed to clone ChartProfile.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
if (!EditorApplication.isCompiling && !EditorApplication.isUpdating) AssetDatabase.Refresh();
|
||||
};
|
||||
|
||||
var clonedProfile = AssetDatabase.LoadAssetAtPath<ChartProfile>(newPath);
|
||||
if (clonedProfile != null && !string.Equals(clonedProfile.name, newName, StringComparison.Ordinal))
|
||||
{
|
||||
clonedProfile.name = newName;
|
||||
EditorUtility.SetDirty(clonedProfile);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
RefreshTree();
|
||||
|
||||
if (clonedProfile != null)
|
||||
{
|
||||
EditorGUIUtility.PingObject(clonedProfile);
|
||||
OnTreeSelectionChanged(new object[] { newPath });
|
||||
}
|
||||
}
|
||||
|
||||
private static bool AssetPathExists(string assetPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(assetPath)) return false;
|
||||
if (AssetDatabase.IsValidFolder(assetPath)) return true;
|
||||
if (AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath) != null) return true;
|
||||
|
||||
string osPath = assetPath.Replace('/', Path.DirectorySeparatorChar);
|
||||
return File.Exists(osPath) || Directory.Exists(osPath);
|
||||
}
|
||||
|
||||
private void DeleteAssetOrFolder(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) return;
|
||||
|
||||
string name = AssetDatabase.IsValidFolder(path)
|
||||
? Path.GetFileName(path)
|
||||
: Path.GetFileNameWithoutExtension(path);
|
||||
|
||||
if (!EditorUtility.DisplayDialog("Delete", $"Delete '{name}'?", "Delete", "Cancel")) return;
|
||||
|
||||
bool ok = AssetDatabase.DeleteAsset(path);
|
||||
if (!ok)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Delete failed.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
RefreshTree();
|
||||
}
|
||||
|
||||
private void CreateNewFolderUnder(string parentFolder)
|
||||
{
|
||||
if (string.IsNullOrEmpty(parentFolder) || !AssetDatabase.IsValidFolder(parentFolder)) return;
|
||||
|
||||
TextPromptWindow.Show("New Folder", "New Folder", folderName =>
|
||||
{
|
||||
folderName = SanitizeFileName(folderName);
|
||||
if (string.IsNullOrWhiteSpace(folderName)) return;
|
||||
|
||||
string guid = AssetDatabase.CreateFolder(parentFolder, folderName);
|
||||
if (string.IsNullOrEmpty(guid))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Failed to create folder.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshTree();
|
||||
});
|
||||
}
|
||||
|
||||
private void CreateNewProfileInFolder(string folder)
|
||||
{
|
||||
if (string.IsNullOrEmpty(folder) || !AssetDatabase.IsValidFolder(folder)) return;
|
||||
CreateNewProfileAtFolder(folder);
|
||||
}
|
||||
|
||||
private void CreateNewProfileAtFolder(string folder)
|
||||
{
|
||||
if (string.IsNullOrEmpty(folder) || !AssetDatabase.IsValidFolder(folder)) return;
|
||||
|
||||
var profile = ScriptableObject.CreateInstance<ChartProfile>();
|
||||
string fullPath = AssetDatabase.GenerateUniqueAssetPath($"{folder}/NewChart.asset");
|
||||
|
||||
AssetDatabase.CreateAsset(profile, fullPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
RefreshTree();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user