예제 #1
0
        private void DrawAddEntry()
        {
            // Create a GUIStyle that can be manipulated for the various text fields
            GUIStyle textFieldStyle = new GUIStyle(GUI.skin.textField);

            // Create a space
            EditorGUILayout.Space();

            // Heading
            GUILayout.Label("Add Player Pref", EditorStyles.boldLabel);

            // UI for whether the new player pref is encrypted and what type it is
            EditorGUILayout.BeginHorizontal();
            newEntryIsEncrypted = GUILayout.Toggle(newEntryIsEncrypted, "Encrypt");
            newEntryType        =
                (PlayerPrefType)GUILayout.SelectionGrid((int)newEntryType, new string[] { "float", "int", "string" },
                                                        3);
            EditorGUILayout.EndHorizontal();

            // Key and Value headings
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("Key", EditorStyles.boldLabel);
            GUILayout.Label("Value", EditorStyles.boldLabel);
            EditorGUILayout.EndHorizontal();

            // If the new value will be encrypted tint the text boxes blue (in line with the display style for existing
            // encrypted player prefs)
            if (newEntryIsEncrypted)
            {
                if (UsingProSkin)
                {
                    textFieldStyle.normal.textColor  = new Color(0.5f, 0.5f, 1);
                    textFieldStyle.focused.textColor = new Color(0.5f, 0.5f, 1);
                }
                else
                {
                    textFieldStyle.normal.textColor  = new Color(0, 0, 1);
                    textFieldStyle.focused.textColor = new Color(0, 0, 1);
                }
            }

            EditorGUILayout.BeginHorizontal();

            // Track the next control so we can detect key events in it
            GUI.SetNextControlName("newEntryKey");
            // UI for the new key text box
            newEntryKey = EditorGUILayout.TextField(newEntryKey, textFieldStyle);

            // Track the next control so we can detect key events in it
            GUI.SetNextControlName("newEntryValue");

            // Display the correct UI field editor based on what type of player pref is being created
            if (newEntryType == PlayerPrefType.Float)
            {
                newEntryValueFloat = EditorGUILayout.FloatField(newEntryValueFloat, textFieldStyle);
            }
            else if (newEntryType == PlayerPrefType.Int)
            {
                newEntryValueInt = EditorGUILayout.IntField(newEntryValueInt, textFieldStyle);
            }
            else
            {
                newEntryValueString = EditorGUILayout.TextField(newEntryValueString, textFieldStyle);
            }

            // If the user hit enter while either the key or value fields were being edited
            bool keyboardAddPressed = Event.current.isKey && Event.current.keyCode == KeyCode.Return &&
                                      Event.current.type == EventType.KeyUp &&
                                      (GUI.GetNameOfFocusedControl() == "newEntryKey" ||
                                       GUI.GetNameOfFocusedControl() == "newEntryValue");

            // If the user clicks the Add button or hits return (and there is a non-empty key), create the player pref
            if ((GUILayout.Button("Add", GUILayout.Width(40)) || keyboardAddPressed) &&
                !string.IsNullOrEmpty(newEntryKey))
            {
                // If the player pref we're creating is encrypted
                if (newEntryIsEncrypted)
                {
                    // Encrypt the key
                    string encryptedKey = SercurePlayerPrefs.KeyPrefix + UserEncryption.EncryptString(newEntryKey);

                    // Note: All encrypted values are stored as string
                    string encryptedValue;

                    // Calculate the encrypted value
                    if (newEntryType == PlayerPrefType.Float)
                    {
                        encryptedValue = SercurePlayerPrefs.ValueFloatPrefix +
                                         UserEncryption.EncryptFloat(newEntryValueFloat);
                    }
                    else if (newEntryType == PlayerPrefType.Int)
                    {
                        encryptedValue = SercurePlayerPrefs.ValueIntPrefix +
                                         UserEncryption.EncryptInt(newEntryValueInt);
                    }
                    else
                    {
                        encryptedValue = SercurePlayerPrefs.ValueStringPrefix +
                                         UserEncryption.EncryptString(newEntryValueString);
                    }

                    // Record the new player pref in PlayerPrefs
                    PlayerPrefs.SetString(encryptedKey, encryptedValue);

                    // Cache the addition
                    CacheRecord(encryptedKey, encryptedValue);
                }
                else
                {
                    if (newEntryType == PlayerPrefType.Float)
                    {
                        // Record the new player pref in PlayerPrefs
                        PlayerPrefs.SetFloat(newEntryKey, newEntryValueFloat);
                        // Cache the addition
                        CacheRecord(newEntryKey, newEntryValueFloat);
                    }
                    else if (newEntryType == PlayerPrefType.Int)
                    {
                        // Record the new player pref in PlayerPrefs
                        PlayerPrefs.SetInt(newEntryKey, newEntryValueInt);
                        // Cache the addition
                        CacheRecord(newEntryKey, newEntryValueInt);
                    }
                    else
                    {
                        // Record the new player pref in PlayerPrefs
                        PlayerPrefs.SetString(newEntryKey, newEntryValueString);
                        // Cache the addition
                        CacheRecord(newEntryKey, newEntryValueString);
                    }
                }

                // Tell Unity to save the PlayerPrefs
                PlayerPrefs.Save();

                // Force a repaint since hitting the return key won't invalidate layout on its own
                Repaint();

                // Reset the values
                newEntryKey         = "";
                newEntryValueFloat  = 0;
                newEntryValueInt    = 0;
                newEntryValueString = "";

                // Deselect
                GUI.FocusControl("");
            }

            EditorGUILayout.EndHorizontal();
        }
