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 |
||