源战役客户端
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

698 lines
17 KiB

using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace U3DExtends {
public class PrefabWin : EditorWindow
{
private static int _labelDefaultFontSize;
[MenuItem("Window/PrefabWin", false, 9)]
static public void OpenPrefabTool()
{
_labelDefaultFontSize = EditorStyles.label.fontSize;
PrefabWin prefabWin = (PrefabWin)EditorWindow.GetWindow<PrefabWin>(false, "Prefab Win", true);
prefabWin.autoRepaintOnSceneChange = true;
prefabWin.Show();
}
static public PrefabWin instance;
class Item
{
public GameObject prefab;
public string guid;
public Texture tex;
public bool dynamicTex = false;
}
enum Mode
{
CompactMode,
IconMode,
DetailedMode,
}
const int cellPadding = 4;
float mSizePercent = 0.5f;
public float SizePercent
{
get { return mSizePercent; }
set
{
if (mSizePercent != value)
{
mReset = true;
mSizePercent = value;
mCellSize = Mathf.FloorToInt(80 * SizePercent + 10);
EditorPrefs.SetFloat("PrefabWin_SizePercent", mSizePercent);
}
}
}
int mCellSize=50;
int cellSize { get { return mCellSize; } }
int mTab = 0;
Mode mMode = Mode.CompactMode;
Vector2 mPos = Vector2.zero;
bool mMouseIsInside = false;
GUIContent mContent;
GUIStyle mStyle;
BetterList<Item> mItems = new BetterList<Item>();
GameObject[] draggedObjects
{
get
{
if (DragAndDrop.objectReferences == null || DragAndDrop.objectReferences.Length == 0)
return null;
return DragAndDrop.objectReferences.Where(x=>x as GameObject).Cast<GameObject>().ToArray();
}
set
{
if (value != null)
{
DragAndDrop.PrepareStartDrag();
DragAndDrop.objectReferences = value;
draggedObjectIsOurs = true;
}
else DragAndDrop.AcceptDrag();
}
}
bool draggedObjectIsOurs
{
get
{
object obj = DragAndDrop.GetGenericData("Prefab Tool");
if (obj == null) return false;
return (bool)obj;
}
set
{
DragAndDrop.SetGenericData("Prefab Tool", value);
}
}
void OnEnable ()
{
instance = this;
Load();
mContent = new GUIContent();
mStyle = new GUIStyle();
mStyle.alignment = TextAnchor.MiddleCenter;
mStyle.padding = new RectOffset(2, 2, 2, 2);
mStyle.clipping = TextClipping.Clip;
mStyle.wordWrap = true;
mStyle.stretchWidth = false;
mStyle.stretchHeight = false;
mStyle.normal.textColor = UnityEditor.EditorGUIUtility.isProSkin ? new Color(1f, 1f, 1f, 0.5f) : new Color(0f, 0f, 0f, 0.5f);
mStyle.normal.background = null;
}
void OnDisable ()
{
instance = null;
foreach (Item item in mItems) DestroyTexture(item);
Save();
}
void OnSelectionChange () { Repaint(); }
public void Reset ()
{
foreach (Item item in mItems) DestroyTexture(item);
mItems.Clear();
if (mTab == 0 && Configure.PrefabWinFirstSearchPath!="")
{
List<string> filtered = new List<string>();
string[] allAssets = AssetDatabase.GetAllAssetPaths();
foreach (string s in allAssets)
{
//search prefab files in folder:Configure.PrefabWinFirstSearchPath
bool isComeFromPrefab = Regex.IsMatch(s, Configure.PrefabWinFirstSearchPath+@"/((?!/).)*\.prefab");
if (isComeFromPrefab)
filtered.Add(s);
}
filtered.Sort(string.Compare);
foreach (string s in filtered) AddGUID(AssetDatabase.AssetPathToGUID(s), -1);
RectivateLights();
}
}
void AddItem (GameObject go, int index)
{
string guid = U3DExtends.UIEditorHelper.ObjectToGUID(go);
if (string.IsNullOrEmpty(guid))
{
string path = EditorUtility.SaveFilePanelInProject("Save a prefab",
go.name + ".prefab", "prefab", "Save prefab as...", "");
if (string.IsNullOrEmpty(path)) return;
go = PrefabUtility.CreatePrefab(path, go);
if (go == null) return;
guid = U3DExtends.UIEditorHelper.ObjectToGUID(go);
if (string.IsNullOrEmpty(guid)) return;
}
Item ent = new Item();
ent.prefab = go;
ent.guid = guid;
GeneratePreview(ent);
RectivateLights();
if (index < mItems.size) mItems.Insert(index, ent);
else mItems.Add(ent);
Save();
}
Item AddGUID (string guid, int index)
{
GameObject go = U3DExtends.UIEditorHelper.GUIDToObject<GameObject>(guid);
if (go != null)
{
Item ent = new Item();
ent.prefab = go;
ent.guid = guid;
GeneratePreview(ent, false);
if (index < mItems.size) mItems.Insert(index, ent);
else mItems.Add(ent);
return ent;
}
return null;
}
void RemoveItem (object obj)
{
if (this == null) return;
int index = (int)obj;
if (index < mItems.size && index > -1)
{
Item item = mItems[index];
DestroyTexture(item);
mItems.RemoveAt(index);
}
Save();
}
Item FindItem (GameObject go)
{
for (int i = 0; i < mItems.size; ++i)
if (mItems[i].prefab == go)
return mItems[i];
return null;
}
string saveKey { get { return "PrefabWin " + Application.dataPath + " " + mTab; } }
void Save ()
{
string data = "";
if (mItems.size > 0)
{
string guid = mItems[0].guid;
StringBuilder sb = new StringBuilder();
sb.Append(guid);
for (int i = 1; i < mItems.size; ++i)
{
guid = mItems[i].guid;
if (string.IsNullOrEmpty(guid))
{
Debug.LogWarning("Unable to save " + mItems[i].prefab.name);
}
else
{
sb.Append('|');
sb.Append(mItems[i].guid);
}
}
data = sb.ToString();
}
EditorPrefs.SetString(saveKey, data);
}
void Load ()
{
mTab = EditorPrefs.GetInt("PrefabWin Prefab Tab", 0);
SizePercent = EditorPrefs.GetFloat("PrefabWin_SizePercent", 0.5f);
foreach (Item item in mItems) DestroyTexture(item);
mItems.Clear();
string data = EditorPrefs.GetString(saveKey, "");
//data = "";//For test
if (string.IsNullOrEmpty(data))
{
Reset();
}
else
{
if (string.IsNullOrEmpty(data)) return;
string[] guids = data.Split('|');
foreach (string s in guids) AddGUID(s, -1);
RectivateLights();
}
}
void DestroyTexture (Item item)
{
if (item != null && item.dynamicTex && item.tex != null)
{
DestroyImmediate(item.tex);
item.dynamicTex = false;
item.tex = null;
}
}
void UpdateVisual ()
{
if (draggedObjects == null) DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
else if (draggedObjectIsOurs) DragAndDrop.visualMode = DragAndDropVisualMode.Move;
else DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
}
Item CreateItemByPath (string path)
{
if (!string.IsNullOrEmpty(path))
{
path = FileUtil.GetProjectRelativePath(path);
string guid = AssetDatabase.AssetPathToGUID(path);
if (!string.IsNullOrEmpty(guid))
{
GameObject go = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;
Item ent = new Item();
ent.prefab = go;
ent.guid = guid;
GeneratePreview(ent);
return ent;
}
else Debug.Log("No GUID");
}
return null;
}
void GeneratePreview (Item item, bool isReCreate = true)
{
if (item == null || item.prefab == null) return;
{
string preview_path = Configure.ResAssetsPath + "/Preview/" + item.prefab.name + ".png";
if (!isReCreate && File.Exists(preview_path))
{
Texture texture = UIEditorHelper.LoadTextureInLocal(preview_path);
item.tex = texture;
}
else
{
Texture Tex = UIEditorHelper.GetAssetPreview(item.prefab);
if (Tex != null)
{
DestroyTexture(item);
item.tex = Tex;
UIEditorHelper.SaveTextureToPNG(Tex, preview_path);
}
}
item.dynamicTex = false;
return;
}
}
static Transform FindChild (Transform t, string startsWith)
{
if (t.name.StartsWith(startsWith)) return t;
for (int i = 0, imax = t.childCount; i < imax; ++i)
{
Transform ch = FindChild(t.GetChild(i), startsWith);
if (ch != null) return ch;
}
return null;
}
static BetterList<Light> mLights;
static void RectivateLights ()
{
if (mLights != null)
{
for (int i = 0; i < mLights.size; ++i)
mLights[i].enabled = true;
mLights = null;
}
}
int GetCellUnderMouse (int spacingX, int spacingY)
{
Vector2 pos = Event.current.mousePosition + mPos;
int topPadding = 24;
int x = cellPadding, y = cellPadding + topPadding;
if (pos.y < y) return -1;
float width = Screen.width - cellPadding + mPos.x;
float height = Screen.height - cellPadding + mPos.y;
int index = 0;
for (; ; ++index)
{
Rect rect = new Rect(x, y, spacingX, spacingY);
if (rect.Contains(pos)) break;
x += spacingX;
if (x + spacingX > width)
{
if (pos.x > x) return -1;
y += spacingY;
x = cellPadding;
if (y + spacingY > height) return -1;
}
}
return index;
}
bool mReset = false;
private List<Item> _selections = new List<Item>();
void OnGUI ()
{
Event currentEvent = Event.current;
EventType type = currentEvent.type;
int x = cellPadding, y = cellPadding;
int width = Screen.width - cellPadding;
int spacingX = cellSize + cellPadding;
int spacingY = spacingX;
if (mMode == Mode.DetailedMode) spacingY += 32;
GameObject[] draggeds = draggedObjects;
bool isDragging = (draggeds != null);
int indexUnderMouse = GetCellUnderMouse(spacingX, spacingY);
if (isDragging)
{
foreach (var gameObject in draggeds)
{
var result = FindItem(gameObject);
if (result != null)
{
_selections.Add(result);
}
}
}
string searchFilter = EditorPrefs.GetString("PrefabWin_SearchFilter", null);
int newTab = mTab;
GUILayout.BeginHorizontal();
if (GUILayout.Toggle(newTab == 0, "通用控件", "ButtonLeft")) newTab = 0;
if (GUILayout.Toggle(newTab == 1, "其它模板", "ButtonRight")) newTab = 1;
GUILayout.EndHorizontal();
if (mTab != newTab)
{
Save();
mTab = newTab;
mReset = true;
EditorPrefs.SetInt("PrefabWin Prefab Tab", mTab);
Load();
}
if (mReset && type == EventType.Repaint)
{
mReset = false;
foreach (Item item in mItems) GeneratePreview(item, false);
RectivateLights();
}
bool eligibleToDrag = (currentEvent.mousePosition.y < Screen.height - 40);
if (type == EventType.MouseDown)
{
mMouseIsInside = true;
}
else if (type == EventType.MouseDrag)
{
mMouseIsInside = true;
if (indexUnderMouse != -1 && eligibleToDrag)
{
if (draggedObjectIsOurs) DragAndDrop.StartDrag("Prefab Tool");
currentEvent.Use();
}
}
else if (type == EventType.MouseUp)
{
DragAndDrop.PrepareStartDrag();
mMouseIsInside = false;
Repaint();
}
else if (type == EventType.DragUpdated)
{
mMouseIsInside = true;
UpdateVisual();
currentEvent.Use();
}
else if (type == EventType.DragPerform)
{
if (draggeds != null)
{
if (_selections != null)
{
foreach (var selection in _selections)
{
DestroyTexture(selection);
mItems.Remove(selection);
}
}
foreach (var dragged in draggeds)
{
AddItem(dragged, indexUnderMouse);
++indexUnderMouse;
}
draggeds = null;
}
mMouseIsInside = false;
currentEvent.Use();
}
else if (type == EventType.DragExited || type == EventType.Ignore)
{
mMouseIsInside = false;
}
if (!mMouseIsInside)
{
_selections.Clear();
draggeds = null;
}
BetterList<int> indices = new BetterList<int>();
for (int i = 0; i < mItems.size; )
{
if (draggeds != null && indices.size == indexUnderMouse)
indices.Add(-1);
var has = _selections.Exists(item => item == mItems[i]);
if (!has)
{
if (string.IsNullOrEmpty(searchFilter) ||
mItems[i].prefab.name.IndexOf(searchFilter, System.StringComparison.CurrentCultureIgnoreCase) != -1)
indices.Add(i);
}
++i;
}
if (!indices.Contains(-1)) indices.Add(-1);
if (eligibleToDrag && type == EventType.MouseDown && indexUnderMouse > -1)
{
GUIUtility.keyboardControl = 0;
if (currentEvent.button == 0 && indexUnderMouse < indices.size)
{
int index = indices[indexUnderMouse];
if (index != -1 && index < mItems.size)
{
_selections.Add(mItems[index]);
draggedObjects = _selections.Select(item => item.prefab).ToArray();
draggeds = _selections.Select(item=>item.prefab).ToArray();
currentEvent.Use();
}
}
}
mPos = EditorGUILayout.BeginScrollView(mPos);
{
Color normal = new Color(1f, 1f, 1f, 0.5f);
for (int i = 0; i < indices.size; ++i)
{
int index = indices[i];
Item ent = (index != -1) ? mItems[index] : _selections.Count == 0 ? null : _selections[0];
if (ent != null && ent.prefab == null)
{
mItems.RemoveAt(index);
continue;
}
Rect rect = new Rect(x, y, cellSize, cellSize);
Rect inner = rect;
inner.xMin += 2f;
inner.xMax -= 2f;
inner.yMin += 2f;
inner.yMax -= 2f;
rect.yMax -= 1f;
if (!isDragging && (mMode == Mode.CompactMode || (ent == null || ent.tex != null)))
mContent.tooltip = (ent != null) ? ent.prefab.name : "Click to add";
else mContent.tooltip = "";
//if (ent == selection)
{
GUI.color = normal;
U3DExtends.UIEditorHelper.DrawTiledTexture(inner, U3DExtends.UIEditorHelper.backdropTexture);
}
GUI.color = Color.white;
GUI.backgroundColor = normal;
if (GUI.Button(rect, mContent, "Button"))
{
if (ent == null || currentEvent.button == 0)
{
string path = EditorUtility.OpenFilePanel("Add a prefab", "", "prefab");
if (!string.IsNullOrEmpty(path))
{
Item newEnt = CreateItemByPath(path);
if (newEnt != null)
{
mItems.Add(newEnt);
Save();
}
}
}
else if (currentEvent.button == 1)
{
//ContextMenu.AddItem("Update Preview", false, UpdatePreView, index);
ContextMenu.AddItemWithArge("Delete", false, RemoveItem, index);
ContextMenu.Show();
}
}
string caption = (ent == null) ? "" : ent.prefab.name.Replace("Control - ", "");
if (ent != null)
{
if (ent.tex == null)
{
//texture may be destroy after exit game
GeneratePreview(ent, false);
}
if (ent.tex != null)
{
GUI.DrawTexture(inner, ent.tex);
var labelPos = new Rect(inner);
var labelStyle = EditorStyles.label;
labelPos.height = labelStyle.lineHeight;
labelPos.y = inner.height - labelPos.height + 5;
labelStyle.fontSize = (int) (_labelDefaultFontSize * SizePercent);
labelStyle.alignment = TextAnchor.LowerCenter;
{
GUI.Label(labelPos, ent.prefab.name,labelStyle);
}
labelStyle.alignment = TextAnchor.UpperLeft;
labelStyle.fontSize = _labelDefaultFontSize;
}
else if (mMode != Mode.DetailedMode)
{
GUI.Label(inner, caption, mStyle);
caption = "";
}
}
else GUI.Label(inner, "Add", mStyle);
if (mMode == Mode.DetailedMode)
{
GUI.backgroundColor = new Color(1f, 1f, 1f, 0.5f);
GUI.contentColor = new Color(1f, 1f, 1f, 0.7f);
GUI.Label(new Rect(rect.x, rect.y + rect.height, rect.width, 32f), caption, "ProgressBarBack");
GUI.contentColor = Color.white;
GUI.backgroundColor = Color.white;
}
x += spacingX;
if (x + spacingX > width)
{
y += spacingY;
x = cellPadding;
}
}
GUILayout.Space(y + spacingY);
}
EditorGUILayout.EndScrollView();
//if (mTab == 0)
{
//EditorGUILayout.BeginHorizontal();
//bool isCreateBackground = GUILayout.Button("背景");
//if (isCreateBackground)
// EditorApplication.ExecuteMenuItem("UIEditor/创建/Background");
//bool isCreateDecorate = GUILayout.Button("参考图");
//if (isCreateDecorate)
// EditorApplication.ExecuteMenuItem("UIEditor/创建/Decorate");
//EditorGUILayout.EndHorizontal();
}
//else if (mTab != 0)
{
GUILayout.BeginHorizontal();
{
string after = EditorGUILayout.TextField("", searchFilter, "SearchTextField", GUILayout.Width(Screen.width - 20f));
if (GUILayout.Button("", "SearchCancelButton", GUILayout.Width(18f)))
{
after = "";
GUIUtility.keyboardControl = 0;
}
if (searchFilter != after)
{
EditorPrefs.SetString("PrefabWin_SearchFilter", after);
searchFilter = after;
}
}
GUILayout.EndHorizontal();
}
SizePercent = EditorGUILayout.Slider(SizePercent, 0, 1);
}
}
}