P4Connect.Icons.cs #1

  • //
  • guest/
  • anis_sg/
  • perforce_software/
  • p4connect/
  • src/
  • P4Connect/
  • P4Connect/
  • P4Connect.Icons.cs
  • View
  • Commits
  • Open Download .zip Download (16 KB)
using UnityEditor;
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Perforce.P4;

namespace P4Connect
{
	public class Icons
	{
		const float MinHeight = 16.0f;
		const float MinWidth = 32.0f;
		const float MaxWidth = 96.0f;
		const float IconMinSize = 8.0f;
		const float IconMaxSize = 24.0f;
		const float MarginX = 1.0f;
		const float MarginY = 0.0f;

		enum Corner
		{
			BottomRight = 0,
			BottomLeft,
			TopLeft,
			TopRight,
			Center
		}

		static Texture IconHasLatest;
		static Texture IconOutOfDate;
		static Texture IconCheckedOutLocal;
		static Texture IconCheckedOutOther;
		static Texture IconMarkedForAddLocal;
		static Texture IconMarkedForAddOther;
		static Texture IconMarkedForDeleteLocal;
		static Texture IconMarkedForDeleteOther;
		static Texture IconMoveAdd;
		static Texture IconMoveDelete;
		static Texture IconMissingFile;
		static Texture IconOtherFile;
		static Texture IconPairFileOnly;
		static Texture IconPairMetaOnly;
		static Texture IconPairFileAndMeta;
		static Texture IconNeedsResolve;
		static Texture IconFolderMetaOutOfDate;
		static Texture IconFolderMetaModifiedLocal;
		static Texture IconLockedLocal;
		static Texture IconLockedOther;
        static Texture IconChangeOther;
        static Texture IconChangeLocal;
        static Texture IconChangeShelvedOther;
        static Texture IconChangeShelvedLocal;

		enum UpdateState
		{
			None,
			ProjectWindowChanged,
			TriggerProjectWindowChanged,
		}
		
		static UpdateState _State;
		static string _CurrentFolder;
		static HashSet<string> _FilesToUpdate = new HashSet<string>();

        static UnityEngine.Object[] allTextures;
        public static AssetBundle iconbundle = null;

		static public void Initialize()
		{
			string iconsPack = Utils.FullPathToAssetPath(System.IO.Path.Combine(Utils.GetEditorAssetFullDirectory(), "icons.pack"));

            if (iconbundle != null)
            {
                iconbundle.Unload(true);
            }
			iconbundle = AssetBundle.CreateFromFile(iconsPack);
            if (iconbundle != null)
            {
#if UNITY_5
                allTextures = iconbundle.LoadAllAssets(typeof(Texture));
#else
                if (Utils.IsRunningUnity5())  // Use reflection to call "LoadAllAssets" at runtime.  Running in Unity5 built in Unity 4 :)
                {
                    System.Reflection.MethodInfo _LoadAllAssets = typeof(AssetBundle).GetMethod("LoadAllAssets", new Type[]{ typeof(Type) });

                    object result = _LoadAllAssets.Invoke(iconbundle, new object[] { typeof(Texture) });
                    allTextures = (UnityEngine.Object[]) result;
                }
                else
                {
                    allTextures = iconbundle.LoadAll(typeof(Texture));
                }     
#endif
                iconbundle.Unload(false);
            }

			if (allTextures != null)
			{
                IconHasLatest = GetTexture("Has-Latest");
                IconOutOfDate = GetTexture("Out-of-date");
                IconCheckedOutLocal = GetTexture("Checked-out-Local");
                IconCheckedOutOther = GetTexture("Checked-out-Other");
                IconMarkedForAddLocal = GetTexture("Marked-for-add-Local");
                IconMarkedForAddOther = GetTexture("Marked-for-add-Other");
                IconMarkedForDeleteLocal = GetTexture("Marked-for-delete-Local");
                IconMarkedForDeleteOther = GetTexture("Marked-for-delete-Other");
                IconMoveAdd = GetTexture("Move-Add");
                IconMoveDelete = GetTexture("Move-Delete");
                IconMissingFile = GetTexture("missing-file");
                IconOtherFile = GetTexture("other-file");
                IconPairFileOnly = GetTexture("has-file");
                IconPairMetaOnly = GetTexture("has-meta");
                IconPairFileAndMeta = GetTexture("has-file-and-meta");
                IconNeedsResolve = GetTexture("needs-resolve");
                IconFolderMetaOutOfDate = GetTexture("foldermeta-out-of-date");
                IconFolderMetaModifiedLocal = GetTexture("foldermeta-modified-local");
                IconLockedLocal = GetTexture("locked-local");
                IconLockedOther = GetTexture("locked-other");
                IconChangeOther = GetTexture("change-other");
                IconChangeLocal = GetTexture("change-local");
                IconChangeShelvedOther = GetTexture("change-shelved-other");
                IconChangeShelvedLocal = GetTexture("change-shelved-local");
				_State = UpdateState.None;
				_FilesToUpdate = new HashSet<string>();
				UpdateDisplay();
			}
		}

