using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor; using UnityEngine; namespace JBooth.MicroVerseCore.Browser { public class ContentDragHandler { private ContentBrowser browser; public ContentDragHandler(ContentBrowser browser) { this.browser = browser; } public void OnEnable() { } public void OnDisable() { } public void OnGUI() { if (ContentBrowser.placementMode == ContentBrowser.PlacementMode.Place) { if (Event.current.type == EventType.DragUpdated) { bool accepted = IsDragAccepted(); if (accepted) DragAndDrop.visualMode = DragAndDropVisualMode.Copy; else DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; Event.current.Use(); } else if (Event.current.type == EventType.DragPerform) { bool dragPerformed = TryDragPerform(); if (dragPerformed) { Event.current.Use(); } } } } /// /// Accept objects from hierarchy /// /// private bool IsDragAccepted() { bool accepted = DragAndDrop.paths.Length == 0 && DragAndDrop.objectReferences.Length > 0 && DragAndDrop.objectReferences[0] is GameObject; return accepted; } private bool TryDragPerform() { bool accepted = IsDragAccepted(); if (!accepted) return false; // effectively accept the drop operation DragAndDrop.AcceptDrag(); BrowserContent contentAsset = browser.GetSelectedBrowserContentAsset(); if (contentAsset == null) { Debug.LogError("Content asset not found"); return false; } ContentCollection collection = contentAsset as ContentCollection; string outputPath = EnsureFolderStructureExists(contentAsset, "Prefabs", collection.contentType.ToString()); List contendDataList = collection.contents == null ? new List() : collection.contents.ToList(); foreach (Object obj in DragAndDrop.objectReferences) { // output path string prefabPath = Path.Combine(outputPath, obj.name + ".prefab"); // check if prefab exists and confirm overwrite Object prefabCheckObject = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)); if (prefabCheckObject != null) { bool overwrite = EditorUtility.DisplayDialog("Overwrite", $"Prefab with name '{obj.name}' exsists:\n\n{prefabPath}\n\nOverwrite?", "Yes", "No"); if (!overwrite) continue; } // create a gameobject instance GameObject clone = Object.Instantiate( obj as GameObject); if( PrefabUtility.IsAnyPrefabInstanceRoot(clone)) { Debug.LogError("Prefab detected. Only completely prefab instances supported, otherwise users will get errors when they import the preset while the assets themselves aren't installed"); continue; } // set name clone.name = obj.name; // reset transform except scale clone.transform.localPosition = Vector3.zero; clone.transform.rotation = Quaternion.identity; Debug.Log($"Creating prefab: {prefabPath}"); GameObject prefab = PrefabUtility.SaveAsPrefabAsset(clone, prefabPath); ContentData data = new ContentData(); data.prefab = prefab; // replace prefab if it exists bool found = false; foreach (ContentData contentData in contendDataList) { if (contentData.prefab != null && contentData.prefab.name == prefab.name) { Debug.Log($"Prefab name {prefab.name} exists. Replacing"); contentData.prefab = prefab; found = true; } } // prefab not registered yet, register as new if( !found) { contendDataList.Add(data); } Object.DestroyImmediate(clone); } collection.contents = contendDataList.ToArray(); EditorUtility.SetDirty(collection); AssetDatabase.SaveAssetIfDirty(collection); AssetDatabase.Refresh(); return true; } private bool PrefabNameExists(ContentData newContent, List contendDataList) { foreach( ContentData data in contendDataList) { if( data.prefab != null && data.prefab.name == newContent.prefab.name) { return true; } } return false; } /// /// Ensure the folder structure exists, if necessary create it /// /// /// /// private string EnsureFolderStructureExists(BrowserContent assetObject, params string[] subFolders) { string path = AssetDatabase.GetAssetPath(assetObject); path = Path.GetDirectoryName(path); foreach (var folder in subFolders) { string currentPath = path; path = Path.Combine(path, folder); if (AssetDatabase.IsValidFolder(path)) continue; AssetDatabase.CreateFolder(currentPath, folder); } return path; } } }