using UnityEditor; using UnityEngine; using System; using System.Collections.Generic; 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; public bool UseTypemap; // 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.EchoP4Commands = 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; Config.UseTypemap = UseTypemap; } // 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.EchoP4Commands; 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; UseTypemap = Config.UseTypemap; } } // 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. [Serializable] public class Config : EditorWindow { [SerializeField] 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; public static bool ConnectionWizardShowing = false; public ConnectionConfig DefaultConnection; public ConnectionConfig LastGoodConnection; public ConnectionConfig LastSavedConnection; #region Properties public static string ServerURI { set { _serverUri = value; } get { return _serverUri; } } public static string Username { set { _username = value; } get { return _username; } } public static string Password { get { return _password; } set { _password = value; } } public static string Workspace { get { return _workspace; } set { _workspace = value; } } public static bool UnityVsSupport { get { return _unityVsSupport; } set { _unityVsSupport = value; } } public static bool PerforceEnabled { set { _perforceEnabled = value; } get { return _perforceEnabled; } } public static bool IncludeSolutionFiles { get { return _includeSolutionFiles; } set { _includeSolutionFiles = value; } } public static bool IncludeProjectFiles { get { return _includeProjectFiles; } set { _includeProjectFiles = value; } } public static bool ShowPaths { get { return _showPaths; } set { _showPaths = value; } } public static bool AskBeforeCheckout { get { return _askBeforeCheckout; } set { _askBeforeCheckout = value; } } public static bool DisplayStatusIcons { get { return _displayStatusIcons; } set { _displayStatusIcons = value; } } public static string Hostname { get { return _hostname; } set { _hostname = value; } } public static string Charset { set { _charset = value; } get { return _charset; } } public static string DiffToolPathname { set { _diffToolPathname = value; } get { return _diffToolPathname; } } public static bool DisplayP4Timings { set { _displayP4Timings = value; } get { return _displayP4Timings; } } public static bool EchoP4Commands { set { _echoP4Commands = value; } get { return _echoP4Commands; } } public static bool CheckStatusForMenus { set { _checkStatusForMenus = value; } get { return _checkStatusForMenus; } } public static bool WarnOnSpecialCharacters { set { _warnOnSpecialCharacters = value; } get { return _warnOnSpecialCharacters; } } public static int CheckStatusForMenusMaxItems { set { _checkStatusForMenusMaxItems = value; } get { return _checkStatusForMenusMaxItems; } } public static int OperationBatchCount { set { _operationBatchCount = value; } get { return _operationBatchCount; } } public static int ConnectionTimeOut { set { _connectionTimeOut = value; } get { return _connectionTimeOut; } } public static string IgnoreName { set { _ignoreName = value; } get { return _ignoreName; } } public static string IgnoreLines { set { _ignoreLines = value; } get { return _ignoreLines; } } public static bool UseTypemap { set { _useTypemap = value; } get { return _useTypemap; } } public static bool EnableLog { set { _enableLog = value; } get { return _enableLog; } } public static Logger.LogLevel ConsoleLogLevel { set { _consoleLogLevel = value; } get { return _consoleLogLevel; } } public static string LogPath { set { _logPath = value; } get { return _logPath; } } // The following properties are NOT saved between sessions [SerializeField] private static string _clientProjectRoot; public static string ClientProjectRoot // Client path associated with project root (has /...) { get { return(_clientProjectRoot); } set { _clientProjectRoot = value; ClientProjectRootMatch = ClientProjectRoot.Substring(0, Math.Max(0, ClientProjectRoot.Length - 4)); ProjectFileSpec = FileSpec.ClientSpecList( new string[1]{ _clientProjectRoot } ); } } // Client path without the /... stuff. public static string ClientProjectRootMatch { set { _clientProjectRootMatch = value; } get { return _clientProjectRootMatch; } } // File Spec which describes the scope of the project (with /...) public static IList<FileSpec> ProjectFileSpec { set { _projectFileSpec = value; } get { return _projectFileSpec; } } // Depot path associated with project root (has /...) public static string DepotProjectRoot { set { _depotProjectRoot = value; } get { return _depotProjectRoot; } } // Connection Settings Have been Tested public static bool Valid { set; get; } #endregion static bool _foundConfigAsset; // Helper property to indicate that P4 can be used public static bool ValidConfiguration { get { return PerforceEnabled && Valid; } } 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"; public const string UseTypemapPrefName = "UseTypemap"; #endregion public enum SaveSettingsMode { EditorPrefs, ConfigAsset, } public static SaveSettingsMode SaveMode { get { return _currentSaveMode; } } [SerializeField] private static SaveSettingsMode _currentSaveMode = SaveSettingsMode.EditorPrefs; [SerializeField] static SaveSettingsMode _saveSelect; static bool _stylesInitialized = false; static void ResetValues() { // Set some default values ServerURI = "localhost:1666"; Username = Environment.UserName.Replace(' ','_'); Password = ""; Workspace = (Username + "_" + Main.ProjectName + "_" + Environment.MachineName).Replace(' ','_'); UnityVsSupport = false; PerforceEnabled = false; IncludeProjectFiles = false; IncludeSolutionFiles = false; ShowPaths = false; AskBeforeCheckout = false; DisplayStatusIcons = true; Hostname = ""; Charset = ""; DiffToolPathname = ""; DisplayP4Timings = false; EchoP4Commands = false; CheckStatusForMenus = true; CheckStatusForMenusMaxItems = 10; ConnectionTimeOut = 30; WarnOnSpecialCharacters = true; _foundConfigAsset = false; IgnoreName = ""; IgnoreLines = ""; UseTypemap = false; EnableLog = false; LogPath = DefaultLogFile(); ConsoleLogLevel = Logger.LogLevel.Info; Instance.DefaultConnection = new ConnectionConfig(true); } // Get an OS dependent path to the default p4connect log file. static string DefaultLogFile() { string rv = ""; if (Application.platform == RuntimePlatform.OSXEditor) { rv = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library/Logs/Unity/p4connect.log"); } else // (Application.platform == RuntimePlatform.WindowsEditor) { rv = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Unity\\Editor\\p4connect.log"); } rv = rv.Replace('/', System.IO.Path.DirectorySeparatorChar); //Debug.Log("DefaultLogFile: " + rv); return rv; } private static Config _pInstance = null; public static Config Instance { get { if (_pInstance == null) { ShowWindow(); } return _pInstance; } } private static string WindowName = "P4 Settings"; // 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. _pInstance = EditorWindow.GetWindow<Config>(WindowName); #if UNITY_5 _pInstance.titleContent = new GUIContent(WindowName); #else _pInstance.title = WindowName; #endif _pInstance.name = WindowName; _pInstance.minSize = new UnityEngine.Vector2(350.0f, 130.0f); } public void OnEnable() { //Debug.Log("Config OnEnable"); //Debug.Log("URI: " + Config.ServerURI.ToStringNullSafe()); //this should be defined in UnityEditor 5.1.1 and later //Config.titleContent.title = "foo"; // = ContentWindowTitle; } public void OnDisable() { //Debug.Log("Config OnDisable"); // Debug.Log("URI: " + Config.ServerURI.ToStringNullSafe()); } void OnSelectionChange() { Repaint(); } public static void OnDestroy() { if (ConnectionWizardShowing) { ConnectionWizard.Window.Close(); ConnectionWizardShowing = false; } } public static void Refresh() { if (Instance != null) Instance.Repaint(); } private static int _blinkCount = 0; private static int _blinkMax = 6; private static bool _blinkOn = true; private void OnInspectorUpdate() { Repaint(); // 10 x a second _blinkCount++; if (_blinkCount >= _blinkMax) // approx every second { if (_blinkOn) { _blinkButtonStyle = _gButtonStyle; } else { _blinkButtonStyle = _yButtonStyle; } _blinkOn = !_blinkOn; _blinkCount = 0; } } private static GUIStyle _fatButtonStyle; private static GUIStyle _rButtonStyle; private static GUIStyle _gButtonStyle; private static GUIStyle _yButtonStyle; private static GUIStyle _blinkButtonStyle; private static GUIStyle _bigButtonStyle; private static GUIStyle _bigRadioStyle; //private static string SkinPath = "Assets/P4Connect/Editor/P4Connect.guiskin"; private static GUISkin _p4Skin = null; // Access the P4Skin, if the asset can't be found, construct it. // Only called once when initializing styles. public static GUISkin GetP4Skin() { if (_p4Skin != null) return _p4Skin; #if Unity_4_0 // GUISkin p4Skin = Resources.LoadAssetAtPath(SkinPath, typeof(GUISkin)) as GUISkin; #else // GUISkin p4Skin = AssetDatabase.LoadAssetAtPath(SkinPath, typeof (GUISkin)) as GUISkin; #endif // if (p4Skin != null) // { // Comment out the following line if you are developing a new skin // return (p4Skin); // } // We couldn't find one, so we construct it ourselves // Debug.Log("Creating GUISkin"); _p4Skin = GUISkin.Instantiate(GUI.skin) as GUISkin; if (_p4Skin == null) { Debug.Log("Could not instantiate p4Skin"); _p4Skin = GUI.skin; return _p4Skin; } var bigButtonStyle = new GUIStyle(GUI.skin.button) { name = "bigButton", alignment = TextAnchor.MiddleCenter, fontSize = 18, fixedHeight = 100, fixedWidth = 100, }; var bigRadioStyle = new GUIStyle(GUI.skin.button) { name = "bigRadio", alignment = TextAnchor.MiddleCenter, fontSize = 14, fixedHeight = 100, fixedWidth = 100, }; var fatButtonStyle = new GUIStyle(GUI.skin.button) { name = "fatButton", alignment = TextAnchor.MiddleCenter, fontSize = 16, fixedHeight = 50, }; var gButtonStyle = new GUIStyle(fatButtonStyle) { name = "greenFatButton", normal = new GUIStyleState() {background = Icons.GetIcon("button-green.png") as Texture2D, textColor = Color.black}, }; var rButtonStyle = new GUIStyle(fatButtonStyle) { name = "redFatButton", normal = new GUIStyleState() { background = Icons.GetIcon("button-red.png") as Texture2D, textColor = Color.white }, }; var yButtonStyle = new GUIStyle(fatButtonStyle) { name = "yellowFatButton", normal = new GUIStyleState() { background = Icons.GetIcon("button-yellow.png") as Texture2D, textColor = Color.black }, }; // Add some custom types to the default set. List<GUIStyle> myCustomStyles = new List<GUIStyle>(_p4Skin.customStyles) { bigButtonStyle, bigRadioStyle, fatButtonStyle, gButtonStyle, rButtonStyle, yButtonStyle, }; _p4Skin.customStyles = myCustomStyles.ToArray(); // Write this skin out to P4Skin for future use. //Debug.Log("Writing Skin"); // try // { // AssetDatabase.StartAssetEditing(); // AssetDatabase.CreateAsset(p4Skin, SkinPath); // AssetDatabase.StopAssetEditing(); // EditorUtility.SetDirty(p4Skin); // } // catch (Exception ex) // { // Debug.Log("GetP4Skin Exception: " + ex.Message); // } return _p4Skin; } // Static initializer called ONCE from OnGUI() after initialization private static void InitializeStyles() { GUI.skin = GetP4Skin(); _bigButtonStyle = GUI.skin.GetStyle("bigButton"); _bigRadioStyle = GUI.skin.GetStyle("bigRadio"); _fatButtonStyle = GUI.skin.GetStyle("fatButton"); _gButtonStyle = GUI.skin.GetStyle("greenFatButton"); _rButtonStyle = GUI.skin.GetStyle("redFatButton"); _yButtonStyle = GUI.skin.GetStyle("yellowFatButton"); } /// <summary> /// Static Constructor, reads connection settings from Prefs at least once /// </summary> public static void Initialize() { Instance.DefaultConnection = new ConnectionConfig(true); //if (Instance.LastGoodConnection != null) // Debug.Log("LastGoodConnection: " + Instance.LastGoodConnection.ToString()); if (string.IsNullOrEmpty(Config.ServerURI)) { //Debug.Log("Resetting values"); ResetValues(); _foundConfigAsset = ReadConfigAsset(); if (_foundConfigAsset) { _currentSaveMode = SaveSettingsMode.ConfigAsset; } else { _currentSaveMode = SaveSettingsMode.EditorPrefs; ReadPrefs(); } } CachedSerializationMode = EditorSettings.serializationMode; Refresh(); if (PerforceEnabled) { if (EnableLog) { Logger.Initialize(); // initialize logging if not done before } if (Instance.DefaultConnection == null) { Instance.DefaultConnection = new ConnectionConfig(); } Instance.DefaultConnection.FromConfig(); Valid = CheckSettings(Instance.DefaultConnection); } } /// <summary> /// Checks the that settings are valid /// </summary> public static bool CheckSettings(ConnectionConfig cfg) { //DefaultConnection.FromConfig(); // copy Configuration settings into DefaultConnection if (PerforceEnabled) { bool goodConnection = TestConnectionConfig(cfg); // Test Configuration if (! goodConnection) { Debug.LogWarning("P4Connect - Perforce integration is enabled but inactive: " + Instance.DefaultConnection.Summary() +"\n Go to Edit->Perforce Settings to update your settings"); } else { ConnectionWizard.CloseWindows(); PasswordPrompt.CloseWindows(); // Debug.Log("P4Connect - Perforce Integration is Active"); return true; } } return false; } /// <summary> /// Updates the current configuration state after checking all the settings /// </summary> public static bool TestConnectionConfig(ConnectionConfig cfg) { //Debug.Log("TestConnectionConfig: " + cfg.ToString()); bool returnValue = false; if (Instance.LastGoodConnection != null && Instance.LastGoodConnection.Matches(cfg)) { // Debug.Log("Using LastGoodConnection"); cfg = Instance.LastGoodConnection; // Use LastGoodConnection } try { cfg.Tested = true; if (!cfg.MetafilesValid) { EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Meta Files", 0.2f); cfg.MetafilesValid = P4Connect.VerifySettings.CheckMetaFiles(); } if (cfg.MetafilesValid && !cfg.ServerValid) { EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Server", 0.4f); cfg.ServerValid = P4Connect.VerifySettings.CheckServerUri(cfg); } if (cfg.ServerValid && !cfg.PasswordValid) { EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Login", 0.6f); cfg.PasswordValid = P4Connect.VerifySettings.CheckUsernamePassword(cfg); } if (cfg.PasswordValid && !cfg.WorkspaceValid) { EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Workspace", 0.8f); cfg.WorkspaceValid = P4Connect.VerifySettings.CheckWorkspace(cfg); } if (cfg.WorkspaceValid && !cfg.ProjectRootValid) { EditorUtility.DisplayProgressBar("P4Connect - Hold on", "Checking Project Root", 0.9f); cfg.ProjectRootValid = P4Connect.VerifySettings.CheckProjectRoot(cfg); } returnValue = cfg.ProjectRootValid; } catch(Exception ex) { log.Debug("TestConnectionConfig exception", ex); } EditorUtility.ClearProgressBar(); if (returnValue == true) { Instance.LastGoodConnection = new ConnectionConfig(cfg); } return returnValue; } public static void SetProjectRootDirectory() { if (Config.ValidConfiguration) { //log.Debug("conn status: " + DefaultConnection.Summary() ); Engine.PerformConnectionOperation(con => { // project root in perforce syntax var spec = FileSpec.LocalSpec(System.IO.Path.Combine(Main.RootPath, "...")); var mappings = con.P4Client.GetClientFileMappings(spec); if (mappings != null && mappings.Count > 0) { // string ProjectRoot; ClientProjectRoot = mappings[0].ClientPath.Path; DepotProjectRoot = mappings[0].DepotPath.Path; //log.Debug("ClientProjectRoot: " + ClientProjectRoot); //log.Debug("DepotProjectRoot: " + DepotProjectRoot); } else { Debug.LogError("Unable to determine Project Root! "); } }); } } /// <summary> /// Figure out if the Current Settings need to be saved. /// This is used to draw attention to saving settings after a successful connection. /// </summary> /// <returns></returns> private bool SaveNeeded() { if (!PerforceEnabled || !Valid) return false; if (LastSavedConnection == null) { if (Valid) { LastSavedConnection = new ConnectionConfig(true); // initialize if connection is valid return false; } return true; } if (LastSavedConnection.MatchesConfig()) { return false; } return true; } static Color _saveColor; private static readonly Color DisabledColor = Color.red; private static readonly Color ConnectedColor = Color.white; private static readonly Color DisconnectedColor = Color.yellow; private static Color StatusColor() { var c = Color.white; if (PerforceEnabled) { c = Valid ? ConnectedColor : DisconnectedColor; } else { c = DisabledColor; } return c; } // static objects frequently used to create controls static readonly GUILayoutOption BoxWidth = GUILayout.MaxWidth(200.0f); static readonly GUILayoutOption EnumWidth = GUILayout.Width(75.0f); static readonly GUILayoutOption WideEnumWidth = GUILayout.Width(100.0f); static readonly GUILayoutOption CheckWidth = GUILayout.Width(16.0f); static readonly GUILayoutOption TextWidth = GUILayout.Width(250.0f); static readonly GUILayoutOption ButtonWidth = GUILayout.Width(80.0f); static readonly GUILayoutOption IntWidth = GUILayout.Width(30.0f); static readonly GUILayoutOption LabelWidth = GUILayout.Width(84.0f); static readonly GUILayoutOption IndentWidth = GUILayout.Width(10.0f); static readonly GUILayoutOption BigIconHeight = GUILayout.Height(100.0f); static float _VerticalSkip = 8.0f; // ToolTips need GUIContent entries private static GUIContent _contentIcon = new GUIContent("Icon", "View P4Connect documentation on the web"); private static readonly GUIContent ContentConnectPane = new GUIContent("Connection", "Edit P4Connect Connection Settings"); private static readonly GUIContent ContentOptionsPane = new GUIContent("Options", "Edit P4Connect general options"); private static readonly GUIContent ContentDiagnosticsPane = new GUIContent("Diagnostics\n+\nUtilities", "Edit P4Connect Diagnostic options"); private static readonly GUIContent ContentDisable = new GUIContent("Disable", "Disable p4connect for this project"); private static readonly GUIContent ContentEnable = new GUIContent("Enable", "Enable p4connect for this project"); private static readonly GUIContent ContentConnect = new GUIContent("Connect", "Create Connection to Server using current settings"); private static readonly GUIContent ContentDisconnect = new GUIContent("Disconnect", "Break Connection with Server"); private static readonly GUIContent ContentSaveSettings = new GUIContent("Save Settings", "Save the current settings"); private static readonly GUIContent ContentDocLink = new GUIContent("View Web Documentation", "Click to view P4Connect documentation"); private static readonly GUIContent ContentSaveTypeEnum = new GUIContent("Settings storage type:", "Change the current save mode\nEditor Preferences (registry) or \n Config Asset stores config in an asset"); private static readonly GUIContent ContentConsoleLogEnum = new GUIContent("Console Log Reporting Level: ", "Select how much of the P4Connect log gets echoed to the Unity Console"); private static GUIContent _wizardIconContent = new GUIContent("Icon", "Configuration Wizard"); static Texture2D _bigIcon = null; static Texture2D _wizardIcon = null; private void OnGuiStatusBar() { _saveColor = GUI.color; GUI.color = StatusColor(); EditorGUILayout.BeginHorizontal("HelpBox", BigIconHeight); if (_bigIcon == null) { _bigIcon = Icons.GetIcon("p4connect-icon.png") as Texture2D; _contentIcon = new GUIContent(_bigIcon, "Click to view documentation on the web"); } if (GUILayout.Button(_contentIcon, _bigButtonStyle)) { System.Diagnostics.Process.Start("http://www.perforce.com/perforce/doc.current/manuals/p4connectguide/index.html"); } GUI.color = _saveColor; EditorGUILayout.BeginVertical(); // Status Pane GUI.color = StatusColor(); if (PerforceEnabled) { EditorGUILayout.BeginHorizontal(); if (!Config.Valid) { EditorGUILayout.HelpBox("Perforce Integration is INACTIVE. Please Verify your Settings!", MessageType.Warning, true); } else { EditorGUILayout.HelpBox("Perforce Integration is ACTIVE.", MessageType.Info, true); } GUILayout.FlexibleSpace(); GUI.color = _saveColor; if (GUILayout.Button(ContentDisable, _rButtonStyle, GUILayout.Width(120.0f))) { PerforceEnabled = false; } EditorGUILayout.EndHorizontal(); } else { EditorGUILayout.BeginHorizontal(); EditorGUILayout.HelpBox("Perforce Integration is DISABLED.", MessageType.Info, true); GUILayout.FlexibleSpace(); GUI.color = _saveColor; if (GUILayout.Button(ContentEnable, _gButtonStyle, GUILayout.Width(120.0f))) { PerforceEnabled = true; DefaultConnection.FromConfig(); Valid = CheckSettings(DefaultConnection); // Go ahead and try to connect also } EditorGUILayout.EndHorizontal(); } EditorGUILayout.BeginVertical("Box"); GUILayout.Label("Version: " + Version.PerforceReleaseString + "-" + Version.Build, "BoldLabel"); GUILayout.Label("Project: " + Main.RootPath.ToStringNullSafe(), EditorStyles.miniLabel); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Save Mode: " + SaveMode.ToString(), EditorStyles.miniLabel); GUILayout.FlexibleSpace(); GUIStyle buttonStyle = SaveNeeded() ? _blinkButtonStyle : _fatButtonStyle; if (GUILayout.Button(ContentSaveSettings, buttonStyle, GUILayout.Width(150.0f))) { if (SaveMode == SaveSettingsMode.EditorPrefs) { Debug.Log("Saving configuration as Editor Preferences"); WritePrefs(); } else { Debug.Log("Saving configuration as Configuration Asset"); WriteConfigAsset(); } LastSavedConnection = new ConnectionConfig(true); } EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); // Box EditorGUILayout.EndVertical(); // Status Pane EditorGUILayout.EndHorizontal(); // End of Toolbar GUI.color = _saveColor; } private enum GuiSettingsMode { Connection, Options, Diagnostics } [SerializeField] private static GuiSettingsMode _currentMode = GuiSettingsMode.Connection; [SerializeField] private static bool _bConnection = true; [SerializeField] private static bool _bOptions = false; [SerializeField] private static bool _bDiagnostics = false; private void OnGuiSettings() { EditorGUILayout.BeginHorizontal("Box"); EditorGUILayout.BeginVertical(); // ReSharper disable once AssignmentInConditionalExpression if (_bConnection = GUILayout.Toggle(_bConnection,ContentConnectPane, _bigRadioStyle)) { _bOptions = _bDiagnostics = false; _currentMode = GuiSettingsMode.Connection; } // ReSharper disable once AssignmentInConditionalExpression if (_bOptions = GUILayout.Toggle(_bOptions, ContentOptionsPane, _bigRadioStyle)) { _bConnection = _bDiagnostics = false; _currentMode = GuiSettingsMode.Options; } // ReSharper disable once AssignmentInConditionalExpression if (_bDiagnostics = GUILayout.Toggle(_bDiagnostics, ContentDiagnosticsPane, _bigRadioStyle)) { _bConnection = _bOptions = false; _currentMode = GuiSettingsMode.Diagnostics; } EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical("box"); switch(_currentMode) { case GuiSettingsMode.Connection: OnGuiConnectionPanel(); break; case GuiSettingsMode.Options: OnGUIOptionsPanel(); break; case GuiSettingsMode.Diagnostics: OnGUIDiagnosticsPanel(); break; } EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); } #region ConnectionPanel /// <summary> /// Draw the Panel with Connection information /// </summary> private void OnGuiConnectionPanel() { bool errorFound = false; if (_wizardIcon == null) { _wizardIcon = Icons.GetIcon("wizard-bee.png") as Texture2D; _wizardIconContent = new GUIContent(_wizardIcon, "Click to activate Wizard"); } GUILayout.BeginVertical(); // Panel GUILayout.Label("Connection Settings", EditorStyles.boldLabel); GUILayout.Space(_VerticalSkip); GUILayout.BeginVertical("Box"); // connection box // Disable connection settings if already connected EditorGUI.BeginDisabledGroup(Valid); { EditorGUILayout.BeginHorizontal(); { GUILayout.Label("Server URI:", LabelWidth); ServerURI = EditorGUILayout.TextField(ServerURI); } EditorGUILayout.EndHorizontal(); if (DefaultConnection.Tested && ! DefaultConnection.ServerValid) { EditorGUILayout.HelpBox("Invalid Server URI", MessageType.Error); errorFound = true; } EditorGUILayout.BeginHorizontal(); { GUILayout.Label("Username:", LabelWidth); Username = EditorGUILayout.TextField(Username); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label("Password:", LabelWidth); Password = EditorGUILayout.PasswordField(Password); } EditorGUILayout.EndHorizontal(); if (!errorFound && DefaultConnection.Tested && ! (DefaultConnection.PasswordValid && DefaultConnection.UserValid)) { EditorGUILayout.HelpBox("Invalid Username / Password", MessageType.Error); errorFound = true; } EditorGUILayout.BeginHorizontal(); { GUILayout.Label("Workspace:", LabelWidth); Workspace = EditorGUILayout.TextField(Workspace); } EditorGUILayout.EndHorizontal(); if (!errorFound && DefaultConnection.Tested && DefaultConnection.PasswordValid && ( ! DefaultConnection.WorkspaceValid)) { EditorGUILayout.HelpBox("Invalid Workspace", MessageType.Error); errorFound = true; } if (!errorFound && DefaultConnection.Tested && DefaultConnection.WorkspaceValid && ! DefaultConnection.ProjectRootValid) { // 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(); { GUILayout.Label("P4HOST:",LabelWidth); Hostname = EditorGUILayout.TextField(Hostname); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label("P4CHARSET:", LabelWidth); Charset = EditorGUILayout.TextField(Charset); } EditorGUILayout.EndHorizontal(); } EditorGUI.EndDisabledGroup(); // Connection Valid EditorGUILayout.BeginHorizontal(); EditorGUI.BeginDisabledGroup(! Config.PerforceEnabled); GUI.SetNextControlName("connect"); if (GUILayout.Button(Config.Valid ? ContentDisconnect : ContentConnect , Config.Valid ? _rButtonStyle : _gButtonStyle, GUILayout.Width(120.0f))) { if (Config.Valid) { DefaultConnection.Reset(); // disconnect Valid = false; } else { EditorGUILayout.HelpBox("Please Wait! Checking Perforce Settings. This can take a while ...", MessageType.Info); DefaultConnection.FromConfig(); Valid = CheckSettings(DefaultConnection); } } EditorGUI.EndDisabledGroup(); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); // Connection Box EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginVertical(); // New Settings Assistance { GUILayout.Label("Load Settings", EditorStyles.boldLabel); GUILayout.Space(_VerticalSkip); EditorGUILayout.BeginVertical("box"); EditorGUI.BeginDisabledGroup(Valid); { EditorGUILayout.BeginHorizontal(); { EditorGUILayout.BeginVertical("box"); if (GUILayout.Button(_wizardIconContent, _bigButtonStyle)) { GUI.FocusControl(""); if (!ConnectionWizardShowing) { ConnectionWizard.ShowWindow(); ConnectionWizardShowing = true; } } EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(); if (GUILayout.Button("Load Defaults", EditorStyles.miniButton, BoxWidth)) { GUI.FocusControl(""); ResetValues(); DefaultConnection.FromConfig(); Repaint(); } if (GUILayout.Button("Load P4 Environment", EditorStyles.miniButton, BoxWidth)) { GUI.FocusControl(""); if (!ReadEnvironment()) { EditorUtility.DisplayDialog("Read Perforce Environment", "No Perforce Environment variables found!", "OK"); } DefaultConnection.FromConfig(); Repaint(); } if (GUILayout.Button("Load P4Config", BoxWidth)) { GUI.FocusControl(""); 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)); } DefaultConnection.FromConfig(); Repaint(); } if (GUILayout.Button("Load Editor Prefs", BoxWidth)) { GUI.FocusControl(""); ReadPrefs(); DefaultConnection.FromConfig(); Repaint(); } if (GUILayout.Button("Load Config Asset", BoxWidth)) { GUI.FocusControl(""); if (!ReadConfigAsset()) { EditorUtility.DisplayDialog("Read Configuration Asset", "No Configuration Asset found!", "OK"); } DefaultConnection.FromConfig(); Repaint(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndHorizontal(); } EditorGUI.EndDisabledGroup(); // Settings Valid EditorGUILayout.EndHorizontal(); GUILayout.EndVertical(); } // new settings EditorGUILayout.EndVertical(); GUILayout.EndVertical(); // Panel } #endregion #region OptionsPanel private void OnGUIOptionsPanel() { GUILayout.Label("Options", EditorStyles.boldLabel); GUILayout.Space(_VerticalSkip); EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginHorizontal(); { DisplayStatusIcons = EditorGUILayout.Toggle(DisplayStatusIcons, CheckWidth); GUILayout.Label("Display Status Icons"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { CheckStatusForMenus = EditorGUILayout.Toggle(CheckStatusForMenus, CheckWidth); GUILayout.Label("Gray out invalid menu options", TextWidth); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { 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("Diff Tool Executable "); 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; } } GUILayout.FlexibleSpace(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label(" ", IndentWidth); DiffToolPathname = GUILayout.TextField(DiffToolPathname, GUILayout.MinWidth(80.0f), GUILayout.ExpandWidth(true)); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { AskBeforeCheckout = EditorGUILayout.Toggle(AskBeforeCheckout, CheckWidth); GUILayout.Label("Ask before checkout on edit"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { WarnOnSpecialCharacters = EditorGUILayout.Toggle(WarnOnSpecialCharacters, CheckWidth); GUILayout.Label("Reserved character warning (@#*%)"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); IncludeSolutionFiles = EditorGUILayout.Toggle(IncludeSolutionFiles, CheckWidth); GUILayout.Label("Include Solution Files"); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); IncludeProjectFiles = EditorGUILayout.Toggle(IncludeProjectFiles, CheckWidth); GUILayout.Label("Include Project Files"); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); UnityVsSupport = EditorGUILayout.Toggle(UnityVsSupport, CheckWidth); GUILayout.Label("Integrate with UnityVS", TextWidth); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); UseTypemap = EditorGUILayout.Toggle(UseTypemap, CheckWidth); GUILayout.Label("Use Perforce server typemap", TextWidth); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label("Close Perforce connection after"); ConnectionTimeOut = EditorGUILayout.IntField(ConnectionTimeOut, IntWidth); GUILayout.Label("seconds"); GUILayout.FlexibleSpace(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label("p4ignore: "); 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; } } GUILayout.FlexibleSpace(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label(" ", IndentWidth); IgnoreName = GUILayout.TextField(IgnoreName, GUILayout.MinWidth(80.0f), GUILayout.ExpandWidth(true)); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label("Additional Ignore Lines:"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label(" ", IndentWidth); IgnoreLines = EditorGUILayout.TextArea(IgnoreLines, GUILayout.MinHeight(16.0f), GUILayout.MinWidth(200.0f), GUILayout.ExpandWidth(true)); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label(ContentSaveTypeEnum); _saveSelect = (SaveSettingsMode)EditorGUILayout.EnumPopup(_saveSelect, WideEnumWidth); _currentSaveMode = _saveSelect; GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); GUILayout.EndVertical(); // BOX } #endregion #region DiagnosticsPanel private void OnGUIDiagnosticsPanel() { GUILayout.Label("Diagnostics", EditorStyles.boldLabel); GUILayout.Space(_VerticalSkip); EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginHorizontal(); DisplayP4Timings = EditorGUILayout.Toggle(DisplayP4Timings, CheckWidth); GUILayout.Label("Display P4 Timings"); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EchoP4Commands = EditorGUILayout.Toggle(EchoP4Commands, CheckWidth); GUILayout.Label("Echo P4 Commands to log"); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); ShowPaths = EditorGUILayout.Toggle(ShowPaths, CheckWidth); GUILayout.Label("Show File Paths in Console"); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { EditorGUI.BeginDisabledGroup(LogPath.Length == 0); { bool newEnableLog = EditorGUILayout.Toggle(EnableLog, CheckWidth); if (newEnableLog != EnableLog) { EnableLog = newEnableLog; Logger.Initialize(); } } EditorGUI.EndDisabledGroup(); GUILayout.Label("Enable Logging"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label("Log File: "); if (GUILayout.Button("Browse...", EditorStyles.miniButton, ButtonWidth)) { string dir; string path; GUI.FocusControl(""); if (LogPath.Length == 0) { LogPath = DefaultLogFile(); } dir = System.IO.Directory.GetParent(LogPath).FullName; path = EditorUtility.SaveFilePanel("Set P4Connect Log File", dir, "p4connect", "log"); if (path.Length > 0) { LogPath = path; EnableLog = true; } } if (LogPath.Length == 0) { EnableLog = false; } GUILayout.FlexibleSpace(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label(" ", IndentWidth); LogPath = GUILayout.TextField(LogPath, GUILayout.MinWidth(80.0f), GUILayout.ExpandWidth(true)); GUILayout.FlexibleSpace(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label(ContentConsoleLogEnum); ConsoleLogLevel = (Logger.LogLevel)EditorGUILayout.EnumPopup(ConsoleLogLevel, EnumWidth); GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.Label("Utilities", EditorStyles.boldLabel); GUILayout.Space(_VerticalSkip); EditorGUILayout.BeginVertical("Box"); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Delete Configuration Asset", EditorStyles.miniButton, BoxWidth)) { if (EditorUtility.DisplayDialog("Delete Configuration Asset", "Are you sure you want to delete this asset?", "OK", "Cancel")) { DeleteConfigAsset(); } } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Clear Editor Prefs", EditorStyles.miniButton, BoxWidth)) { if (EditorUtility.DisplayDialog("Remove All EditorPrefs", "Are you sure you want to remove ALL Unity EditorPreferences?", "OK", "Cancel")) { EditorPrefs.DeleteAll(); } } EditorGUILayout.EndHorizontal(); GUILayout.Space(_VerticalSkip); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(ContentDocLink, EditorStyles.miniButton, BoxWidth)) { System.Diagnostics.Process.Start("http://www.perforce.com/perforce/doc.current/manuals/p4connectguide/index.html"); } EditorGUILayout.EndHorizontal(); GUILayout.EndVertical(); } #endregion [SerializeField] Vector2 vScroll = Vector2.zero; /// <summary> /// Called by Unity when the windows needs to be updated /// </summary> void OnGUI() { if (Event.current == null || Application.isPlaying) { GUIUtility.ExitGUI(); } if (PasswordPrompt.Active) { return; } if (!_stylesInitialized) { InitializeStyles(); _stylesInitialized = true; } vScroll = EditorGUILayout.BeginScrollView(vScroll, false, false); // Show the status bar OnGuiStatusBar(); OnGuiSettings(); EditorGUILayout.EndScrollView(); // Scroll View Wrapper for dialog } // Check for the "well known" Perforce environment variables. public static bool ReadEnvironment() { bool found = false; string 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)); } if (HasStringPrefNotEmpty(WorkspacePrefName)) Workspace = GetPrefString(WorkspacePrefName); if (HasPref(PerforceEnabledPrefName)) PerforceEnabled = GetPrefBool(PerforceEnabledPrefName); 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)) EchoP4Commands = 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(UseTypemapPrefName)) UseTypemap = GetPrefBool(UseTypemapPrefName); 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)); } 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, EchoP4Commands); SetPrefBool(CheckStatusForMenusPrefName, CheckStatusForMenus); SetPrefInt(CheckStatusForMenusMaxItemsPrefName, CheckStatusForMenusMaxItems); SetPrefInt(OperationBatchCountPrefName, OperationBatchCount); SetPrefInt(ConnectionTimeOutPrefName, ConnectionTimeOut); SetPrefBool(WarnOnSpecialCharactersPrefName, WarnOnSpecialCharacters); SetPrefString(IgnoreNamePrefName, IgnoreName); SetPrefString(IgnoreLinesPrefName, IgnoreLines); SetPrefBool(UseTypemapPrefName, UseTypemap); 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() { // 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(UseTypemapPrefName); EditorPrefs.DeleteKey(EnableLogPrefName); EditorPrefs.DeleteKey(ConsoleLogLevelPrefName); } #endregion public static SerializationMode CachedSerializationMode { get; private set; } public static bool SettingsSaved { get; 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"; // Backing stores for properties [SerializeField] private static string _serverUri; [SerializeField] private static string _username; [SerializeField] private static string _password; [SerializeField] private static string _workspace; [SerializeField] private static bool _unityVsSupport; [SerializeField] private static bool _perforceEnabled; [SerializeField] private static bool _includeSolutionFiles; [SerializeField] private static bool _includeProjectFiles; [SerializeField] private static bool _showPaths; [SerializeField] private static bool _askBeforeCheckout; [SerializeField] private static bool _displayStatusIcons; [SerializeField] private static string _hostname; [SerializeField] private static string _charset; [SerializeField] private static string _diffToolPathname; [SerializeField] private static bool _displayP4Timings; [SerializeField] private static bool _echoP4Commands; [SerializeField] private static bool _checkStatusForMenus; [SerializeField] private static bool _warnOnSpecialCharacters; [SerializeField] private static int _checkStatusForMenusMaxItems; [SerializeField] private static int _operationBatchCount; [SerializeField] private static int _connectionTimeOut; [SerializeField] private static string _ignoreName; [SerializeField] private static string _ignoreLines; [SerializeField] private static bool _useTypemap; [SerializeField] private static bool _enableLog; [SerializeField] private static Logger.LogLevel _consoleLogLevel; [SerializeField] private static string _logPath; [SerializeField] private static string _clientProjectRootMatch; [SerializeField] private static IList<FileSpec> _projectFileSpec; [SerializeField] private static string _depotProjectRoot; public static void WriteConfigAsset() { ConfigAsset asset = ScriptableObject.CreateInstance<ConfigAsset>(); asset.CopyConfigToAsset(); AssetDatabase.CreateAsset(asset, configAssetPath); AssetDatabase.SaveAssets(); } public static bool ReadConfigAsset() { ConfigAsset asset = AssetDatabase.LoadAssetAtPath(configAssetPath, (typeof(ConfigAsset))) as ConfigAsset; if (asset != null) { asset.CopyAssetToConfig(); Config.Refresh(); return true; } else { 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 } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 18970 | rtande |
Merging //guest/perforce_software/p4connect/main/src/... to //rtande/p4connect/main/src/... |
||
//guest/perforce_software/p4connect/main/src/P4Connect/P4Connect/P4Connect.Config.cs | |||||
#9 | 18942 | Norman Morse | 2016.1 Patch 2 changes | ||
#8 | 18665 | Norman Morse | 16.2 preparation checkin | ||
#7 | 18462 | Norman Morse |
Final Changes needed for 2016.1 release New Icons. New Icon Packaging. Unity 4 compatibility changes. |
||
#6 | 18436 | Norman Morse |
A lot of clean up. PackageIcons was a mess Needed to remove GUIStyle Saving because textures are getting lost. |
||
#5 | 18418 | Norman Morse |
Many changes from the dev branch. Icons are packaged differently. Style Sheet is created / used New ConnectionWizard Dialog New PasswordDialog Generate -a tickets Update version to 2016.1.0.0 |
||
#4 | 16384 | Norman Morse | Move test code out of DEBUG block | ||
#3 | 16383 | Norman Morse |
Changed Password storage obfuscation code. Added debug for EditorPrefs issue on OSX |
||
#2 | 16350 | Norman Morse |
Minor Code Clean Up Minor Documentation Clean Up Changed Post Processor callback to ignore directories Added option to use Server Typemap |
||
#1 | 16209 | Norman Morse | Move entire source tree into "main" branch so workshop code will act correctly. | ||
//guest/perforce_software/p4connect/src/P4Connect/P4Connect/P4Connect.Config.cs | |||||
#28 | 16163 | Norman Morse |
Import latest changes from 2015.2/1245676 Fixes disconnect issue on "run" Fixes SSL versioning problem on OSX Added VS2015 support to project files |
||
#27 | 16117 | Norman Morse |
Fix for EditorPrefs related Disconnection. Cleaned up some code. Removed Spurious Comments Initialize Config from within Main |
||
#26 | 15424 | Norman Morse |
Fixed exceptions in Dialogs. Updated release Notes. Added checks to menus for PerforceEnabled |
||
#25 | 15401 | Norman Morse |
Fixed serialization of Config so P4Connect remains connected after a Game Run Cleaned up some menus. |
||
#24 | 15383 | Norman Morse |
Improved Diagnostics, cleaned up unnecessary log output Moved some Dialog Initialization to OnEnable() Fixed Unity 5.1.1 incompatibilities Added Operation support for In Depot Deleted files |
||
#23 | 15298 | Norman Morse | Fix Version Stamping to not use UpdateVersion.exe for personal (workshop) builds. | ||
#22 | 15266 | Norman Morse |
Integrated "UpdateVersion" tool to update the VersionInfo and the DLL properties with information from "Version" EC generates the Version file for us in builds. Workshop users need to generate their own Release number with two zeros (like 2015.2.0.0) which will have the last two numbers replaced with change ID. |
||
#21 | 15244 | Norman Morse |
Better Directory support in "add" "get latest" "refresh" and other commands. Improved Project Root detection Various Bug Fixes and Clean up |
||
#20 | 15146 | Norman Morse |
Rewrote Config Dialog to resize well and work both vertically and horizontally. Fixed some internal issues in file handling. Removed .bytes from default type of "text" |
||
#19 | 15079 | Norman Morse |
Rewrote AssetStatusCache to Cache AssetStatuses and FileMetaData Fixed Edge conditions on Engine Operations Change Debug output defaults. Will now Checkout files which request to be "added" but which already exist in perforce. Output P4Connect version to log on initialization. |
||
#18 | 14801 | Norman Morse |
GA.9 changes. Fixed debug message exceptions Improved Pending Changes dialog for large changesets Changed configuration to allow saving configuration with Perforce disabled. Improved restart after recompile, automatically attempts connection now unless disabled. |
||
#17 | 14193 | Norman Morse |
GA.7 release Refactor Pending Changes Resolve Submit issues. Fixed Menu entries. Handle mismatched file and meta states. |
||
#16 | 13864 | Norman Morse | Final fixes for GA.5 release. | ||
#15 | 13813 | Norman Morse |
Changed Config to call CheckProjectRoot which creates ClientProjectRoot and DepotProjectRoot Filter files in changelists to include only files under the Project root. Run fstat on files in the default change to make sure we have complete metadata |
||
#14 | 13596 | Norman Morse |
GA.3 fixes Update release notes. Fix config dialog initialization, update version Disable warnings for PackageIcons.cs, Fix crash in GetLockState() call |
||
#13 | 13269 | Norman Morse |
Bumped version to 2.7 GA 2 Fixed problem with Hung Config Window and no previous settings Fixed code to automattically attempt to connect to Perforce Server if configuration allows. |
||
#12 | 12862 | Norman Morse |
Fixed problem with an empty default change list not refresshing. Fixed crash in is_ignored Removed a lot of log output |
||
#11 | 12568 | Norman Morse | Fixed some error handling during Perforce Configuration | ||
#10 | 12566 | Norman Morse |
Fixed hang when restarting after rebuild Updated Release String to GA |
||
#9 | 12554 | Norman Morse |
Changed OSX DLL checking code. Improved re-connection after restart |
||
#8 | 12553 | Norman Morse |
integrate from internal main Build fixes for EC. Major changes to Configuration and re-initialization code. Bug fixes |
||
#7 | 12512 | Norman Morse | Integrate from Dev branch, preparing for Beta3 release | ||
#6 | 12368 | Norman Morse |
Improved config dialog. Perforce defaults to Enabled |
||
#5 | 12251 | Norman Morse |
Fixes for Beta 2 release Mostly Configuration dialog bug fixes |
||
#4 | 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 |
||
#3 | 11378 | Norman Morse |
P4Config support. Debugging DLL Loading issues |
||
#2 | 11224 | Norman Morse |
Add P4Config support to P4Connect. It checks for a P4Config Environment variable, and if found, looks for the controlling P4Config file. It then pre-populates the settings with information from P4Config and kicks off a validate. You can re-run the P4Config routine by turning on and off the checkbox from within the P4Connect settings. |
||
#1 | 10940 | Norman Morse |
Inital Workshop release of P4Connect. Released under BSD-2 license |