        public static Texture GetTexture(string name)
        {
            foreach(Texture icon in allTextures)
            {
                if (icon.name.ToLower() == name.ToLower())
                {
                    return icon;
                }
            }
            Debug.Log("Missing texture: " + name);
            return null;
        }

        // 
        // Hook up all the callback functions into editorApplication
        //
		public static void UpdateDisplay()
		{
			EditorApplication.projectWindowItemOnGUI -= OnProjectWindowItem;
			EditorApplication.update -= OnUpdate;
			AssetStatusCache.OnAssetStatusChanged -= OnOperationPerformed;
			if (Config.ValidConfiguration && Config.DisplayStatusIcons)
			{
				EditorApplication.projectWindowItemOnGUI += OnProjectWindowItem;
				EditorApplication.update += OnUpdate;
				AssetStatusCache.OnAssetStatusChanged += OnOperationPerformed;
			}
			_State = UpdateState.TriggerProjectWindowChanged;
			EditorApplication.RepaintProjectWindow();
		}

		static void OnProjectWindowItem(String aGUID, Rect aSelectionRect)
		{
			// What kind of asset is this?
			string assetPath = AssetDatabase.GUIDToAssetPath(aGUID);
			DrawItemIcons(assetPath, aSelectionRect, aSelectionRect.height <= 16.0f);

			if (_State == UpdateState.ProjectWindowChanged)
			{
				_FilesToUpdate.Add(assetPath);
			}
		}

