241 lines
11 KiB
C#
241 lines
11 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
using SubAssetsToolbox.Utilities;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace SubAssetsToolbox.Editor
|
|
{
|
|
internal static class DragAndDropAddon
|
|
{
|
|
#if UNITY_6000_3_OR_NEWER
|
|
[InitializeOnLoadMethod]
|
|
public static void AddDragProjectHandler()
|
|
{
|
|
DragAndDrop.AddDropHandlerV2(ProjectWindowHandler);
|
|
}
|
|
|
|
private static DragAndDropVisualMode ProjectWindowHandler(EntityId id, string destinationPath, bool released)
|
|
{
|
|
#else
|
|
[InitializeOnLoadMethod]
|
|
public static void AddDragProjectHandler() => DragAndDrop.AddDropHandler(ProjectWindowHandler);
|
|
|
|
private static DragAndDropVisualMode ProjectWindowHandler(int id, string destinationPath, bool released)
|
|
{
|
|
#endif
|
|
if (DragAndDrop.paths.Length == 0 || DragAndDrop.objectReferences.Length == 0)
|
|
// Was not dragging from another window
|
|
return DragAndDropVisualMode.None;
|
|
|
|
bool destinationIsFolder = AssetDatabase.IsValidFolder(destinationPath);
|
|
|
|
if (released)
|
|
{
|
|
bool isDraggingSubAssets = DragAndDrop.objectReferences.Any(AssetDatabase.IsSubAsset);
|
|
|
|
foreach (string path in DragAndDrop.paths)
|
|
{
|
|
if (string.Equals(path, destinationPath)) return DragAndDropVisualMode.None;
|
|
if (destinationIsFolder) continue;
|
|
if (isDraggingSubAssets) continue;
|
|
|
|
if (!TypeChecker.ValidateSubAssetType(path)) return DragAndDropVisualMode.Rejected;
|
|
if (!TypeChecker.ValidateDestinationType(destinationPath)) return DragAndDropVisualMode.Rejected;
|
|
}
|
|
|
|
if (!destinationIsFolder)
|
|
{
|
|
// Adding sub-asset(s)
|
|
// (drag destination is an asset)
|
|
|
|
string objectName = Path.GetFileNameWithoutExtension(destinationPath);
|
|
|
|
bool isOne = DragAndDrop.objectReferences.Length == 1;
|
|
|
|
int choice = EditorUtility.DisplayDialogComplex(
|
|
isOne ? "Add as Sub-Asset" : "Add as Sub-Assets",
|
|
isOne
|
|
? string.Format(Constants.ConfirmAddAsSubAsset, DragAndDrop.objectReferences[0].name,
|
|
objectName)
|
|
: string.Format(Constants.ConfirmAddAsSubAssets, DragAndDrop.objectReferences[0].name,
|
|
DragAndDrop.objectReferences[1].name, objectName),
|
|
isOne ? "Add" : "Add all",
|
|
"Cancel",
|
|
isOne ? "Add and Keep Original" : "Add and Keep Originals");
|
|
|
|
int redirectRefChoice = -1;
|
|
|
|
if (choice == 0)
|
|
{
|
|
ReferencePatchingMode mode = SubAssetsToolboxSettings.PatchReferences.value;
|
|
if (mode == ReferencePatchingMode.AutoApply)
|
|
redirectRefChoice = 0;
|
|
else if (mode == ReferencePatchingMode.AskEachTime)
|
|
redirectRefChoice = EditorUtility.DisplayDialogComplex("Patch references",
|
|
Constants.PatchRefsToSubAssetPrompt,
|
|
"Patch References", "Don't Patch", "Cancel Moving Assets");
|
|
}
|
|
|
|
// Cancelled the operation
|
|
if (choice == 1 || redirectRefChoice == 2) return DragAndDropVisualMode.Rejected;
|
|
|
|
foreach (Object draggedObject in DragAndDrop.objectReferences)
|
|
{
|
|
string draggedObjectPath = AssetDatabase.GetAssetPath(draggedObject);
|
|
string draggedObjectName = draggedObject.name;
|
|
bool wasMainAsset = AssetDatabase.IsMainAsset(draggedObject);
|
|
|
|
// TODO: preserve selection if the object selected was the one being destroyed
|
|
SubAssetsToolbox.AddSubAsset(destinationPath, draggedObject, out Object newSubasset);
|
|
|
|
if (choice == 2) continue; // Keep previous objects
|
|
|
|
if (redirectRefChoice == 0)
|
|
{
|
|
AssetDatabase.SaveAssets();
|
|
if (!AssetReferenceRedirector.RedirectToSubAsset(draggedObject, newSubasset))
|
|
{
|
|
Debug.LogWarning(string.Format(Constants.RedirectionFailed, draggedObjectName));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Do not keep previous
|
|
if (wasMainAsset)
|
|
{
|
|
#if ADDRESSABLES_INSTALLED
|
|
AddressableEntryMigrator.MigrateOrRemoveEntry(
|
|
AssetDatabase.AssetPathToGUID(draggedObjectPath),
|
|
AssetDatabase.AssetPathToGUID(destinationPath),
|
|
objectName);
|
|
#endif
|
|
AssetDatabase.DeleteAsset(draggedObjectPath);
|
|
}
|
|
else
|
|
{
|
|
// After redirect, Refresh() may have invalidated the original reference.
|
|
// Reload the sub-asset from disk if needed.
|
|
Object objectToRemove = draggedObject;
|
|
if (objectToRemove == null)
|
|
{
|
|
Object[] subAssets = AssetDatabase.LoadAllAssetRepresentationsAtPath(draggedObjectPath);
|
|
objectToRemove = subAssets.FirstOrDefault(a => a.name == draggedObjectName);
|
|
}
|
|
|
|
if (objectToRemove != null)
|
|
SubAssetsToolbox.RemoveSubAsset(draggedObjectPath, objectToRemove);
|
|
}
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
return DragAndDropVisualMode.Link;
|
|
}
|
|
|
|
// Removing sub-asset(s)
|
|
// (drag destination is a folder or an empty space)
|
|
|
|
if (!DragAndDrop.objectReferences.Any(AssetDatabase.IsSubAsset))
|
|
return Path.GetDirectoryName(DragAndDrop.paths[0]) == destinationPath
|
|
? DragAndDropVisualMode.Move
|
|
: DragAndDropVisualMode.None;
|
|
|
|
ReferencePatchingMode redirectMode = SubAssetsToolboxSettings.PatchReferences.value;
|
|
int redirectRefsChoice;
|
|
if (redirectMode == ReferencePatchingMode.AutoApply)
|
|
redirectRefsChoice = 0;
|
|
else if (redirectMode == ReferencePatchingMode.AskEachTime)
|
|
redirectRefsChoice = EditorUtility.DisplayDialogComplex("Patch references",
|
|
Constants.PatchRefsToStandalonePrompt,
|
|
"Patch References", "Don't Patch", "Cancel Sub-Asset Removal");
|
|
else
|
|
redirectRefsChoice = 1;
|
|
|
|
if (redirectRefsChoice == 2) return DragAndDropVisualMode.Rejected;
|
|
|
|
int rejected = 0;
|
|
|
|
foreach (Object draggedObject in DragAndDrop.objectReferences)
|
|
{
|
|
string draggedObjectPath = AssetDatabase.GetAssetPath(draggedObject);
|
|
|
|
if (AssetDatabase.IsSubAsset(draggedObject))
|
|
{
|
|
// Was dragging a sub-asset: un-parent
|
|
|
|
// Check if its parent is in selection too
|
|
Object mainAssetAtPath = AssetDatabase.LoadMainAssetAtPath(draggedObjectPath);
|
|
string fileExtension = ExtensionMap.GetFileExtensionByType(draggedObject.GetType());
|
|
if (DragAndDrop.objectReferences.Contains(mainAssetAtPath)) continue;
|
|
|
|
// Verify if there's an object with the same name
|
|
string desiredName = Path.Combine(destinationPath, $"{draggedObject.name}.{fileExtension}");
|
|
if (AssetDatabase.LoadAssetAtPath<Object>(desiredName) != null)
|
|
{
|
|
Debug.LogWarning(string.Format(Constants.ImpossibleToExtract, draggedObject.name));
|
|
|
|
rejected++;
|
|
continue;
|
|
}
|
|
|
|
string draggedObjectName = draggedObject.name;
|
|
Object newObject = Object.Instantiate(draggedObject);
|
|
newObject.name = draggedObjectName;
|
|
AssetDatabase.CreateAsset(newObject, desiredName);
|
|
|
|
if (redirectRefsChoice == 0)
|
|
{
|
|
AssetDatabase.SaveAssets();
|
|
if (!AssetReferenceRedirector.RedirectToStandaloneAsset(draggedObject, newObject))
|
|
{
|
|
Debug.LogWarning(string.Format(Constants.RedirectionFailed, draggedObjectName));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// After redirect, Refresh() may have invalidated the original reference.
|
|
// Reload the sub-asset from disk if needed.
|
|
Object objectToRemove = draggedObject;
|
|
if (objectToRemove == null)
|
|
{
|
|
Object[] subAssets = AssetDatabase.LoadAllAssetRepresentationsAtPath(draggedObjectPath);
|
|
objectToRemove = subAssets.FirstOrDefault(a => a.name == draggedObjectName);
|
|
}
|
|
|
|
if (objectToRemove != null)
|
|
SubAssetsToolbox.RemoveSubAsset(draggedObjectPath, objectToRemove);
|
|
}
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
if (rejected != 0) return DragAndDropVisualMode.Rejected;
|
|
if (Path.GetDirectoryName(DragAndDrop.paths[0]) != destinationPath)
|
|
return DragAndDropVisualMode.None; // Allows relocation of main assets
|
|
|
|
return DragAndDropVisualMode.Move; // Avoid confirmation popup when drag/dropping in the same folder
|
|
}
|
|
|
|
// While dragging
|
|
|
|
if (destinationIsFolder)
|
|
return DragAndDropVisualMode.Generic;
|
|
|
|
if (DragAndDrop.objectReferences.Any(AssetDatabase.IsSubAsset))
|
|
return DragAndDropVisualMode.Link;
|
|
|
|
foreach (string path in DragAndDrop.paths)
|
|
{
|
|
if (string.Equals(path, destinationPath)) return DragAndDropVisualMode.None;
|
|
if (!TypeChecker.ValidateSubAssetType(path, true)) return DragAndDropVisualMode.Rejected;
|
|
if (!TypeChecker.ValidateDestinationType(destinationPath, true)) return DragAndDropVisualMode.Rejected;
|
|
}
|
|
|
|
return DragAndDropVisualMode.Link;
|
|
}
|
|
}
|
|
} |