using UnityEditor;
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
using System.Linq;
using System.IO;
using Perforce.P4;
using log4net;
namespace P4Connect
{
[Serializable]
public class ConfigAsset : ScriptableObject
{
// These are the config values
// We serialize this Class and place it in the P4Connect/Editor Asset Hierarchy
public string ServerURI;
public string Username;
[HideInInspector]
public string Password;
public string Workspace;
public string Hostname;
public string Charset;
public bool UnityVSSupport;
public bool PerforceEnabled;
public bool IncludeProjectFiles;
public bool IncludeSolutionFiles;
public bool ShowPaths;
public bool AskBeforeCheckout;
public bool DisplayStatusIcons;
public string DiffToolPathname;
public bool DisplayP4Timings;
public bool DisplayP4Commands;
public bool CheckStatusForMenus;
public int CheckStatusForMenusMaxItems;
public int ConnectionTimeOut;
public bool WarnOnSpecialCharacters;
public string IgnoreName;
public bool EnableLog;
public Logger.LogLevel ConsoleLogLevel;
public string LogPath;
public string IgnoreLines;
// Copy the contents of this ConfigAsset into the P4Connect Config class.
public void CopyAssetToConfig()
{
Config.ServerURI = ServerURI;
Config.Username = Username;
Config.Password = Password;
Config.Workspace = Workspace;
Config.Hostname = Hostname;
Config.Charset = Charset;
Config.UnityVSSupport = UnityVSSupport;
Config.PerforceEnabled = PerforceEnabled;
Config.IncludeProjectFiles = IncludeProjectFiles;
Config.IncludeSolutionFiles = IncludeSolutionFiles;
Config.ShowPaths = ShowPaths;
Config.AskBeforeCheckout = AskBeforeCheckout;
Config.DisplayStatusIcons = DisplayStatusIcons;
Config.DiffToolPathname = DiffToolPathname;
Config.DisplayP4Timings = DisplayP4Timings;
Config.DisplayP4Commands = DisplayP4Commands;
Config.CheckStatusForMenus = CheckStatusForMenus;
Config.CheckStatusForMenusMaxItems = CheckStatusForMenusMaxItems;
Config.ConnectionTimeOut = ConnectionTimeOut;
Config.WarnOnSpecialCharacters = WarnOnSpecialCharacters;
Config.IgnoreName = IgnoreName;
Config.EnableLog = EnableLog;
Config.ConsoleLogLevel = ConsoleLogLevel;
Config.LogPath = LogPath;
Config.IgnoreLines = IgnoreLines;
}
// Seed a ConfigAsset with data from the Config Class
public void CopyConfigToAsset()
{
ServerURI = Config.ServerURI;
Username = Config.Username;
Password = Config.Password;
Workspace = Config.Workspace;
Hostname = Config.Hostname;
Charset = Config.Charset;
UnityVSSupport = Config.UnityVSSupport;
PerforceEnabled = Config.PerforceEnabled;
IncludeProjectFiles = Config.IncludeProjectFiles;
IncludeSolutionFiles = Config.IncludeSolutionFiles;
ShowPaths = Config.ShowPaths;
AskBeforeCheckout = Config.AskBeforeCheckout;
DisplayStatusIcons = Config.DisplayStatusIcons;
DiffToolPathname = Config.DiffToolPathname;
DisplayP4Timings = Config.DisplayP4Timings;
DisplayP4Commands = Config.DisplayP4Commands;
CheckStatusForMenus = Config.CheckStatusForMenus;
CheckStatusForMenusMaxItems = Config.CheckStatusForMenusMaxItems;
ConnectionTimeOut = Config.ConnectionTimeOut;
WarnOnSpecialCharacters = Config.WarnOnSpecialCharacters;
IgnoreName = Config.IgnoreName;
EnableLog = Config.EnableLog;
ConsoleLogLevel = Config.ConsoleLogLevel;
LogPath = Config.LogPath;
IgnoreLines = Config.IgnoreLines;
}
}
// This Editor window allows the user to set and store
// Perforce connection settings that will be used to
// Check out files on Save / Move / Delete / etc...
// The connection parameters are saved as Editor Preferences
// which means they go the registry.
public class Config : EditorWindow
{
private static readonly ILog log = LogManager.GetLogger(typeof(Config));
static string P4CONFIG_DEFAULT = ".p4config";
// Event triggered when the configuration changes
public delegate void OnPrefsChanged();
public static event OnPrefsChanged PrefsChanged;
#region Properties
// Give access to the Server URI
public static string ServerURI { get; set; }
// Give access to the User Name
public static string Username { get; set; }
// Give access to the Password
public static string Password { get; set; }
// Give access to the Workspace Name
public static string Workspace { get; set; }
// Give access to whether we integrate with UnityVS
public static bool UnityVSSupport { get; set; }
// Give access to whether the integration is turned on or not
public static bool PerforceEnabled { get; set; }
// Give access to whether we check out solution files
public static bool IncludeSolutionFiles { get; set; }
// Give access to whether we check out project files
public static bool IncludeProjectFiles { get; set; }
// Give access to whether we print out paths or just filenames
public static bool ShowPaths { get; set; }
// Give access to whether we automatically check out on edit
public static bool AskBeforeCheckout { get; set; }
// Give access to whether we want to display Icons in the Project view
public static bool DisplayStatusIcons { get; set; }
// The host name, if different than the local machine
public static string Hostname { get; set; }
// The host name, if different than the local machine
public static string Charset { get; set; }
// The location of the Diff tool
public static string DiffToolPathname { get; set; }
// Whether or not to display timing info for debugging
public static bool DisplayP4Timings { get; set; }
// Whether to display the commands sent to P4
public static bool DisplayP4Commands { get; set; }
// Whether or not to check the status of files before showing the contextual menu
public static bool CheckStatusForMenus { get; set; }
// Whether or not to warn when adding files with special characters
public static bool WarnOnSpecialCharacters { get; set; }
// Whether or not to check the status of files before showing the contextual menu
public static int CheckStatusForMenusMaxItems { get; set; }
// How many files to submit at once
public static int OperationBatchCount { get; set; }
// How long to keep connections open
public static int ConnectionTimeOut { get; set; }
// Provide an Ignore file name
public static string IgnoreName { get; set; }
// Additional Ignore Lines
public static string IgnoreLines { get; set; }
// Enable log4net Logging
public static bool EnableLog { get; set; }
// What log level to display in the console?
public static Logger.LogLevel ConsoleLogLevel { get; set; }
// Where to save log output
public static string LogPath { get; set; }
#endregion
static bool FoundConfigAsset;
// Helper property to indicate that P4 can be used
public static bool ValidConfiguration
{
get { return PerforceEnabled && _CurrentState == ConfigurationState.SettingsValid; }
}
public const string P4BridgeDLLName = "p4bridge.dll";
public const string P4BridgeDYLIBName = "libp4bridge.dylib";
public const int MaxPendingItems = 200;
#region Registry Names
// These are the names under which the connection settings are stored in the registry
public const string ServerURIPrefName = "ServerURI";
public const string UserNamePrefName = "UserName";
public const string PasswordPrefName = "Password";
public const string WorkspacePrefName = "Workspace";
public const string PerforceEnabledPrefName = "Enabled";
public const string UnityVSSupportPrefName = "UnityVSSupport";
public const string IncludeProjectFilesPrefName = "IncludeProjectFiles";
public const string IncludeSolutionFilesPrefName = "IncludeSolutionFiles";
public const string ShowPathsPrefName = "ShowPaths";
public const string AskBeforeCheckoutPrefName = "AskBeforeCheckout";
public const string DisplayStatusIconsPrefName = "DisplayStatusIcons";
public const string HostnamePrefName = "Hostname";
public const string DiffToolPathnamePrefName = "DiffToolPathname";
public const string DisplayP4TimingsPrefName = "DisplayTimings";
public const string DisplayP4CommandsPrefName = "DisplayCommands";
public const string CheckStatusForMenusPrefName = "CheckStatusForMenus";
public const string CheckStatusForMenusMaxItemsPrefName = "CheckStatusForMenusMaxItems";
public const string OperationBatchCountPrefName = "OperationBatchCount";
public const string ConnectionTimeOutPrefName = "ConnectionTimeOut";
public const string WarnOnSpecialCharactersPrefName = "WarnOnSpecialCharacters";
public const string UseIgnorePrefName = "UseIgnore";
public const string IgnoreNamePrefName = "IgnoreName";
public const string EnableLogPrefName = "EnableLog";
public const string ConsoleLogLevelPrefName = "ConsoleLogLevel";
public const string LogPathPrefName = "LogPath";
public const string IgnoreLinesPrefName = "IgnoreLines";
#endregion
// The current state of the configuration, whether it is valid to be used
enum ConfigurationState
{
Unknown = 0,
MetaFilesInvalid,
MetaFilesValid,
ServerInvalid,
ServerValid,
UsernamePassInvalid,
UsernamePassValid,
WorkspaceInvalid,
WorkspaceValid,
ProjectRootInvalid,
ProjectRootValid,
SettingsValid,
}
// The current state of the configuration, whether it is valid to be used
static ConfigurationState _CurrentState = ConfigurationState.Unknown;
bool _Repaint = false;
///
/// Set some default configuration values
///
static Config() // Config Window Constructor
{
Initialize();
}
static void ResetValues()
{
Debug.Log("ResetValues");
// Set some default values
ServerURI = "localhost:1666";
Username = Environment.UserName;
Password = "";
Workspace = Username + "_" + Main.ProjectName + "_" + Environment.MachineName;
UnityVSSupport = false;
PerforceEnabled = true;
IncludeProjectFiles = false;
IncludeSolutionFiles = false;
ShowPaths = false;
AskBeforeCheckout = false;
DisplayStatusIcons = true;
Hostname = "";
Charset = "";
DiffToolPathname = "";
DisplayP4Timings = false;
DisplayP4Commands = false;
CheckStatusForMenus = true;
CheckStatusForMenusMaxItems = 10;
ConnectionTimeOut = 30;
WarnOnSpecialCharacters = true;
FoundConfigAsset = false;
IgnoreName = "";
IgnoreLines = "";
EnableLog = false;
LogPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\p4connect.log";
ConsoleLogLevel = Logger.LogLevel.Info;
}
static Config window = null;
// Add menu item to show the configuration panel
[MenuItem("Edit/Perforce Settings", false, 300)]
public static void ShowWindow()
{
// Show existing window instance. If one doesn't exist, make one.
window = EditorWindow.GetWindow("P4 Settings");
window.name = "P4 Settings";
window.title = "P4 Settings";
window.minSize = new UnityEngine.Vector2(500.0f, 500.0f);
}
public static void Refresh()
{
if (window != null)
window.Repaint();
}
///
/// Static Constructor, reads connection settings from Prefs at least once
///
public static void Initialize()
{
FoundConfigAsset = readConfigAsset();
if (!FoundConfigAsset)
{
Debug.Log("Loading Configuration from EditorPrefs");
ReadPrefs();
}
CachedSerializationMode = EditorSettings.serializationMode;
Refresh();
}
///
/// Checks the that settings are valid
///
public static void CheckSettings()
{
if (PerforceEnabled)
{
// We only display a message when something changes
ConfigurationState prevState = _CurrentState;
_CurrentState = ConfigurationState.Unknown;
UpdateConfigState(true); // Run config state machine
// If the state is different then when we started
if (_CurrentState != prevState)
{
Icons.UpdateDisplay();
if (_CurrentState != ConfigurationState.SettingsValid)
{
Debug.LogWarning("P4Connect - Perforce integration is enabled but inactive. Go to Edit->Perforce Settings to update your settings");
}
else if (prevState != ConfigurationState.SettingsValid)
{
Debug.Log("P4Connect - Perforce Integration is Active");
}
}
//if (_CurrentState == ConfigurationState.SettingsValid)
//{
// SetProjectRootDirectory();
//}
}
}
///
/// Updates the current configuration state after checking all the settings
///
public static void UpdateConfigState(bool fast)
{
try
{
switch (_CurrentState)
{
case ConfigurationState.Unknown:
// The unknown state starts by checking the meta files
goto case ConfigurationState.MetaFilesInvalid;
case ConfigurationState.MetaFilesInvalid:
EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Meta Files", 0.2f);
if (P4Connect.VerifySettings.CheckMetaFiles())
{
// Meta files are valid, move on
_CurrentState = ConfigurationState.MetaFilesValid;
goto case ConfigurationState.MetaFilesValid;
}
else
{
// Stay in this state
_CurrentState = ConfigurationState.MetaFilesInvalid;
break;
}
case ConfigurationState.MetaFilesValid:
if (fast)
{
goto case ConfigurationState.ProjectRootInvalid; // jump ahead for a quick connection
}
goto case ConfigurationState.ServerInvalid;
case ConfigurationState.ServerInvalid:
EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Server", 0.4f);
if (P4Connect.VerifySettings.CheckServerURI())
{
Debug.Log("ServerValid");
// Server is valid, move on
_CurrentState = ConfigurationState.ServerValid;
goto case ConfigurationState.ServerValid;
}
else
{
Debug.Log("ServerInvalid");
// Stay here
_CurrentState = ConfigurationState.ServerInvalid;
break;
}
case ConfigurationState.ServerValid:
goto case ConfigurationState.UsernamePassInvalid;
case ConfigurationState.UsernamePassInvalid:
EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Login", 0.6f);
if (P4Connect.VerifySettings.CheckUsernamePassword())
{
// Username / Password is valid, move on
_CurrentState = ConfigurationState.UsernamePassValid;
goto case ConfigurationState.UsernamePassValid;
}
else
{
// Stay here
_CurrentState = ConfigurationState.UsernamePassInvalid;
break;
}
case ConfigurationState.UsernamePassValid:
goto case ConfigurationState.WorkspaceInvalid;
case ConfigurationState.WorkspaceInvalid:
EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Workspace", 0.8f);
if (P4Connect.VerifySettings.CheckWorkspace())
{
// Workspace is valid
_CurrentState = ConfigurationState.WorkspaceValid;
goto case ConfigurationState.WorkspaceValid;
}
else
{
// Stay here
_CurrentState = ConfigurationState.WorkspaceInvalid;
break;
}
case ConfigurationState.WorkspaceValid:
goto case ConfigurationState.ProjectRootInvalid;
case ConfigurationState.ProjectRootInvalid:
EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Project Root", 0.9f);
if (P4Connect.VerifySettings.CheckProjectRoot())
{
// Root is valid
_CurrentState = ConfigurationState.ProjectRootValid;
goto case ConfigurationState.ProjectRootValid;
}
else
{
// Stay here
_CurrentState = ConfigurationState.ProjectRootInvalid;
break;
}
case ConfigurationState.ProjectRootValid:
_CurrentState = ConfigurationState.SettingsValid;
goto case ConfigurationState.SettingsValid;
case ConfigurationState.SettingsValid:
break;
}
EditorUtility.ClearProgressBar();
if (_CurrentState != ConfigurationState.SettingsValid)
{
string msg = String.Format("Bad Settings, current state is {0}", _CurrentState.ToString());
EditorUtility.DisplayDialog("p4connect", msg, "Ok");
}
}
catch(Exception ex)
{
log.Debug("exception", ex);
}
}
public static void SetProjectRootDirectory()
{
if (Config.ValidConfiguration)
{
Engine.PerformConnectionOperation(con =>
{
// project root in perforce syntax
var spec = FileSpec.LocalSpec(System.IO.Path.Combine(Main.RootPath, "..."));
//log.DebugFormat("spec: {0}", spec.ToString());
var mappings = con.P4Client.GetClientFileMappings(spec);
//log.DebugFormat("mappings: {0}", Logger.FileSpecListToString(mappings));
if (mappings != null && mappings.Count > 0)
{
// string ProjectRoot;
string clientProjectRoot = mappings[0].ClientPath.Path;
//log.DebugFormat("clientProjectRoot: {0} ", clientProjectRoot);
int projectRootOffset = clientProjectRoot.ToLowerInvariant().IndexOf(Config.Workspace.ToLowerInvariant());
//log.DebugFormat("projectRootOffset: {0}", projectRootOffset);
if (projectRootOffset != -1)
{
//ProjectRoot = clientProjectRoot.Substring(projectRootOffset + Config.Workspace.Length);
//log.DebugFormat("ProjectRoot1: {0} ", ProjectRoot);
//ProjectRoot = ProjectRoot.TrimStart(System.IO.Path.DirectorySeparatorChar, '/');
//if (ProjectRoot.EndsWith("..."))
// ProjectRoot = ProjectRoot.Substring(0, ProjectRoot.Length - 3);
//ProjectRoot = ProjectRoot.TrimEnd(System.IO.Path.DirectorySeparatorChar, '/');
//ProjectRoot = ProjectRoot.Replace('/', System.IO.Path.DirectorySeparatorChar);
//log.Debug("SetProjectRootDirectory - ProjectRoot: " + ProjectRoot);
}
else
{
Debug.LogError("P4Connect - Your Project does not appear to be under your workspace root.");
}
}
});
}
}
// static objects frequently used to create controls
static GUILayoutOption _BoxWidth = GUILayout.MaxWidth(200.0f);
static GUILayoutOption _EnumWidth = GUILayout.Width(75.0f);
static GUILayoutOption _CheckWidth = GUILayout.Width(16.0f);
static GUILayoutOption _TextWidth = GUILayout.Width(250.0f);
static GUILayoutOption _ButtonWidth = GUILayout.Width(80.0f);
static GUILayoutOption _IntWidth = GUILayout.Width(30.0f);
int _FrameIndex = 0;
int _MaxFrameCount = 3; // seems to be the right number of repaints needed to display something
//Vector2 scroll = new Vector2(0,0); // Track scroll position in the additional ignore TextArea
///
/// Called by Unity when the windows needs to be updated
///
void OnGUI()
{
EditorGUILayout.BeginVertical(); // Main Window over status
// A global checkbox to turn perforce integration on/off
bool newPerforceEnabled = EditorGUILayout.BeginToggleGroup("Enable Perforce Integration", PerforceEnabled);
// Check for a changed value
if (newPerforceEnabled != PerforceEnabled)
{
PerforceEnabled = newPerforceEnabled;
if (PerforceEnabled)
{
if (_FrameIndex >= _MaxFrameCount) // UI has been running a while
{
CheckSettings();
}
}
}
if (PerforceEnabled)
{
if (_FrameIndex < _MaxFrameCount) // UI was just created, need to wait a bit before display updates
{
if (Event.current.type == EventType.Repaint)
{
++_FrameIndex;
_Repaint = true;
}
}
if (_FrameIndex == _MaxFrameCount)
{
CheckSettings(); // Delayed a few frames, now we try to connect.
++_FrameIndex;
}
EditorGUILayout.BeginHorizontal(); // Main Window
EditorGUILayout.BeginVertical(); // Left panel
{
EditorGUILayout.BeginVertical("box"); // Load Settings
GUILayout.Label("Load Settings");
EditorGUI.BeginDisabledGroup(_CurrentState == ConfigurationState.SettingsValid);
{
if (GUILayout.Button("Load Defaults", EditorStyles.miniButton, _BoxWidth))
{
ResetValues();
_CurrentState = ConfigurationState.Unknown;
Repaint();
}
if (GUILayout.Button("Load P4 Environment", EditorStyles.miniButton, _BoxWidth))
{
if (!ReadEnvironment())
{
EditorUtility.DisplayDialog("Read Perforce Environment", "No Perforce Environment variables found!", "OK");
}
_CurrentState = ConfigurationState.Unknown;
Repaint();
}
if (GUILayout.Button("Load P4Config", EditorStyles.miniButton, _BoxWidth))
{
string configName = Environment.GetEnvironmentVariable("P4CONFIG");
if (string.IsNullOrEmpty(configName))
{
configName = P4CONFIG_DEFAULT; // If not in environment, use the default.
}
string p4configFile = FindP4ConfigFile(configName);
if (string.IsNullOrEmpty(p4configFile))
{
Debug.Log("P4Config file " + configName + " Not Found");
}
else
{
LoadP4ConfigFile(p4configFile);
Debug.Log("P4Config Found at: " + Path.GetFullPath(p4configFile));
}
_CurrentState = ConfigurationState.Unknown;
Repaint();
}
if (GUILayout.Button("Load Editor Prefs", EditorStyles.miniButton, _BoxWidth))
{
ReadPrefs();
_CurrentState = ConfigurationState.Unknown;
Repaint();
}
if (GUILayout.Button("Load Config Asset", EditorStyles.miniButton, _BoxWidth))
{
if (!readConfigAsset())
{
EditorUtility.DisplayDialog("Read Configuration Asset", "No Configuration Asset found!", "OK");
}
_CurrentState = ConfigurationState.Unknown;
Repaint();
}
}
EditorGUI.EndDisabledGroup(); // Settings Valid
EditorGUILayout.EndVertical(); // Load Settings
GUILayout.FlexibleSpace();
EditorGUILayout.BeginVertical("box"); // Save Settings
GUILayout.Label("Save Settings");
if (GUILayout.Button("Clear Editor Prefs", EditorStyles.miniButton, _BoxWidth))
{
if (EditorUtility.DisplayDialog("Remove All EditorPrefs",
"Are you sure you want to remove ALL editorPrefs?", "OK", "Cancel"))
{
EditorPrefs.DeleteAll();
//DeleteAllEditorPrefs(); // This call doesn't work on all entries! Unity Bug?
}
}
if (GUILayout.Button("Save EditorPrefs", EditorStyles.miniButton, _BoxWidth))
{
WritePrefs();
}
if (GUILayout.Button("Save Config Asset", EditorStyles.miniButton, _BoxWidth))
{
writeConfigAsset();
}
if (GUILayout.Button("Delete Config Asset", EditorStyles.miniButton, _BoxWidth))
{
if (EditorUtility.DisplayDialog("Delete Configuration Asset",
"Are you sure you want to delete this configuration?", "OK", "Cancel"))
{
deleteConfigAsset();
}
}
EditorGUILayout.EndVertical(); // Save Settings
}
EditorGUILayout.EndVertical(); // left panel
EditorGUILayout.BeginVertical(); // The right panel
GUILayout.BeginVertical("Box"); // connection box
GUILayout.Label("Connection Settings", EditorStyles.boldLabel);
// Disable connection settings if already connected
EditorGUI.BeginDisabledGroup(_CurrentState == ConfigurationState.SettingsValid);
{
EditorGUILayout.BeginHorizontal();
{
// The edit field for the server
ServerURI = EditorGUILayout.TextField("\tServer URI", ServerURI);
}
EditorGUILayout.EndHorizontal();
if (_CurrentState == ConfigurationState.ServerInvalid)
{
EditorGUILayout.HelpBox("Invalid Server URI", MessageType.Error);
}
EditorGUILayout.BeginHorizontal();
{
Username = EditorGUILayout.TextField("\tUsername", Username);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
{
Password = EditorGUILayout.PasswordField("\tPassword", Password);
}
EditorGUILayout.EndHorizontal();
if (_CurrentState == ConfigurationState.UsernamePassInvalid)
{
EditorGUILayout.HelpBox("Invalid Username / Password", MessageType.Error);
}
EditorGUILayout.BeginHorizontal();
{
Workspace = EditorGUILayout.TextField("\tWorkspace", Workspace);
}
EditorGUILayout.EndHorizontal();
if (_CurrentState == ConfigurationState.WorkspaceInvalid)
{
EditorGUILayout.HelpBox("Invalid Workspace", MessageType.Error);
}
if (_CurrentState == ConfigurationState.ProjectRootInvalid)
{
// The project isn't under the workspace root
string perforcePath = "//" + Workspace + "/...";
string rootPath = P4Connect.Main.RootPath;
EditorGUILayout.HelpBox("Invalid Workspace. The client path:\n" +
"\t" + perforcePath + "\n" +
"maps to this folder:\n" +
"\t" + VerifySettings.LastWorkspaceMapping + "\n" +
"which is not a parent directory of the project's root:\n" +
"\t" + rootPath, MessageType.Error);
}
EditorGUILayout.BeginHorizontal();
{
Hostname = EditorGUILayout.TextField("\tP4HOST", Hostname);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
{
Charset = EditorGUILayout.TextField("\tP4CHARSET", Charset);
}
EditorGUILayout.EndHorizontal();
}
EditorGUI.EndDisabledGroup(); // Connection Valid
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button((_CurrentState == ConfigurationState.SettingsValid ? "Disconnect" : "Connect"),
EditorStyles.miniButton, _BoxWidth))
{
if (_CurrentState == ConfigurationState.SettingsValid)
{
_CurrentState = ConfigurationState.Unknown;
}
else
{
EditorGUILayout.HelpBox("Please Wait! Checking Perforce Settings. This can take a while ...", MessageType.Info);
CheckSettings();
}
}
EditorGUILayout.EndHorizontal();
GUILayout.EndVertical(); // Connection Box
GUILayout.Label("Interface", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("\tDisplay Status Icons", _TextWidth);
DisplayStatusIcons = EditorGUILayout.Toggle(DisplayStatusIcons, _CheckWidth);
GUILayout.Label("\tShow File Paths in Console", _TextWidth);
ShowPaths = EditorGUILayout.Toggle(ShowPaths, _CheckWidth);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("\tGray out invalid menu options", _TextWidth);
CheckStatusForMenus = EditorGUILayout.Toggle(CheckStatusForMenus, _CheckWidth);
GUILayout.Label("Don't check if more than");
CheckStatusForMenusMaxItems = EditorGUILayout.IntField(CheckStatusForMenusMaxItems, _IntWidth);
GUILayout.Label("files selected");
GUILayout.FlexibleSpace();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("\tDiff Tool Executable", _TextWidth);
DiffToolPathname = EditorGUILayout.TextField("", DiffToolPathname);
if (GUILayout.Button("Browse...", EditorStyles.miniButton, _ButtonWidth))
{
string dir;
string path;
GUI.FocusControl("");
if (DiffToolPathname.Length > 0)
{
dir = System.IO.Directory.GetParent(DiffToolPathname).FullName;
}
else
{
dir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles);
}
path = EditorUtility.OpenFilePanel("Choose Diff Tool Executable", dir, "");
if (path.Length > 0)
{
DiffToolPathname = path;
}
}
}
EditorGUILayout.EndHorizontal();
GUILayout.Label("Behaviour", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("\tAsk before checkout on edit", _TextWidth);
AskBeforeCheckout = EditorGUILayout.Toggle(AskBeforeCheckout, _CheckWidth);
}
GUILayout.Label("\tReserved character warning (@#*%)", _TextWidth);
WarnOnSpecialCharacters = EditorGUILayout.Toggle(WarnOnSpecialCharacters, _CheckWidth);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
GUILayout.Label("\tInclude Solution Files", _TextWidth);
IncludeSolutionFiles = EditorGUILayout.Toggle(IncludeSolutionFiles, _CheckWidth);
GUILayout.Label("\tInclude Project Files", _TextWidth);
IncludeProjectFiles = EditorGUILayout.Toggle(IncludeProjectFiles, _CheckWidth);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
GUILayout.Label("\tIntegrate with UnityVS", _TextWidth);
UnityVSSupport = EditorGUILayout.Toggle(UnityVSSupport, _CheckWidth);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("\tClose Perforce connection after");
ConnectionTimeOut = EditorGUILayout.IntField(ConnectionTimeOut, _IntWidth);
GUILayout.Label("seconds");
GUILayout.FlexibleSpace();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("\tP4IGNORE", _TextWidth);
IgnoreName = EditorGUILayout.TextField(IgnoreName);
if (GUILayout.Button("Browse...", EditorStyles.miniButton, _ButtonWidth))
{
string dir;
string path;
GUI.FocusControl("");
if (IgnoreName.Length > 0)
{
dir = System.IO.Directory.GetParent(IgnoreName).FullName;
}
else
{
dir = Main.RootPath;
}
path = EditorUtility.OpenFilePanel("Choose P4Ignore File", dir, "");
if (path.Length > 0)
{
IgnoreName = path;
}
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("\tAdditional Ignore Lines", _TextWidth);
//scroll = EditorGUILayout.BeginScrollView(scroll, GUILayout.Width(pathWidth + 10.0f), GUILayout.MaxHeight(50.0f));
//scroll = EditorGUILayout.BeginScrollView(scroll);
IgnoreLines = EditorGUILayout.TextArea(IgnoreLines, GUILayout.MinHeight(16.0f), GUILayout.MinWidth(200.0f));
//EditorGUILayout.EndScrollView();
}
EditorGUILayout.EndHorizontal();
GUILayout.Label("Advanced", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
GUILayout.Label("\tDisplay P4 Timings", _TextWidth);
DisplayP4Timings = EditorGUILayout.Toggle(DisplayP4Timings, _CheckWidth);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("\tEnable Logging", _TextWidth);
bool newEnableLog = EditorGUILayout.Toggle(EnableLog, _CheckWidth);
GUILayout.Label("Console Log Level: ");
ConsoleLogLevel = (Logger.LogLevel)EditorGUILayout.EnumPopup(ConsoleLogLevel, _EnumWidth);
GUILayout.FlexibleSpace();
if (newEnableLog != EnableLog)
{
EnableLog = newEnableLog;
Logger.Initialize();
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("\tLog File", _TextWidth);
LogPath = EditorGUILayout.TextField(LogPath);
if (GUILayout.Button("Browse...", EditorStyles.miniButton, _ButtonWidth))
{
string dir;
string path;
GUI.FocusControl("");
if (LogPath.Length > 0)
{
dir = System.IO.Directory.GetParent(LogPath).FullName;
}
else
{
dir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory);
}
path = EditorUtility.SaveFilePanel("Set P4Connect Log File", dir, "p4connect", "log");
if (path.Length > 0)
{
LogPath = path;
EnableLog = true;
}
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical(); // Right Panel
EditorGUILayout.EndHorizontal(); // Main Window
} // If PerforceEnabled
EditorGUILayout.EndToggleGroup();
// Status lines
if (PerforceEnabled)
{
if (_CurrentState == ConfigurationState.MetaFilesInvalid)
{
EditorGUILayout.HelpBox("You must set the Editor Version Control to \"Meta Files\" under Edit->Project Settings->Editor", MessageType.Warning);
}
else if (_CurrentState != ConfigurationState.SettingsValid)
{
EditorGUILayout.HelpBox("Perforce Integration is INACTIVE. Please Verify your Settings!", MessageType.Warning);
}
else
{
EditorGUILayout.HelpBox("Perforce Integration is ACTIVE.", MessageType.Info);
}
}
else
{
EditorGUILayout.HelpBox("Perforce Integration is DISABLED.", MessageType.Info);
}
// Display the bottom "Status" line
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Project: " + Main.RootPath);
GUILayout.FlexibleSpace();
GUILayout.Label("P4Connect " + Version.p4ConnectVersion + " " + Version.build, EditorStyles.miniLabel);
if (GUILayout.Button("Visit Website", EditorStyles.miniButton))
{
System.Diagnostics.Process.Start("http://www.perforce.com/perforce/doc.current/manuals/p4connectguide/index.html");
}
EditorGUILayout.EndHorizontal(); // bottom line
EditorGUILayout.EndVertical(); // Main Window over status
}
void OnSelectionChange()
{
// UnityEngine.Object cursel = Selection.activeObject;
}
void OnInspectorUpdate()
{
if (_Repaint)
{
_Repaint = false;
Repaint();
}
}
// Check for the "well known" Perforce environment variables.
public static bool ReadEnvironment()
{
string value;
bool found = false;
value = Environment.GetEnvironmentVariable("P4PORT");
if (value != null)
{
Config.ServerURI = value;
found = true;
}
value = Environment.GetEnvironmentVariable("P4USER");
if (value != null)
{
Config.Username = value;
found = true;
}
value = Environment.GetEnvironmentVariable("P4PASSWD");
if (value != null)
{
Config.Password = value;
found = true;
}
value = Environment.GetEnvironmentVariable("P4CLIENT");
if (value != null)
{
Config.Workspace = value;
found = true;
}
value = Environment.GetEnvironmentVariable("P4HOST");
if (value != null)
{
Config.Hostname = value;
found = true;
}
value = Environment.GetEnvironmentVariable("P4CHARSET");
if (value != null)
{
Config.Charset = value;
found = true;
}
value = Environment.GetEnvironmentVariable("P4IGNORE");
if (value != null)
{
Config.IgnoreName = value;
found = true;
}
Config.Refresh();
return found;
}
#region EditorPreferences
// Utility method to read connection prefs from the registry
public static void ReadPrefs()
{
// Check if the keys exist, and if so, read the values out
// Otherwise, leave the existing values
if (HasStringPrefNotEmpty(ServerURIPrefName))
ServerURI = GetPrefString(ServerURIPrefName);
if (HasStringPrefNotEmpty(UserNamePrefName))
Username = GetPrefString(UserNamePrefName);
if (HasStringPrefNotEmpty(PasswordPrefName))
{
// Password = Secure.DecryptString(GetPrefString(PasswordPrefName));
Password = GetPrefString(PasswordPrefName);
}
if (HasStringPrefNotEmpty(WorkspacePrefName))
Workspace = GetPrefString(WorkspacePrefName);
if (HasPref(UnityVSSupportPrefName))
UnityVSSupport = GetPrefBool(UnityVSSupportPrefName);
if (HasPref(IncludeProjectFilesPrefName))
IncludeProjectFiles = GetPrefBool(IncludeProjectFilesPrefName);
if (HasPref(IncludeSolutionFilesPrefName))
IncludeSolutionFiles = GetPrefBool(IncludeSolutionFilesPrefName);
if (HasPref(ShowPathsPrefName))
ShowPaths = GetPrefBool(ShowPathsPrefName);
if (HasPref(AskBeforeCheckoutPrefName))
AskBeforeCheckout = GetPrefBool(AskBeforeCheckoutPrefName);
if (HasPref(DisplayStatusIconsPrefName))
DisplayStatusIcons = GetPrefBool(DisplayStatusIconsPrefName);
if (HasStringPrefNotEmpty(HostnamePrefName))
Hostname = GetPrefString(HostnamePrefName);
if (HasStringPrefNotEmpty(DiffToolPathnamePrefName))
DiffToolPathname = GetPrefString(DiffToolPathnamePrefName);
if (HasPref(DisplayP4TimingsPrefName))
DisplayP4Timings = GetPrefBool(DisplayP4TimingsPrefName);
if (HasPref(DisplayP4CommandsPrefName))
DisplayP4Commands = GetPrefBool(DisplayP4CommandsPrefName);
if (HasPref(CheckStatusForMenusPrefName))
CheckStatusForMenus = GetPrefBool(CheckStatusForMenusPrefName);
if (HasPref(CheckStatusForMenusMaxItemsPrefName))
CheckStatusForMenusMaxItems = GetPrefInt(CheckStatusForMenusMaxItemsPrefName);
if (HasPref(OperationBatchCountPrefName))
OperationBatchCount = GetPrefInt(OperationBatchCountPrefName);
if (HasPref(ConnectionTimeOutPrefName))
ConnectionTimeOut = GetPrefInt(ConnectionTimeOutPrefName);
if (HasPref(WarnOnSpecialCharactersPrefName))
WarnOnSpecialCharacters = GetPrefBool(WarnOnSpecialCharactersPrefName);
if (HasStringPrefNotEmpty(IgnoreNamePrefName))
IgnoreName = GetPrefString(IgnoreNamePrefName);
if (HasStringPrefNotEmpty(IgnoreLinesPrefName))
IgnoreLines = GetPrefString(IgnoreLinesPrefName);
if (HasPref(EnableLogPrefName))
EnableLog = GetPrefBool(EnableLogPrefName);
if (HasPref(ConsoleLogLevelPrefName))
ConsoleLogLevel = (Logger.LogLevel)GetPrefInt(ConsoleLogLevelPrefName);
if (HasStringPrefNotEmpty(LogPathPrefName))
LogPath = GetPrefString(LogPathPrefName);
Config.Refresh();
// Notify users that prefs changed
if (PrefsChanged != null)
PrefsChanged();
}
// Utility method to write our the connection prefs to the registry
public static void WritePrefs()
{
SetPrefString(ServerURIPrefName, ServerURI);
SetPrefString(UserNamePrefName, Username);
if (!String.IsNullOrEmpty(Password))
{
SetPrefString(PasswordPrefName, Password);
// SetPrefString(PasswordPrefName, Secure.EncryptString(Password)); // Crashes Unity!
}
SetPrefString(WorkspacePrefName, Workspace);
SetPrefBool(PerforceEnabledPrefName, PerforceEnabled);
SetPrefBool(UnityVSSupportPrefName, UnityVSSupport);
SetPrefBool(IncludeProjectFilesPrefName, IncludeProjectFiles);
SetPrefBool(IncludeSolutionFilesPrefName, IncludeSolutionFiles);
SetPrefBool(ShowPathsPrefName, ShowPaths);
SetPrefBool(AskBeforeCheckoutPrefName, AskBeforeCheckout);
SetPrefBool(DisplayStatusIconsPrefName, DisplayStatusIcons);
SetPrefString(HostnamePrefName, Hostname);
SetPrefString(DiffToolPathnamePrefName, DiffToolPathname);
SetPrefBool(DisplayP4TimingsPrefName, DisplayP4Timings);
SetPrefBool(DisplayP4CommandsPrefName, DisplayP4Commands);
SetPrefBool(CheckStatusForMenusPrefName, CheckStatusForMenus);
SetPrefInt(CheckStatusForMenusMaxItemsPrefName, CheckStatusForMenusMaxItems);
SetPrefInt(OperationBatchCountPrefName, OperationBatchCount);
SetPrefInt(ConnectionTimeOutPrefName, ConnectionTimeOut);
SetPrefBool(WarnOnSpecialCharactersPrefName, WarnOnSpecialCharacters);
SetPrefString(IgnoreNamePrefName, IgnoreName);
SetPrefString(IgnoreLinesPrefName, IgnoreLines);
SetPrefBool(EnableLogPrefName, EnableLog);
SetPrefInt(ConsoleLogLevelPrefName, (int)ConsoleLogLevel);
SetPrefString(LogPathPrefName, LogPath);
}
static string GetFullPrefName(string aPrefName)
{
return "P4Connect_" + Main.ProjectName + "_" + aPrefName;
}
static bool HasPref(string aPrefName)
{
return EditorPrefs.HasKey(GetFullPrefName(aPrefName));
}
static bool HasStringPrefNotEmpty(string aPrefName)
{
return (!String.IsNullOrEmpty(EditorPrefs.GetString(GetFullPrefName(aPrefName))));
}
static void SetPrefString(string aPrefName, string aPref)
{
EditorPrefs.SetString(GetFullPrefName(aPrefName), aPref);
}
static void SetPrefInt(string aPrefName, int aPref)
{
EditorPrefs.SetInt(GetFullPrefName(aPrefName), aPref);
}
static void SetPrefBool(string aPrefName, bool aPref)
{
EditorPrefs.SetBool(GetFullPrefName(aPrefName), aPref);
}
static string GetPrefString(string aPrefName)
{
return EditorPrefs.GetString(GetFullPrefName(aPrefName));
}
static int GetPrefInt(string aPrefName)
{
return EditorPrefs.GetInt(GetFullPrefName(aPrefName));
}
static bool GetPrefBool(string aPrefName)
{
return EditorPrefs.GetBool(GetFullPrefName(aPrefName));
}
// [MenuItem("Edit/Delete Project EditorPrefs", false, 300)]
static void DeleteAllEditorPrefs()
{
Debug.Log("DeletePrefs()");
// Delete All keys for this project
EditorPrefs.DeleteKey(ServerURIPrefName);
EditorPrefs.DeleteKey(UserNamePrefName);
EditorPrefs.DeleteKey(PasswordPrefName);
EditorPrefs.DeleteKey(WorkspacePrefName);
EditorPrefs.DeleteKey(UnityVSSupportPrefName);
EditorPrefs.DeleteKey(IncludeProjectFilesPrefName);
EditorPrefs.DeleteKey(IncludeSolutionFilesPrefName);
EditorPrefs.DeleteKey(ShowPathsPrefName);
EditorPrefs.DeleteKey(AskBeforeCheckoutPrefName);
EditorPrefs.DeleteKey(DisplayStatusIconsPrefName);
EditorPrefs.DeleteKey(HostnamePrefName);
EditorPrefs.DeleteKey(DiffToolPathnamePrefName);
EditorPrefs.DeleteKey(DisplayP4TimingsPrefName);
EditorPrefs.DeleteKey(DisplayP4CommandsPrefName);
EditorPrefs.DeleteKey(CheckStatusForMenusPrefName);
EditorPrefs.DeleteKey(CheckStatusForMenusMaxItemsPrefName);
EditorPrefs.DeleteKey(OperationBatchCountPrefName);
EditorPrefs.DeleteKey(ConnectionTimeOutPrefName);
EditorPrefs.DeleteKey(WarnOnSpecialCharactersPrefName);
EditorPrefs.DeleteKey(IgnoreNamePrefName);
EditorPrefs.DeleteKey(IgnoreLinesPrefName);
EditorPrefs.DeleteKey(EnableLogPrefName);
EditorPrefs.DeleteKey(ConsoleLogLevelPrefName);
}
#endregion
public static SerializationMode CachedSerializationMode
{
get;
private set;
}
#region P4CONFIG
public static string FindP4ConfigFile(string config)
{
string directoryName;
if (!String.IsNullOrEmpty(config))
{
string path = Application.dataPath;
while (path != null)
{
directoryName = Path.GetDirectoryName(path);
if (!String.IsNullOrEmpty(directoryName))
{
string[] files = System.IO.Directory.GetFiles(directoryName, config);
if (files.Count() > 0)
{
return files[0];
}
}
path = directoryName;
}
}
return null;
}
public static void LoadP4ConfigFile(string path)
{
string line;
char[] equalsChars = { '=' };
System.IO.StreamReader file = new System.IO.StreamReader(path);
while ((line = file.ReadLine()) != null)
{
string[] segments = line.Split(equalsChars);
if (segments.Length >= 2)
{
string key = segments[0];
string val = segments[1];
switch (segments[0])
{
case "P4PORT":
{
ServerURI = val;
}
break;
case "P4USER":
{
Username = val;
}
break;
case "P4CLIENT":
{
Workspace = val;
}
break;
case "P4PASSWD":
{
Password = val;
}
break;
case "P4HOST":
{
Hostname = val;
}
break;
case "P4CHARSET":
{
Charset = val;
}
break;
}
}
}
file.Close();
}
#endregion
#region ConfigAsset
static string configAssetPath = "Assets/P4Connect/Editor/Config.asset";
public static void writeConfigAsset()
{
ConfigAsset asset = ScriptableObject.CreateInstance();
asset.CopyConfigToAsset();
AssetDatabase.CreateAsset(asset, configAssetPath);
AssetDatabase.SaveAssets();
}
public static bool readConfigAsset()
{
ConfigAsset asset = AssetDatabase.LoadAssetAtPath(configAssetPath, (typeof(ConfigAsset))) as ConfigAsset;
if (asset != null)
{
Debug.Log("Loaded Asset");
asset.CopyAssetToConfig();
Config.Refresh();
return true;
}
else
{
Debug.Log("Failed to Load Asset");
return false;
}
}
public static void deleteConfigAsset()
{
if (!AssetDatabase.DeleteAsset(configAssetPath))
{
System.IO.File.Delete(System.IO.Path.Combine(Main.RootPath, configAssetPath));
}
}
/* If the inspector is used to view a Config Asset, these properties control the presentation */
[CustomEditor(typeof(ConfigAsset))]
public class ConfigAssetPropertiesEditor : Editor
{
public override void OnInspectorGUI()
{
GUI.enabled = false;
DrawDefaultInspector();
GUI.enabled = true;
}
}
#endregion
}
}