		static void OnUpdate()
		{
			// Don't update icons while in play mode
			if (Config.ValidConfiguration && Config.DisplayStatusIcons && !EditorApplication.isPlayingOrWillChangePlaymode)
			{
				if (_State == UpdateState.TriggerProjectWindowChanged)
				{
					_FilesToUpdate.Clear();
					_State = UpdateState.ProjectWindowChanged;

					// Force a refresh
					AssetDatabase.Refresh();
				}
				else if (_State == UpdateState.ProjectWindowChanged)
				{
					// Now we update the state of all the flags
					List<string> validFiles = new List<string>();
					foreach (var file in _FilesToUpdate)
					{
						if (file != "" && file != "Assets")
						{
							validFiles.Add(file);
						}
					}

					// Merge in the list of assets from the current folder
					var sel = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets);
					if (sel != null && sel.Length > 0)
					{
						string assetPath = AssetDatabase.GetAssetPath(sel[0]);
						string assetFullPath = Utils.AssetPathToFullPath(assetPath);
						string folderFullPath;
						if (Utils.IsDirectory(assetPath))
							folderFullPath = assetFullPath;
						else
							folderFullPath = System.IO.Path.GetDirectoryName(assetFullPath);

						foreach (var name in System.IO.Directory.GetFileSystemEntries(folderFullPath))
						{
							string subAssetPath = Utils.FullPathToAssetPath(name);
							if (!validFiles.Contains(subAssetPath))
								validFiles.Add(subAssetPath);
						}
					}

					AssetStatusCache.UpdateAssetData(validFiles);
					_FilesToUpdate.Clear();
					_State = UpdateState.None;
					AssetDatabase.Refresh();
				}
				else if (_State == UpdateState.None)
				{
					// Detect change in selection
					var selection = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets);
					if (selection != null && selection.Length > 0)
					{
						string selectionFolder = AssetDatabase.GetAssetPath(selection[0]);
						if (!Utils.IsDirectory(selectionFolder))
						{
							selectionFolder = System.IO.Path.GetDirectoryName(selectionFolder);
						}
						if (_CurrentFolder != selectionFolder)
						{
							_CurrentFolder = selectionFolder;
							_FilesToUpdate.Clear();
							_State = UpdateState.ProjectWindowChanged;
						}
					}
				}
			}
		}

		static void OnOperationPerformed(PerforceConnection aConnection)
		{
			// Refresh the project view
			_State = UpdateState.TriggerProjectWindowChanged;
		}

		public static void DrawItemIcons(String aAssetPath, Rect aSelectionRect, bool aHorizontal)
		{
			CheckInit();
			// What kind of asset is this?
			if (aAssetPath != "" && aAssetPath != "Assets")
			{
				bool isFolder = Utils.IsDirectory(aAssetPath);

				AssetStatusCache.AssetStatus status;
				if (isFolder)
					status = AssetStatusCache.GetAssetStatus(Utils.MetaFromAsset(aAssetPath));
				else
					status = AssetStatusCache.GetAssetStatus(aAssetPath);

				DrawItemIcons(status, isFolder, aSelectionRect, aHorizontal);
			}
		}

		public static void DrawItemIcons(AssetStatusCache.AssetStatus aStatus, bool aIsFolder, Rect aSelectionRect, bool aHorizontal)
		{
			CheckInit();
			Rect iconRect = GetIconRect(aSelectionRect, Corner.TopLeft, aHorizontal);
			switch (aStatus.LocalState)
			{
				case FileState.None:
					break;
				case FileState.InDepot:
					break;
				case FileState.MarkedForEdit:
					if (aIsFolder)
						GUI.DrawTexture(iconRect, IconFolderMetaModifiedLocal);
					else
						GUI.DrawTexture(iconRect, IconCheckedOutLocal);
					break;
				case FileState.MarkedForAdd:
					if (aIsFolder)
						GUI.DrawTexture(iconRect, IconFolderMetaModifiedLocal);
					else
						GUI.DrawTexture(iconRect, IconMarkedForAddLocal);
					break;
				case FileState.MarkedForDelete:
					if (aIsFolder)
						GUI.DrawTexture(iconRect, IconFolderMetaModifiedLocal);
					else
						GUI.DrawTexture(iconRect, IconMarkedForDeleteLocal);
					break;
				case FileState.MarkedForAddMove:
					if (aIsFolder)
						GUI.DrawTexture(iconRect, IconFolderMetaModifiedLocal);
					else
						GUI.DrawTexture(iconRect, IconMoveAdd);
					break;
				case FileState.MarkedForDeleteMove:
					if (aIsFolder)
						GUI.DrawTexture(iconRect, IconFolderMetaModifiedLocal);
					else
						GUI.DrawTexture(iconRect, IconMoveDelete);
					break;
			}

			iconRect = GetIconRect(aSelectionRect, Corner.TopRight, aHorizontal);
			switch (aStatus.OtherState)
			{
				case FileState.None:
					break;
				case FileState.InDepot:
					break;
				case FileState.MarkedForEdit:
					if (!aIsFolder)
					{
						GUI.DrawTexture(iconRect, IconCheckedOutOther);
					}
					break;
				case FileState.MarkedForAdd:
					if (!aIsFolder)
					{
						GUI.DrawTexture(iconRect, IconMarkedForAddOther);
					}
					break;
				case FileState.MarkedForDelete:
					if (!aIsFolder)
					{
						GUI.DrawTexture(iconRect, IconMarkedForDeleteOther);
					}
					break;
				case FileState.MarkedForAddMove:
					if (!aIsFolder)
					{
						GUI.DrawTexture(iconRect, IconMarkedForAddOther);
					}
					break;
				case FileState.MarkedForDeleteMove:
					if (!aIsFolder)
					{
						GUI.DrawTexture(iconRect, IconMarkedForDeleteOther);
					}
					break;
			}

			iconRect = GetIconRect(aSelectionRect, Corner.BottomRight, aHorizontal);
			switch (aStatus.LocalState)
			{
				case FileState.None:
					break;
				case FileState.InDepot:
					switch (aStatus.RevisionState)
					{
						case RevisionState.None:
							break;
						case RevisionState.HasLatest:
							if (!aIsFolder)
							{
								GUI.DrawTexture(iconRect, IconHasLatest);
							}
							break;
						case RevisionState.OutOfDate:
							if (aIsFolder)
								GUI.DrawTexture(iconRect, IconFolderMetaOutOfDate);
							else
								GUI.DrawTexture(iconRect, IconOutOfDate);
							break;
					}
					break;
				case FileState.MarkedForEdit:
					goto case FileState.InDepot;
				case FileState.MarkedForAdd:
					break;
				case FileState.MarkedForDelete:
					goto case FileState.InDepot;
				case FileState.MarkedForAddMove:
					if (!aIsFolder)
					{
						GUI.DrawTexture(iconRect, IconHasLatest);
					}
					break;
				case FileState.MarkedForDeleteMove:
					goto case FileState.InDepot;
			}

			switch (aStatus.ResolvedState)
			{
				case ResolvedState.None:
					break;
				case ResolvedState.NeedsResolve:
					if (aIsFolder)
					{
						iconRect = GetIconRect(aSelectionRect, Corner.BottomRight, aHorizontal);
						GUI.DrawTexture(iconRect, IconNeedsResolve);
					}
					else
					{
						iconRect = GetIconRect(aSelectionRect, Corner.Center, aHorizontal);
						GUI.DrawTexture(iconRect, IconNeedsResolve);
					}
					break;
			}

			switch (aStatus.LockState)
			{
				case LockState.None:
					break;
				case LockState.OurLock:
					iconRect = GetIconRect(aSelectionRect, Corner.BottomLeft, aHorizontal);
					GUI.DrawTexture(iconRect, IconLockedLocal);
					break;
				case LockState.TheirLock:
					iconRect = GetIconRect(aSelectionRect, Corner.BottomLeft, aHorizontal);
					GUI.DrawTexture(iconRect, IconLockedOther);
					break;
			}
		}

		public static Texture GetAssetIcon(string arPath)
		{
			CheckInit();
			Texture asset = AssetDatabase.GetCachedIcon(arPath);

			// If we still don't have an icon, use a default one
			if (asset == null)
			{
				if (arPath.StartsWith("Assets/",!Utils.IsCaseSensitive(),null))
				{
					asset = IconMissingFile;
				}
				else
				{
					asset = IconOtherFile;
				}
			}
			return asset;
		}

		public static Texture GetFileAndMetaTypeIcon(FileAndMetaType aType)
		{
			CheckInit();
			Texture ret = null;
			switch (aType)
			{
				case FileAndMetaType.FileOnly:
					ret = IconPairFileOnly;
					break;
				case FileAndMetaType.MetaOnly:
					ret = IconPairMetaOnly;
					break;
				case FileAndMetaType.FileAndMeta:
					ret = IconPairFileAndMeta;
					break;
			}
			return ret;
		}

		static Rect GetIconRect(Rect aSelectionRect, Corner aCorner, bool aHorizontal)
		{
			Rect iconRect = aSelectionRect;

			float iconSize = 0.0f;
			if (aHorizontal)
			{
				// The view is in list mode
				iconSize = IconMinSize;
				switch (aCorner)
				{
					case Corner.BottomRight:
						iconRect.xMin += MinHeight - iconSize + MarginX;
						iconRect.yMin = iconRect.yMax - iconSize + MarginY;
						break;
					case Corner.BottomLeft:
						iconRect.xMin -= MarginX;
						iconRect.yMin = iconRect.yMax - iconSize + MarginY;
						break;
					case Corner.TopLeft:
						iconRect.xMin -= MarginX;
						iconRect.yMin -= MarginY;
						break;
					case Corner.TopRight:
						iconRect.xMin += MinHeight - iconSize + MarginX;
						iconRect.yMin -= MarginY;
						break;
					case Corner.Center:
						iconRect.xMin += 1.0f;
						iconRect.xMax = iconRect.xMin + MinHeight - 2.0f;
						iconRect.yMin += 1.0f;
						iconRect.yMax -= 1.0f;
						break;
				}
			}
			else
			{
				// The view is in grid mode
				float sizePercent = (aSelectionRect.width - MinWidth) / (MaxWidth - MinWidth);
				iconSize = Mathf.Round(Mathf.Lerp(IconMinSize, IconMaxSize, sizePercent));
				switch (aCorner)
				{
					case Corner.BottomRight:
						iconRect.xMin = iconRect.xMax - iconSize + MarginX;
						iconRect.yMin = iconRect.yMax - MinHeight - iconSize + MarginY;
						break;
					case Corner.BottomLeft:
						iconRect.xMin -= MarginX;
						iconRect.yMin = iconRect.yMax - MinHeight - iconSize + MarginY;
						break;
					case Corner.TopLeft:
						iconRect.xMin -= MarginX;
						iconRect.yMin -= MarginY;
						break;
					case Corner.TopRight:
						iconRect.xMin = iconRect.xMax - iconSize + MarginX;
						iconRect.yMin -= MarginY;
						break;
					case Corner.Center:
						iconRect.yMax -= MinHeight + 1.0f;
						iconRect.yMin += 2.0f;
						iconRect.xMin += 2.0f;
						iconRect.xMax -= 2.0f;
						break;
				}
			}
			if (aCorner != Corner.Center)
			{
				iconRect.width = iconSize;
				iconRect.height = iconSize;
			}
			return iconRect;
		}

        public static Texture GetChangelistIcon(Changelist change)
        {
            CheckInit();
            Texture asset;

            if (change.OwnerName == Config.Username && change.ClientId == Config.Workspace)
            {
                if (change.Shelved) { asset = IconChangeShelvedLocal; } else { asset = IconChangeLocal;  }
            }
            else
            {
                if (change.Shelved) { asset = IconChangeShelvedOther; } else { asset = IconChangeOther;  }
            }

            return asset;
        }

		static void CheckInit()
		{
			if (IconHasLatest == null)
			{
				Initialize();
			}
		}
	}
}
# Change User Description Committed
#1 12954 anis_sg Populate -o //guest/perforce_software/p4connect/...
//guest/anis_sg/perforce_software/p4connect/....
//guest/perforce_software/p4connect/src/P4Connect/P4Connect/P4Connect.Icons.cs
#5 12568 Norman Morse Fixed some error handling during Perforce Configuration
#4 12565 Norman Morse Integrated from Dev Branch
Made ChangeManager into Static Class.
Improved close window behavior for when connection is invalid
Fixed localOpenFiles not updating on submit
#3 12362 Norman Morse Added Debug Logging for p4log
Fixed some path comparison issues.
Created a CaseSensitivity test
#2 12135 Norman Morse Integrate dev branch changes into main.

This code is the basiis of the 2.7 BETA release which provides Unity 5 compatibility
#1 10940 Norman Morse Inital Workshop release of P4Connect.
Released under BSD-2 license