-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSubAssetDragAndDrop.cs
186 lines (163 loc) · 6.92 KB
/
SubAssetDragAndDrop.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace UnityEditor
{
//
// This extension allow to drag&drop subassets while pressing 'Alt'
//
[InitializeOnLoad]
public static class SubAssetDragAndDrop
{
static SubAssetDragAndDrop()
{
EditorApplication.projectWindowItemOnGUI += OnProjectWindowItemOnGUI;
}
private static void OnProjectWindowItemOnGUI(string guid, Rect selectionRect)
{
// Break - key modifier doen't pressed
var activated = Event.current.alt;
if (activated == false) return;
// Break - OnGUI() call not for mouse target
var within = selectionRect.Contains(Event.current.mousePosition);
if (within == false) return;
// Break - destination match one of sources
var target = AssetDatabase.GUIDToAssetPath(guid);
var targetInSources = Array.IndexOf(DragAndDrop.paths, target) != -1;
if (targetInSources) return;
// Break - unity default moving
var targetIsFolder = AssetDatabase.IsValidFolder(target);
if (targetIsFolder)
foreach (var asset in DragAndDrop.objectReferences)
if (AssetDatabase.IsMainAsset(asset)) return;
// Break - there is Unity restriction to use GameObjects as SubAssets
foreach (var obj in DragAndDrop.objectReferences)
if (obj is GameObject) return;
if (Event.current.type == EventType.DragUpdated)
{
DragAndDrop.visualMode = DragAndDropVisualMode.Move;
Event.current.Use();
}
else if (Event.current.type == EventType.DragPerform)
{
Move(DragAndDrop.objectReferences, target);
DragAndDrop.AcceptDrag();
Event.current.Use();
}
}
private static void Move(IEnumerable<UnityEngine.Object> sources, string destinationPath)
{
var destinationIsFolder = AssetDatabase.IsValidFolder(destinationPath);
foreach (var source in sources)
{
var sourcePath = AssetDatabase.GetAssetPath(source);
var sourceIsMain = AssetDatabase.IsMainAsset(source);
var sourceAssets = new List<UnityEngine.Object>() { source };
if (sourceIsMain)
sourceAssets.AddRange(AssetDatabase.LoadAllAssetRepresentationsAtPath(sourcePath));
// Peform move assets from source file to destination
foreach (var asset in sourceAssets)
MoveAsset(asset, destinationPath);
// Remove asset file if it is empty now
if (sourceIsMain)
AssetDatabase.DeleteAsset(sourcePath);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void MoveAsset(UnityEngine.Object asset, string destinationPath)
{
// Find hidden references (before source move)
var assetRefs = GetHiddenReferences(asset);
// Move asset
var destinationIsFolder = AssetDatabase.IsValidFolder(destinationPath);
if (destinationIsFolder)
{
var assetName = asset.name + "." + GetFileExtention(asset);
var assetPath = Path.Combine(destinationPath, assetName);
var assetUniquePath = AssetDatabase.GenerateUniqueAssetPath(assetPath);
AssetDatabase.RemoveObjectFromAsset(asset);
AssetDatabase.CreateAsset(asset, assetUniquePath);
}
else
{
AssetDatabase.RemoveObjectFromAsset(asset);
AssetDatabase.AddObjectToAsset(asset, destinationPath);
}
// Move attached hidden references
foreach (var reference in assetRefs)
{
AssetDatabase.RemoveObjectFromAsset(reference);
AssetDatabase.AddObjectToAsset(reference, asset);
}
}
private static List<UnityEngine.Object> GetHiddenReferences(UnityEngine.Object asset, string refsPath = null, List<UnityEngine.Object> refs = null)
{
if (refsPath == null)
refsPath = AssetDatabase.GetAssetPath(asset);
if (refs == null)
refs = new List<UnityEngine.Object>();
var iterator = new SerializedObject(asset).GetIterator();
while (iterator.Next(true))
{
if (iterator.propertyType == SerializedPropertyType.ObjectReference)
{
var obj = iterator.objectReferenceValue;
if (obj != null && (obj.hideFlags & HideFlags.HideInHierarchy) != 0)
{
if (refs.IndexOf(obj) == -1 && AssetDatabase.GetAssetPath(obj) == refsPath)
{
refs.Add(obj);
GetHiddenReferences(obj, refsPath, refs);
}
}
}
}
return refs;
}
/// Thanks to mob-sakai (https://github.com/mob-sakai/SubAssetEditor) for full mapping list
private static string GetFileExtention(UnityEngine.Object obj)
{
if (obj is AnimationClip)
return "anim";
else if (obj is UnityEditor.Animations.AnimatorController)
return "controller";
else if (obj is AnimatorOverrideController)
return "overrideController";
else if (obj is Material)
return "mat";
else if (obj is Texture)
return "png";
else if (obj is ComputeShader)
return "compute";
else if (obj is Shader)
return "shader";
else if (obj is Cubemap)
return "cubemap";
else if (obj is Flare)
return "flare";
else if (obj is ShaderVariantCollection)
return "shadervariants";
else if (obj is LightmapParameters)
return "giparams";
else if (obj is GUISkin)
return "guiskin";
else if (obj is PhysicMaterial)
return "physicMaterial";
else if (obj is PhysicsMaterial2D)
return "physicsMaterial2D";
else if (obj is UnityEngine.Audio.AudioMixer)
return "mixer";
else if (obj is UnityEngine.U2D.SpriteAtlas)
return "spriteatlas";
else if (obj is TextAsset)
return "txt";
else if (obj is GameObject)
return "prefab";
else if (obj is ScriptableObject)
return "asset";
return null;
}
}
}