Esempio n. 1
0
        private void Remap(RemapType type, ref string current)
        {
            string prefix = PrefixFor(type) ?? PrefixFor(RemapType.All);
            string suffix = SuffixFor(type) ?? SuffixFor(RemapType.All);

            if (!string.IsNullOrWhiteSpace(prefix) && !current.StartsWith(prefix))
            {
                current = prefix + current;
            }
            if (!string.IsNullOrWhiteSpace(suffix) && !current.EndsWith(suffix))
            {
                current = current + suffix;
            }
        }
Esempio n. 2
0
 private string Remap(RemapType type, string current)
 {
     Remap(type, ref current);
     return(current);
 }
Esempio n. 3
0
 public void SuffixFor(RemapType type, string suffix)
 {
     m_suffix[type] = suffix;
 }
Esempio n. 4
0
        public string SuffixFor(RemapType type)
        {
            string val = null;

            return(m_suffix.TryGetValue(type, out val) ? val : null);
        }
Esempio n. 5
0
 public void PrefixFor(RemapType type, string prefix)
 {
     m_prefix[type] = prefix;
 }
        private void OnMaterialsDropped(Material[] droppedMaterials)
        {
            remappingRoot.Clear();

            DisposeOfSerializedObjects();

            //Construct a dictionary between shaders and their materials
            shadersToMaterials = new Dictionary <Shader, List <SerializedObject> >();
            foreach (Material material in droppedMaterials)
            {
                if (!shadersToMaterials.TryGetValue(material.shader, out var list))
                {
                    list = new List <SerializedObject>();
                    shadersToMaterials.Add(material.shader, list);
                }

                list.Add(new SerializedObject(material));
            }

            foreach (var pair in shadersToMaterials)
            {
                Box shaderRoot = new Box();
                shaderRoot.AddToClassList("innerPadding");
                remappingRoot.Add(shaderRoot);

                Shader      shader      = pair.Key;
                ObjectField shaderField = new ObjectField {
                    objectType = typeof(Shader), value = shader
                };
                shaderField.SetEnabled(false);
                shaderRoot.Add(shaderField);

                //RemapType, to a set of keys referring to values that could be remapped.
                var remapsFrom = new Dictionary <RemapType, HashSet <string> >();
                var remapsTo   = new Dictionary <RemapType, HashSet <string> >();

                List <SerializedObject> materials = pair.Value;
                foreach (SerializedObject materialSO in materials)
                {
                    SerializedProperty savedProperties = materialSO.FindProperty("m_SavedProperties");

                    //Textures -------------------------------------------------------------------------
                    SerializedProperty texEnvsArray = savedProperties.FindPropertyRelative("m_TexEnvs");
                    var textureKeys = new HashSet <string>();
                    remapsTo.Add(RemapType.Texture, textureKeys);
                    var textureKeysFrom = new HashSet <string>();
                    remapsFrom.Add(RemapType.Texture, textureKeysFrom);
                    for (int i = 0; i < texEnvsArray.arraySize; i++)
                    {
                        SerializedProperty texEnv  = texEnvsArray.GetArrayElementAtIndex(i);
                        SerializedProperty key     = texEnv.FindPropertyRelative("first");
                        SerializedProperty texture = texEnv.FindPropertyRelative("second.m_Texture");

                        textureKeys.Add(key.stringValue);
                        //Only add to the "from", if there is a key with a meaningful value in it.
                        if (texture.objectReferenceValue != null)
                        {
                            textureKeysFrom.Add(key.stringValue);
                        }
                    }
                    //-----------------------------------------------------------------------------------

                    //Floats ----------------------------------------------------------------------------
                    SerializedProperty floatsArray = savedProperties.FindPropertyRelative("m_Floats");
                    //floats have no way of telling if they're not set, so they can use the same set
                    var floatKeys = new HashSet <string>();
                    remapsTo.Add(RemapType.Float, floatKeys);
                    remapsFrom.Add(RemapType.Float, floatKeys);
                    for (int i = 0; i < floatsArray.arraySize; i++)
                    {
                        SerializedProperty @float = floatsArray.GetArrayElementAtIndex(i);
                        SerializedProperty key    = @float.FindPropertyRelative("first");
                        floatKeys.Add(key.stringValue);
                    }
                    //-----------------------------------------------------------------------------------

                    //Vectors and Colors ----------------------------------------------------------------
                    SerializedProperty colorsArray = savedProperties.FindPropertyRelative("m_Colors");
                    //colors have no way of telling if they're not set, so they can use the same set
                    var vectorKeys = new HashSet <string>();
                    remapsTo.Add(RemapType.VectorOrColor, vectorKeys);
                    remapsFrom.Add(RemapType.VectorOrColor, vectorKeys);
                    for (int i = 0; i < colorsArray.arraySize; i++)
                    {
                        SerializedProperty vector = colorsArray.GetArrayElementAtIndex(i);
                        SerializedProperty key    = vector.FindPropertyRelative("first");
                        vectorKeys.Add(key.stringValue);
                    }

                    //-----------------------------------------------------------------------------------
                }

                //CONTROLS
                var remapTypeField = new EnumField("Remap Type", RemapType.None)
                {
                    name = remapTypeName
                };
                remapTypeField.RegisterCallback <ChangeEvent <Enum> >(SelectedRemapType);
                shaderRoot.Add(remapTypeField);

                PopupField <string> popupFromField = new PopupField <string>(fromKeyLabel, noneList, 0)
                {
                    name = fromKeyPopupName
                };
                popupFromField.SetEnabled(false);
                shaderRoot.Add(popupFromField);

                PopupField <string> popupToField = new PopupField <string>(toKeyLabel, noneList, 0)
                {
                    name = toKeyPopupName
                };
                popupToField.SetEnabled(false);
                shaderRoot.Add(popupToField);

                Button remapButton = new Button {
                    text = "Remap", name = remapButtonName
                };
                remapButton.SetEnabled(false);
                shaderRoot.Add(remapButton);


                void SelectedRemapType(ChangeEvent <Enum> remapEvt)
                {
                    if (remapEvt == null)
                    {
                        throw new ArgumentNullException(nameof(remapEvt));
                    }

                    RemapType value = (RemapType)remapEvt.newValue;

                    if (value == RemapType.None)
                    {
                        GetButton().SetEnabled(false);
                        GetRemapTo().SetEnabled(false);
                        GetRemapFrom().SetEnabled(false);
                        return;
                    }

                    PopupField <string> child = GetRemapFrom();
                    int index = shaderRoot.IndexOf(child);

                    child.RemoveFromHierarchy();

                    List <string> choicesFrom = remapsFrom[value].ToList();

                    choicesFrom.Insert(0, none);
                    popupFromField = new PopupField <string>(fromKeyLabel, choicesFrom, none)
                    {
                        name = fromKeyPopupName
                    };
                    shaderRoot.Insert(index, popupFromField);
                    popupFromField.RegisterCallback <ChangeEvent <string> >(SelectedRemapFrom);
                }

                void SelectedRemapFrom(ChangeEvent <string> popupFromEvt)
                {
                    string remapFromKey = popupFromEvt.newValue;

                    if (remapFromKey == none)
                    {
                        GetButton().SetEnabled(false);
                        GetRemapTo().SetEnabled(false);
                        return;
                    }

                    PopupField <string> child = GetRemapTo();
                    int index = shaderRoot.IndexOf(child);

                    child.RemoveFromHierarchy();

                    List <string> choicesTo = remapsTo[(RemapType)remapTypeField.value].ToList();

                    choicesTo.Insert(0, none);
                    popupToField = new PopupField <string>(toKeyLabel, choicesTo, none)
                    {
                        name = toKeyPopupName
                    };
                    shaderRoot.Insert(index, popupToField);
                    popupToField.RegisterCallback <ChangeEvent <string>, (PopupField <string>, string)>(SelectedRemapTo, (popupToField, remapFromKey));
                }

                void SelectedRemapTo(ChangeEvent <string> popupToEvt, (PopupField <string> popupToField, string remapFromKey) args)
                {
                    string        remapToKey = popupToEvt.newValue;
                    VisualElement background = args.popupToField.Q(null, PopupField <string> .inputUssClassName);

                    if (remapToKey == none)
                    {
                        GetButton().SetEnabled(false);
                        background.style.unityBackgroundImageTintColor = default;
                        return;
                    }

                    if (remapToKey == args.remapFromKey)
                    {
                        background.style.unityBackgroundImageTintColor = new Color(1f, 0.46f, 0.51f);
                        return;
                    }

                    background.style.unityBackgroundImageTintColor = default;

                    var button = GetButton();

                    button.SetEnabled(true);
                    button.RemoveManipulator(button.clickable);
                    button.clickable = new Clickable(() => PerformRemap(shader, (RemapType)GetRemapType().value, args.remapFromKey, remapToKey));
                    button.AddManipulator(button.clickable);
                }

                Button GetButton() => shaderRoot.Q <Button>(remapButtonName);
                EnumField GetRemapType() => shaderRoot.Q <EnumField>(remapTypeName);
                PopupField <string> GetRemapFrom() => shaderRoot.Q <PopupField <string> >(fromKeyPopupName);
                PopupField <string> GetRemapTo() => shaderRoot.Q <PopupField <string> >(toKeyPopupName);
            }
        }
        void PerformRemap(Shader shader, RemapType remapType, string fromKey, string toKey)
        {
            if (remapType == RemapType.None)
            {
                Debug.LogError($"This shouldn't happen. {RemapType.None} has been provided to Perform Remap");
                return;
            }

            EditorUtility.DisplayProgressBar("Remapping", "Remapping materials", 0);
            StringBuilder log = new StringBuilder();

            try
            {
                string[] guids = AssetDatabase.FindAssets($"t:{nameof(Material)}");

                for (var index = 0; index < guids.Length; index++)
                {
                    if (index % 5 == 0)
                    {
                        if (EditorUtility.DisplayCancelableProgressBar("Remapping", "Remapping materials", index / (float)(guids.Length - 1)))
                        {
                            EditorUtility.ClearProgressBar();
                            return;
                        }
                    }

                    string guid     = guids[index];
                    string path     = AssetDatabase.GUIDToAssetPath(guid);
                    var    material = AssetDatabase.LoadAssetAtPath <Material>(path);
                    try
                    {
                        if (material.shader != shader)
                        {
                            continue;
                        }
                        using (SerializedObject materialSO = new SerializedObject(material))
                        {
                            SerializedProperty savedProperties = materialSO.FindProperty("m_SavedProperties");
                            SerializedProperty source;
                            switch (remapType)
                            {
                            case RemapType.Texture:
                                source = savedProperties.FindPropertyRelative("m_TexEnvs");
                                break;

                            case RemapType.Float:
                                source = savedProperties.FindPropertyRelative("m_Floats");
                                break;

                            case RemapType.VectorOrColor:
                                source = savedProperties.FindPropertyRelative("m_Colors");
                                break;

                            default:
                                throw new ArgumentOutOfRangeException(nameof(remapType), remapType, null);
                            }

                            //Collect the source and destination remappings
                            SerializedProperty from = null;
                            int fromIndex           = -1;
                            int toIndex             = -1;
                            for (int i = 0; i < source.arraySize; i++)
                            {
                                SerializedProperty value = source.GetArrayElementAtIndex(i);
                                SerializedProperty key   = value.FindPropertyRelative("first");
                                if (key.stringValue == fromKey)
                                {
                                    from      = value;
                                    fromIndex = i;
                                    if (toIndex != -1)
                                    {
                                        break;
                                    }
                                    continue;
                                }

                                if (key.stringValue == toKey)
                                {
                                    toIndex = i;
                                    if (from != null)
                                    {
                                        break;
                                    }
                                }
                            }

                            if (from == null)
                            {
                                log.AppendLine($"Failed to modify {materialSO.targetObject}. It did not contain the From property.");                                 //<color=#aa4400ff>
                                continue;
                            }

                                                        #if !OVERWRITE_SOURCE
                            //TODO this has not been tested, it almost certainly needs to do a copy
                            source.InsertArrayElementAtIndex(fromIndex);
                            from = source.GetArrayElementAtIndex(fromIndex);
                                                        #endif

                            if (remapType == RemapType.Texture)
                            {
                                SerializedProperty texProp = from.FindPropertyRelative("second.m_Texture");
                                if (texProp != null)
                                {
                                    if (texProp.objectReferenceValue == null)
                                    {
                                        log.AppendLine($"{materialSO.targetObject} was skipped as it did not have a texture set in the From property.");                                         //<color=#aa4400ff>
                                        continue;
                                    }
                                }
                            }

                            //Re-assign from's key to be the destination key.
                            from.FindPropertyRelative("first").stringValue = toKey;

                            if (toIndex != -1)
                            {
                                //Delete pre-existing "to"
                                source.DeleteArrayElementAtIndex(toIndex);
//							source.DeleteArrayElementAtIndex(toIndex);
                            }

                            materialSO.ApplyModifiedProperties();


                            log.AppendLine($"Modified {materialSO.targetObject} successfully.");                             //<color=#22aa22ff>
                        }
                    }
                    catch (Exception e)
                    {
                        log.AppendLine($"\"{path}\" was skipped as an exception occurred.");                         //<color=#aa4400ff>
                        Debug.LogWarning("Exception was encountered, remap will continue.");
                        Debug.LogException(e);
                    }
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }

            Debug.LogWarning(log.ToString());
        }