예제 #2
0
        private void DrawMainList()
        {
            // The bold table headings
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("Key", EditorStyles.boldLabel);
            GUILayout.Label("Value", EditorStyles.boldLabel);
            GUILayout.Label("Type", EditorStyles.boldLabel, GUILayout.Width(37));
            GUILayout.Label("Del", EditorStyles.boldLabel, GUILayout.Width(25));
            EditorGUILayout.EndHorizontal();

            // Create a GUIStyle that can be manipulated for the various text fields
            GUIStyle textFieldStyle = new GUIStyle(GUI.skin.textField);

            // Could be dealing with either the full list or search results, so get the right list
            List <PlayerPrefPair> activePlayerPrefs = deserializedPlayerPrefs;

            if (!string.IsNullOrEmpty(searchFilter))
            {
                activePlayerPrefs = filteredPlayerPrefs;
            }

            // Cache the entry count
            int entryCount = activePlayerPrefs.Count;

            // Record the last scroll position so we can calculate if the user has scrolled this frame
            lastScrollPosition = scrollPosition;

            // Start the scrollable area
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
            // Ensure the scroll doesn't go below zero
            if (scrollPosition.y < 0)
            {
                scrollPosition.y = 0;
            }

            // The following code has been optimised so that rather than attempting to draw UI for every single PlayerPref
            // it instead only draws the UI for those currently visible in the scroll view and pads above and below those
            // results to maintain the right size using GUILayout.Space(). This enables us to work with thousands of
            // PlayerPrefs without slowing the interface to a halt.

            // Fixed height of one of the rows in the table
            float rowHeight = 18;

            // Determine how many rows are visible on screen. For simplicity, use Screen.height (the overhead is negligible)
            int visibleCount = Mathf.CeilToInt(Screen.height / rowHeight);

            // Determine the index of the first player pref that should be drawn as visible in the scrollable area
            int firstShownIndex = Mathf.FloorToInt(scrollPosition.y / rowHeight);

            // Determine the bottom limit of the visible player prefs (last shown index + 1)
            int shownIndexLimit = firstShownIndex + visibleCount;

            // If the actual number of player prefs is smaller than the caculated limit, reduce the limit to match
            if (entryCount < shownIndexLimit)
            {
                shownIndexLimit = entryCount;
            }

            // If the number of displayed player prefs is smaller than the number we can display (like we're at the end
            // of the list) then move the starting index back to adjust
            if (shownIndexLimit - firstShownIndex < visibleCount)
            {
                firstShownIndex -= visibleCount - (shownIndexLimit - firstShownIndex);
            }

            // Can't have a negative index of a first shown player pref, so clamp to 0
            if (firstShownIndex < 0)
            {
                firstShownIndex = 0;
            }

            // Pad above the on screen results so that we're not wasting draw calls on invisible UI and the drawn player
            // prefs end up in the same place in the list
            GUILayout.Space(firstShownIndex * rowHeight);

            // For each of the on screen results
            for (int i = firstShownIndex; i < shownIndexLimit; i++)
            {
                // Detect if it's an encrypted player pref (these have key prefixes)
                bool isEncryptedPair = SercurePlayerPrefs.IsEncryptedKey(activePlayerPrefs[i].Key);

                // Colour code encrypted player prefs blue
                if (isEncryptedPair)
                {
                    if (UsingProSkin)
                    {
                        textFieldStyle.normal.textColor  = new Color(0.5f, 0.5f, 1);
                        textFieldStyle.focused.textColor = new Color(0.5f, 0.5f, 1);
                    }
                    else
                    {
                        textFieldStyle.normal.textColor  = new Color(0, 0, 1);
                        textFieldStyle.focused.textColor = new Color(0, 0, 1);
                    }
                }
                else
                {
                    // Normal player prefs are just black
                    textFieldStyle.normal.textColor  = GUI.skin.textField.normal.textColor;
                    textFieldStyle.focused.textColor = GUI.skin.textField.focused.textColor;
                }

                // The full key is the key that's actually stored in player prefs
                string fullKey = activePlayerPrefs[i].Key;

                // Display key is used so in the case of encrypted keys, we display the decrypted version instead (in
                // auto-decrypt mode).
                string displayKey = fullKey;

                // Used for accessing the type information stored against the player pref
                object deserializedValue = activePlayerPrefs[i].Value;

                // Track whether the auto decrypt failed, so we can instead fallback to encrypted values and mark it red
                bool failedAutoDecrypt = false;

                // If this is an encrypted play pref and we're attempting to decrypt them, try to decrypt it!
                if (isEncryptedPair && automaticDecryption)
                {
                    // This may throw exceptions (e.g. if private key changes), so wrap in a try-catch
                    try {
                        deserializedValue = SercurePlayerPrefs.GetValue(fullKey, (string)deserializedValue);
                        displayKey        = SercurePlayerPrefs.DecryptKey(fullKey);
                    } catch {
                        // Change the colour to red to highlight the decrypt failed
                        textFieldStyle.normal.textColor  = Color.red;
                        textFieldStyle.focused.textColor = Color.red;

                        // Track that the auto decrypt failed, so we can prevent any editing
                        failedAutoDecrypt = true;
                    }
                }

                EditorGUILayout.BeginHorizontal();

                // The type of player pref being stored (in auto decrypt mode this works with the decrypted values too)
                Type valueType;

                // If it's an encrypted playerpref, we're automatically decrypting and it didn't fail the earlier
                // auto decrypt test
                if (isEncryptedPair && automaticDecryption && !failedAutoDecrypt)
                {
                    // Get the encrypted string
                    string encryptedValue = PlayerPrefs.GetString(fullKey);
                    // Set valueType appropiately based on which type identifier prefix the encrypted string starts with
                    if (encryptedValue.StartsWith(SercurePlayerPrefs.ValueFloatPrefix))
                    {
                        valueType = typeof(float);
                    }
                    else if (encryptedValue.StartsWith(SercurePlayerPrefs.ValueIntPrefix))
                    {
                        valueType = typeof(int);
                    }
                    else if (encryptedValue.StartsWith(SercurePlayerPrefs.ValueStringPrefix) ||
                             string.IsNullOrEmpty(encryptedValue))
                    {
                        // Special case here, empty encrypted values will also report as strings
                        valueType = typeof(string);
                    }
                    else
                    {
                        throw new InvalidOperationException(
                                  "Could not decrypt item, no match found in known encrypted key prefixes");
                    }
                }
                else
                {
                    // Otherwise fallback to the type of the cached value (for non-encrypted values this will be
                    // correct). For encrypted values when not in auto-decrypt mode, this will return string type
                    valueType = deserializedValue.GetType();
                }

                // Display the PlayerPref key
                EditorGUILayout.TextField(displayKey, textFieldStyle);

                // Value display and user editing
                // If we're dealing with a float
                if (valueType == typeof(float))
                {
                    float initialValue;
                    if (isEncryptedPair && automaticDecryption)
                    {
                        // Automatically decrypt the value if encrypted and in auto-decrypt mode
                        initialValue = SercurePlayerPrefs.GetFloat(displayKey);
                    }
                    else
                    {
                        // Otherwise fetch the latest plain value from PlayerPrefs in memory
                        initialValue = PlayerPrefs.GetFloat(fullKey);
                    }

                    // Display the float editor field and get any changes in value
                    float newValue = EditorGUILayout.FloatField(initialValue, textFieldStyle);

                    // If the value has changed
                    if (newValue != initialValue)
                    {
                        // Store the changed value in player prefs, encrypting if necessary
                        if (isEncryptedPair)
                        {
                            string encryptedValue = SercurePlayerPrefs.ValueFloatPrefix +
                                                    UserEncryption.EncryptFloat(newValue);
                            PlayerPrefs.SetString(fullKey, encryptedValue);
                        }
                        else
                        {
                            PlayerPrefs.SetFloat(fullKey, newValue);
                        }

                        // Save PlayerPrefs
                        PlayerPrefs.Save();
                    }

                    // Display the PlayerPref type
                    GUILayout.Label("float", GUILayout.Width(37));
                }
                else if (valueType == typeof(int))                   // if we're dealing with an int
                {
                    int initialValue;
                    if (isEncryptedPair && automaticDecryption)
                    {
                        // Automatically decrypt the value if encrypted and in auto-decrypt mode
                        initialValue = SercurePlayerPrefs.GetInt(displayKey);
                    }
                    else
                    {
                        // Otherwise fetch the latest plain value from PlayerPrefs in memory
                        initialValue = PlayerPrefs.GetInt(fullKey);
                    }

                    // Display the int editor field and get any changes in value
                    int newValue = EditorGUILayout.IntField(initialValue, textFieldStyle);

                    // If the value has changed
                    if (newValue != initialValue)
                    {
                        // Store the changed value in player prefs, encrypting if necessary
                        if (isEncryptedPair)
                        {
                            string encryptedValue =
                                SercurePlayerPrefs.ValueIntPrefix + UserEncryption.EncryptInt(newValue);
                            PlayerPrefs.SetString(fullKey, encryptedValue);
                        }
                        else
                        {
                            PlayerPrefs.SetInt(fullKey, newValue);
                        }

                        // Save PlayerPrefs
                        PlayerPrefs.Save();
                    }

                    // Display the PlayerPref type
                    GUILayout.Label("int", GUILayout.Width(37));
                }
                else if (valueType == typeof(string))                   // if we're dealing with a string
                {
                    string initialValue;
                    if (isEncryptedPair && automaticDecryption && !failedAutoDecrypt)
                    {
                        // Automatically decrypt the value if encrypted and in auto-decrypt mode
                        initialValue = SercurePlayerPrefs.GetString(displayKey);
                    }
                    else
                    {
                        // Otherwise fetch the latest plain value from PlayerPrefs in memory
                        initialValue = PlayerPrefs.GetString(fullKey);
                    }

                    // Display the text (string) editor field and get any changes in value
                    string newValue = EditorGUILayout.TextField(initialValue, textFieldStyle);

                    // If the value has changed
                    if (newValue != initialValue && !failedAutoDecrypt)
                    {
                        // Store the changed value in player prefs, encrypting if necessary
                        if (isEncryptedPair)
                        {
                            string encryptedValue = SercurePlayerPrefs.ValueStringPrefix +
                                                    UserEncryption.EncryptString(newValue);
                            PlayerPrefs.SetString(fullKey, encryptedValue);
                        }
                        else
                        {
                            PlayerPrefs.SetString(fullKey, newValue);
                        }

                        // Save PlayerPrefs
                        PlayerPrefs.Save();
                    }

                    if (isEncryptedPair && !automaticDecryption && !string.IsNullOrEmpty(initialValue))
                    {
                        // Because encrypted values when not in auto-decrypt mode are stored as string, determine their
                        // encrypted type and display that instead for these encrypted PlayerPrefs
                        PlayerPrefType playerPrefType = (PlayerPrefType)(int)char.GetNumericValue(initialValue[0]);
                        GUILayout.Label(playerPrefType.ToString().ToLower(), GUILayout.Width(37));
                    }
                    else
                    {
                        // Display the PlayerPref type
                        GUILayout.Label("string", GUILayout.Width(37));
                    }
                }

                // Delete button
                if (GUILayout.Button("X", GUILayout.Width(25)))
                {
                    // Delete the key from player prefs
                    PlayerPrefs.DeleteKey(fullKey);
                    // Tell Unity to Save PlayerPrefs
                    PlayerPrefs.Save();
                    // Delete the cached record so the list updates immediately
                    DeleteCachedRecord(fullKey);
                }

                EditorGUILayout.EndHorizontal();
            }

            // Calculate the padding at the bottom of the scroll view (because only visible player pref rows are drawn)
            float bottomPadding = (entryCount - shownIndexLimit) * rowHeight;

            // If the padding is positive, pad the bottom so that the layout and scroll view size is correct still
            if (bottomPadding > 0)
            {
                GUILayout.Space(bottomPadding);
            }

            EditorGUILayout.EndScrollView();

            // Display the number of player prefs
            GUILayout.Label("Entry Count: " + entryCount);
        }