Skip to content

Instantly share code, notes, and snippets.

@Raptorij
Last active August 29, 2024 04:18
Show Gist options
  • Save Raptorij/a4b20e2aa0f14c3564bb08df4f33382c to your computer and use it in GitHub Desktop.
Save Raptorij/a4b20e2aa0f14c3564bb08df4f33382c to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
public class QbarEditor : EditorWindow
{
const int CELL_SIZE = 50;
private List<Object> setOfObjects = new List<Object>();
private QBarSaves qBarSaves = new();
private Vector2 scrollView;
private string searchString = "";
private Vector2 clickPos;
private float zoom = 1f;
private bool lockClick;
private string FolderPath => Path.Combine(Path.Combine( Application.dataPath, "../" ), "UserSettings");
private string FullPath => Path.Combine(FolderPath, "Qbar.asset");
[System.Serializable]
private class QBarSaves
{
public List<string> ObjectsPaths = new List<string>();
public float Zoom;
}
[MenuItem("Tools/Qbar")]
private static void Init()
{
var window = EditorWindow.CreateInstance<QbarEditor>();
GUIContent titleContent = new GUIContent("Qbar", EditorGUIUtility.IconContent("GridLayoutGroup Icon").image);
window.titleContent = titleContent;
window.Show();
}
private void OnFocus()
{
Load();
}
private void OnLostFocus()
{
GUI.FocusControl(null);
Repaint();
}
private void OnEnable()
{
Load();
}
private void Load()
{
setOfObjects.Clear();
if (!File.Exists(FullPath))
{
return;
}
using (var file = File.Open(FullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var formatter = new BinaryFormatter();
qBarSaves = (QBarSaves)formatter.Deserialize(file);
}
if (qBarSaves != null)
{
for (int i = 0; i < qBarSaves.ObjectsPaths.Count; i++)
{
var path = AssetDatabase.GUIDToAssetPath(qBarSaves.ObjectsPaths[i]);
var obj = AssetDatabase.LoadAssetAtPath<Object>(path);
if (obj != null)
{
setOfObjects.Add(obj);
}
}
zoom = qBarSaves.Zoom;
}
else
{
qBarSaves = new QBarSaves();
Save();
}
}
private void Save()
{
qBarSaves.ObjectsPaths.Clear();
for (int i = 0; i < setOfObjects.Count; i++)
{
var path = AssetDatabase.GetAssetPath(setOfObjects[i]);
var guid = AssetDatabase.GUIDFromAssetPath(path);
var guidString = guid.ToString();
qBarSaves.ObjectsPaths.Add(guidString);
}
qBarSaves.Zoom = zoom;
if (!File.Exists(FullPath))
{
using (var file = File.Create(FullPath))
{
var formatter = new BinaryFormatter();
formatter.Serialize(file, qBarSaves);
}
}
else
{
using (var file = File.Open(FullPath, FileMode.Create, FileAccess.Write, FileShare.Write))
{
var formatter = new BinaryFormatter();
formatter.Serialize(file, qBarSaves);
}
}
}
private void OnGUI()
{
var zoomRect = new Rect(new Vector2(0, Screen.height - 42), new Vector2(Screen.width, 42));
var dropArea = new Rect(0, 0, Screen.width, Screen.height);
DropAreaGUI(dropArea);
GUILayout.BeginHorizontal(GUI.skin.FindStyle("Toolbar"));
GUILayout.Space(5);
//var searchStyle = GUI.skin.FindStyle("ToolbarSeachTextField");
searchString = GUILayout.TextField(searchString /*, searchStyle*/);
if (GUILayout.Button("", GUI.skin.FindStyle("ToolbarSearchCancelButton")))
{
searchString = "";
GUI.FocusControl(null);
}
GUILayout.EndHorizontal();
var e = Event.current;
lockClick = zoomRect.Contains(Event.current.mousePosition);
if (zoom >= 0.75f)
{
DisplayPrefabsGrid(setOfObjects);
}
else
{
DisplayPrefabsList(setOfObjects);
}
GUI.Box(zoomRect, "", "ProjectBrowserBottomBarBg");
zoomRect = new Rect(new Vector2(Screen.width - 80, Screen.height - 40), new Vector2(60, 25));
EditorGUI.BeginChangeCheck();
zoom = GUI.HorizontalSlider(zoomRect, zoom, 0, 2);
if (EditorGUI.EndChangeCheck())
{
Save();
}
}
private void Remove(Object @object)
{
setOfObjects.Remove(@object);
Save();
Repaint();
}
private bool TryShowContextMenu(Rect r, Object @object)
{
var e = Event.current;
if (e.type == EventType.ContextClick)
{
Vector2 mousePos = e.mousePosition;
if (r.Contains(mousePos))
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Remove"), false, (x) => Remove(@object), "item 1");
menu.ShowAsContext();
e.Use();
return true;
}
}
return false;
}
public void DisplayPrefabsList(List<Object> prefabs)
{
if (prefabs == null || prefabs.Count == 0)
{
return;
}
int numberOfPrefabs = searchString == ""
? prefabs.Count
: prefabs.Where(x => x.name.ToLower().Contains(searchString.ToLower())).Count();
var searchedPrefabs = searchString == ""
? prefabs
: prefabs.Where(x => x.name.ToLower().Contains(searchString.ToLower())).ToList();
int y = (int)(EditorGUIUtility.singleLineHeight);
float heightScroll = 5 + prefabs.Count * EditorGUIUtility.singleLineHeight + EditorGUIUtility.singleLineHeight;
scrollView = GUI.BeginScrollView(new Rect(0 - 2, y + 2, Screen.width, Screen.height - y - 42), scrollView,
new Rect(0, 0, Screen.width - 20, heightScroll));
var e = Event.current;
if (e.type == EventType.KeyDown)
{
if (e.keyCode == KeyCode.Escape)
{
GUI.FocusControl(null);
}
}
for (int i = 0; i < numberOfPrefabs; i++)
{
var go = searchedPrefabs[i];
float posX = 5;
float posY = 5 + i * EditorGUIUtility.singleLineHeight;
Rect r = new Rect(posX, posY, 20, 20);
var clickRect = r;
clickRect.x = 0;
clickRect.width = Screen.width;
if (TryShowContextMenu(clickRect, go))
{
return;
}
if (clickRect.Contains(Event.current.mousePosition) && !lockClick)
{
if (Event.current.type == EventType.MouseDrag)
{
DragAndDrop.PrepareStartDrag();
DragAndDrop.StartDrag("Dragging title");
DragAndDrop.objectReferences = new Object[] { go };
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
break;
}
else
{
if (e.type == EventType.MouseDown && e.button == 0)
{
GUI.FocusControl(null);
clickPos = Event.current.mousePosition;
if (clickPos == Event.current.mousePosition)
{
if (e.clickCount == 2)
{
Selection.activeObject = null;
AssetDatabase.OpenAsset(go);
Repaint();
}
else
{
Selection.activeObject = go;
EditorGUIUtility.PingObject(go);
if (e.control)
{
}
}
}
}
else if (e.type == EventType.MouseUp && e.button == 0)
{
GUI.FocusControl(null);
}
}
}
var path = AssetDatabase.GetAssetPath(go);
GUI.Label(r, AssetDatabase.GetCachedIcon(path));
r.x += 2 + 20;
r.width = Screen.width;
GUI.Label(r, go.name);
}
GUI.EndScrollView();
}
public void DisplayPrefabsGrid(List<Object> prefabs)
{
if (prefabs == null || prefabs.Count == 0)
{
return;
}
int numberOfPrefabs = searchString == ""
? prefabs.Count
: prefabs.Where(x => x.name.ToLower().Contains(searchString.ToLower())).Count();
int windowWidth = Mathf.FloorToInt(Screen.width);
int columns = Mathf.FloorToInt((float)windowWidth / ((CELL_SIZE + 1f) * zoom));
int rows = Mathf.FloorToInt(numberOfPrefabs / columns);
int y = (int)(EditorGUIUtility.singleLineHeight);
scrollView = GUI.BeginScrollView(new Rect(0 - 2, y + 2, Screen.width, Screen.height - y - 42), scrollView,
new Rect(0, 0, 0, ((CELL_SIZE + 15) * zoom) * rows));
var searchedPrefabs = searchString == ""
? prefabs
: prefabs.Where(x => x.name.ToLower().Contains(searchString.ToLower())).ToList();
var e = Event.current;
if (e.type == EventType.KeyDown)
{
if (e.keyCode == KeyCode.Escape)
{
GUI.FocusControl(null);
}
}
for (int i = 0; i < numberOfPrefabs; i++)
{
var go = searchedPrefabs[i];
float posX = 5 + CELL_SIZE * zoom * (i - (Mathf.FloorToInt(i / columns)) * columns);
float posY = CELL_SIZE * zoom * Mathf.FloorToInt(i / columns);
Rect r = new Rect(posX, posY + 10 * (i / columns), CELL_SIZE * zoom, CELL_SIZE * zoom);
Rect border = new Rect(r.x + 2 * zoom, r.y + 6 * zoom, r.width - 4 * zoom, r.height - 4 * zoom);
if (TryShowContextMenu(r, go))
{
return;
}
if (r.Contains(Event.current.mousePosition) && !lockClick)
{
if (Event.current.type == EventType.MouseDrag)
{
DragAndDrop.PrepareStartDrag();
DragAndDrop.StartDrag("Dragging title");
DragAndDrop.objectReferences = new Object[] { go };
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
break;
}
else
{
if (e.type == EventType.MouseDown && e.button == 0)
{
GUI.FocusControl(null);
clickPos = Event.current.mousePosition;
if (clickPos == Event.current.mousePosition)
{
if (e.clickCount == 2)
{
Selection.activeObject = null;
AssetDatabase.OpenAsset(go);
Repaint();
}
else
{
Selection.activeObject = go;
EditorGUIUtility.PingObject(go);
if (e.control)
{
}
}
}
}
else if (e.type == EventType.MouseUp && e.button == 0)
{
GUI.FocusControl(null);
}
}
}
border.x += 2 * zoom;
border.y += 2 * zoom;
border.width -= 4 * zoom;
border.height -= 4 * zoom;
var preview = AssetPreview.GetAssetPreview(go);
if (preview != null)
{
EditorGUI.DrawTextureTransparent(border, preview, ScaleMode.ScaleToFit, 1f);
}
else
{
EditorGUI.DrawRect(border, new Color(0.32156862745f, 0.32156862745f, 0.32156862745f));
var path = AssetDatabase.GetAssetPath(go);
GUI.Label(border, AssetDatabase.GetCachedIcon(path));
}
border.x -= 2 * zoom;
border.y += (CELL_SIZE * zoom) / 2f + 5 * zoom;
GUI.Label(border, go.name);
}
GUI.EndScrollView();
}
public void DropAreaGUI(Rect r)
{
var e = Event.current;
var dropArea = r;
GUI.Box(dropArea, string.Empty);
GUI.Label(dropArea, "+", EditorStyles.centeredGreyMiniLabel);
switch (e.type)
{
case EventType.DragUpdated:
case EventType.DragPerform:
if (!dropArea.Contains(e.mousePosition))
{
return;
}
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
foreach (var dragged_object in DragAndDrop.objectReferences)
{
Object go = (Object)dragged_object;
if (AssetDatabase.GetAssetPath(go) == "")
{
DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
return;
}
}
if (e.type == EventType.DragPerform)
{
DragAndDrop.AcceptDrag();
foreach (var dragged_object in DragAndDrop.objectReferences)
{
Object go = (Object)dragged_object;
if (AssetDatabase.GetAssetPath(go) != "")
{
if (setOfObjects.Contains(go))
{
Debug.Log($"<color=yellow>[Qtbar] </color>Object \"{go.name}\" already exist in Qbar.");
}
else
{
setOfObjects.Add(go);
Save();
}
}
else
{
Debug.Log($"<color=yellow>[Qbar] </color>Object \"{go.name}\" is belong scene");
}
}
}
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment