Пример #1
0
        private void UpdateSearch()
        {
            // Clear any existing cached search results
            filteredPlayerPrefs.Clear();

            // Don't attempt to find the search results if a search filter hasn't actually been supplied
            if (string.IsNullOrEmpty(searchFilter))
            {
                return;
            }

            int entryCount = deserializedPlayerPrefs.Count;

            // Iterate through all the cached results and add any matches to filteredPlayerPrefs
            for (int i = 0; i < entryCount; i++)
            {
                string fullKey    = deserializedPlayerPrefs[i].Key;
                string displayKey = fullKey;

                // Special case for encrypted keys in auto decrypt mode, search should use decrypted values
                bool isEncryptedPair = SercurePlayerPrefs.IsEncryptedKey(deserializedPlayerPrefs[i].Key);
                if (automaticDecryption && isEncryptedPair)
                {
                    displayKey = SercurePlayerPrefs.DecryptKey(fullKey);
                }

                // If the key contains the search filter (ToLower used on both parts to make this case insensitive)
                if (displayKey.ToLower().Contains(searchFilter.ToLower()))
                {
                    filteredPlayerPrefs.Add(deserializedPlayerPrefs[i]);
                }
            }
        }
Пример #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);
        }