public override void OnInspectorGUI() { Object obj = Selection.activeObject; if (obj != null) { prefabLinkIcon = AssetDatabase.LoadAssetAtPath <Texture2D>("Assets/Packages/TP/Prefabulous/Textures/Prefabulous Icon Big.png"); IconManager.SetIcon(obj as GameObject, prefabLinkIcon); } MovePrefabLinksToTop(); int columns = 4; float padding = 60; float buttonWidth = (EditorGUIUtility.currentViewWidth / columns) - (padding / columns); float buttonHeight = EditorGUIUtility.singleLineHeight; bool smallButtons = buttonWidth < 90; int prefabLinksSelected = PrefabLinks.Count; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Target", GUILayout.Width(40)); EditorGUI.BeginChangeCheck(); GameObject prefabLinkTarget = EditorGUILayout.ObjectField(FirstPrefabLink.Target, typeof(GameObject), GUILayout.ExpandWidth(true)) as GameObject; if (EditorGUI.EndChangeCheck()) { foreach (PrefabLink prefabLink in PrefabLinks) { prefabLink.Target = prefabLinkTarget; } } if (FirstPrefabLink.Target == null) { string createPrefabButtonText = "Create Prefab"; if (prefabLinksSelected > 1) { createPrefabButtonText = "Create Prefabs (" + prefabLinksSelected + ")"; } if (smallButtons) { createPrefabButtonText = "Create"; } if (GUILayout.Button(createPrefabButtonText, GUILayout.Width(buttonWidth))) { int multiPrefabDialogueResult = -1; if (prefabLinksSelected > 1) { multiPrefabDialogueResult = EditorUtility.DisplayDialogComplex("You've got multiple PrefabsLinks selected", "We are about to try to create " + prefabLinksSelected + " prefabs. How would you like to continue?", "Skip Prompts", //0 "Show All Prompts", //1 "Cancel"); //2 Close with x is also results in a 2. if (multiPrefabDialogueResult != 2) { string absoluteDirectoryPath = EditorUtility.OpenFolderPanel("Select Prefab Folder", "", ""); bool processCanceled = false; int prefabsCreated = 0; foreach (PrefabLink selectedPrefabLink in PrefabLinks) { string saveAttemptAppend = ""; int fileSaveAttempts = 0; bool saved = false; string prefabName = ""; string prefabPath = ""; while (!saved) { prefabName = selectedPrefabLink.name + saveAttemptAppend + ".prefab"; prefabPath = AbsolutePathToRelative(absoluteDirectoryPath) + "/" + prefabName; if (!File.Exists(prefabPath)) { saved = true; } else { fileSaveAttempts++; saveAttemptAppend = " (" + fileSaveAttempts + ")"; } } if (multiPrefabDialogueResult == 1) { string absolutePath = EditorUtility.SaveFilePanel( "Save new Prefab Target", absoluteDirectoryPath, prefabName, "prefab"); if (absolutePath.Length > 0) { prefabPath = AbsolutePathToRelative(absolutePath); } else { processCanceled = true; EditorUtility.DisplayDialog( "Process Aborted", "Process Aborted after creating " + prefabsCreated + " of " + prefabLinksSelected + " prefabs", "Ok"); break; } } if (!processCanceled) { selectedPrefabLink.Target = PrefabUtility.CreatePrefab(prefabPath, selectedPrefabLink.gameObject); TriggerApplyAll(); prefabsCreated++; } else { break; } } } } else { string absolutePath = EditorUtility.SaveFilePanel( "Save new Prefab Target", "", FirstPrefabLink.name + ".prefab", "prefab"); if (absolutePath.Length > 0) { FirstPrefabLink.Target = PrefabUtility.CreatePrefab(AbsolutePathToRelative(absolutePath), FirstPrefabLink.gameObject); TriggerApplyAll(); } } } } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); bool prefabFileSelected = false; bool canRevert = true; bool canRevertAll = true; bool canApply = true; bool canApplyAll = true; if (FirstPrefabLink.Target == null) { canRevert = false; canRevertAll = false; canApply = false; canApplyAll = false; } else { foreach (PrefabLink prefabLink in PrefabLinks) { if (prefabLink.gameObject.IsPrefab()) { prefabFileSelected = true; } if (prefabLink.Target == prefabLink.gameObject) { canRevert = false; } } } GUI.enabled = canRevert; if (GUILayout.Button("Revert", GUILayout.Width(buttonWidth))) { TriggerRevert(); } GUI.enabled = canRevertAll && !PrefabLink.useUnityEditorRevert; if (GUILayout.Button(smallButtons ? "All" : "Revert All", GUILayout.Width(buttonWidth))) { TriggerRevertHierarchy(); } GUI.enabled = canApply; if (GUILayout.Button("Apply", GUILayout.Width(buttonWidth))) { TriggerApply(); } GUI.enabled = canApplyAll && !PrefabLink.useUnityEditorApply; if (GUILayout.Button(smallButtons ? "All" : "Apply All", GUILayout.Width(buttonWidth))) { TriggerApplyAll(); } EditorGUILayout.EndHorizontal(); GUI.enabled = true; foreach (PrefabLink prefabLink in PrefabLinks) { float startTime = prefabLink.StartTime; bool revertSuccessful = prefabLink.copySuccessful; float messageDisplayTime = (float)EditorApplication.timeSinceStartup - startTime; if (messageDisplayTime < messageDuration && messageDisplayTime > 0) { if (!revertSuccessful) { message = prefabLink.name + " - Reverting may have ran into issues. See console output."; messageType = MessageType.Warning; } else { message = prefabLink.name + " - Reverting succesful."; messageType = MessageType.Info; } //EditorGUILayout.HelpBox(message, messageType); //Dont know why this breaks. Balls. } } PrefabLink.advancedOptions = EditorGUILayout.Foldout(PrefabLink.advancedOptions, "Advanced"); if (PrefabLink.advancedOptions) { PrefabLink.ChangeNames = EditorGUILayout.Toggle("Change Names", PrefabLink.ChangeNames); PrefabLink.useUnityEditorRevert = EditorGUILayout.Toggle("Use Unity Revert", PrefabLink.useUnityEditorRevert); PrefabLink.useUnityEditorApply = EditorGUILayout.Toggle("Use Unity Apply", PrefabLink.useUnityEditorApply); ExtensionMethods.ExtensionMethods.masterVerbose = EditorGUILayout.Toggle("Verbose", ExtensionMethods.ExtensionMethods.masterVerbose); EditorGUILayout.Toggle("Is Dirty", firstPrefabLink.Dirty); //PrefabLink.dirtyChecksPerSecond = EditorGUILayout.Slider("Dirty Checks/Sec", PrefabLink.dirtyChecksPerSecond, 0, 10); //if (PrefabLink.dirtyChecksPerSecond == 0) //{ // if (GUILayout.Button(smallButtons ? "Check" : "Check Dirty", GUILayout.Width(buttonWidth))) // { // foreach (PrefabLink prefabLink in PrefabLinks) // { // prefabLink.UpdateDirty(); // } // EditorApplication.RepaintHierarchyWindow(); // } //} EditorGUI.indentLevel++; EditorGUILayout.BeginHorizontal(); Rect reportFoldoutRect = EditorGUILayout.GetControlRect(GUILayout.Width(buttonWidth)); PrefabLink.showDirtyObjects = EditorGUI.Foldout(reportFoldoutRect, PrefabLink.showDirtyObjects, "Dirty Report"); PrefabLink.dirtyChecksPerSecond = EditorGUILayout.Slider(PrefabLink.dirtyChecksPerSecond, 0, 10, GUILayout.Width(buttonWidth)); EditorGUILayout.LabelField(smallButtons ? "Check(s)" : "Check(s)/Second", GUILayout.Width(buttonWidth)); if (GUILayout.Button(smallButtons ? "Refresh" : "Refresh", GUILayout.Width(buttonWidth))) { PrefabLink.showDirtyObjects = true; foreach (PrefabLink prefabLink in PrefabLinks) { prefabLink.UpdateDirty(); } EditorApplication.RepaintHierarchyWindow(); } EditorGUILayout.EndHorizontal(); if (PrefabLink.showDirtyObjects) { if (firstPrefabLink.DirtyReport.Length == 0) { EditorGUILayout.LabelField("NO REPORT FOUND"); } else { int currentAddLimit = FirstPrefabLink.DirtyReport.AddLimit; FirstPrefabLink.DirtyReport.AddLimit = EditorGUILayout.IntSlider("History", FirstPrefabLink.DirtyReport.AddLimit, 0, 100); if (currentAddLimit != FirstPrefabLink.DirtyReport.AddLimit) { FirstPrefabLink.UpdateDirty(); } float[] columnWidth = { buttonWidth * 1.5f, buttonWidth * 1.5f, buttonWidth }; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("OBJECT", EditorStyles.boldLabel, GUILayout.Width(columnWidth[0])); EditorGUILayout.LabelField("MATCH", EditorStyles.boldLabel, GUILayout.Width(columnWidth[1])); EditorGUILayout.LabelField("TYPE", EditorStyles.boldLabel, GUILayout.Width(columnWidth[2])); EditorGUILayout.EndHorizontal(); Color defaultGuiColor = GUI.color; foreach (object objectInReport in firstPrefabLink.DirtyReport.BadMatches.Union(firstPrefabLink.DirtyReport.GoodMatches)) //foreach (object objectInReport in firstPrefabLink.DirtyReport.AllMatches) { ValueEqualsReportMatch matchDetails = firstPrefabLink.DirtyReport.GetMatchDetails(objectInReport); bool show = true; Color matchColor = defaultGuiColor; string type = ""; switch (matchDetails.Type) { case ValueEqualsReportMatchType.NONE: matchColor = new Color(1, .3f, .3f); //light red type = "None"; break; case ValueEqualsReportMatchType.NAMES_EQUAL: matchColor = new Color(1, .6f, .3f); //light orange type = "Names equal"; break; case ValueEqualsReportMatchType.TARGET_EQUAL: matchColor = new Color(1, 1, 0); //yellow type = "Target equals"; break; case ValueEqualsReportMatchType.VALUE_EQUAL: matchColor = Color.green; type = "Deep equal"; break; case ValueEqualsReportMatchType.EQUAL: matchColor = Color.green; type = "Equal"; break; case ValueEqualsReportMatchType.REFERENCE_EQUAL: matchColor = Color.green; type = "Referecne equal"; break; } if (show) { EditorGUILayout.BeginHorizontal(); Object unityObjectInReport = objectInReport as Object; if (unityObjectInReport != null) { EditorGUILayout.ObjectField(unityObjectInReport as Object, typeof(Object), false, GUILayout.Width(columnWidth[0])); } else { EditorGUILayout.TextField(objectInReport.ToString(), GUILayout.Width(columnWidth[0] - 18)); EditorGUILayout.LabelField("", GUILayout.Width(14)); } GUI.color = matchColor; if (matchDetails.Match is Object || matchDetails.Match == null) { EditorGUILayout.ObjectField(matchDetails.Match as Object, typeof(Object), false, GUILayout.Width(columnWidth[1])); } else { EditorGUILayout.TextField(matchDetails.Match.ToString(), GUILayout.Width(columnWidth[0] - 18)); EditorGUILayout.LabelField("", GUILayout.Width(14)); } GUI.color = defaultGuiColor; EditorGUILayout.SelectableLabel(type, GUILayout.Width(columnWidth[2]), GUILayout.Height(EditorGUIUtility.singleLineHeight)); EditorGUILayout.EndHorizontal(); List <string> notes = firstPrefabLink.DirtyReport.GetNotes(objectInReport); if (notes != null) { EditorGUI.indentLevel++; foreach (string note in notes) { EditorGUILayout.SelectableLabel(note, GUILayout.Height(EditorGUIUtility.singleLineHeight)); } EditorGUI.indentLevel--; } } } } } EditorGUI.indentLevel--; EditorGUI.indentLevel++; PrefabLink.debugInfo = EditorGUILayout.Foldout(PrefabLink.debugInfo, "Debug Info"); if (PrefabLink.debugInfo) { EditorGUILayout.SelectableLabel("isPrefab: " + FirstPrefabLink.gameObject.IsPrefab(), GUILayout.ExpandWidth(true), GUILayout.Height(EditorGUIUtility.singleLineHeight)); EditorGUILayout.SelectableLabel("hierarchyCount: " + FirstPrefabLink.transform.hierarchyCount, GUILayout.ExpandWidth(true), GUILayout.Height(EditorGUIUtility.singleLineHeight)); EditorGUILayout.SelectableLabel("hierarchyCapacity: " + FirstPrefabLink.transform.hierarchyCapacity, GUILayout.ExpandWidth(true), GUILayout.Height(EditorGUIUtility.singleLineHeight)); EditorGUILayout.SelectableLabel("childCount: " + FirstPrefabLink.transform.childCount, GUILayout.ExpandWidth(true), GUILayout.Height(EditorGUIUtility.singleLineHeight)); EditorGUILayout.SelectableLabel("parentDepth: " + FirstPrefabLink.transform.ParentDepth(), GUILayout.ExpandWidth(true), GUILayout.Height(EditorGUIUtility.singleLineHeight)); EditorGUILayout.SelectableLabel("PrefabLink ID: " + FirstPrefabLink.GetInstanceID(), GUILayout.ExpandWidth(true), GUILayout.Height(EditorGUIUtility.singleLineHeight)); EditorGUILayout.SelectableLabel("PrefabLink.gameObject ID: " + FirstPrefabLink.gameObject.GetInstanceID(), GUILayout.ExpandWidth(true), GUILayout.Height(EditorGUIUtility.singleLineHeight)); if (FirstPrefabLink.Target != null) { EditorGUILayout.SelectableLabel("PrefabLink.target ID: " + FirstPrefabLink.Target.GetInstanceID(), GUILayout.ExpandWidth(true), GUILayout.Height(EditorGUIUtility.singleLineHeight)); } } EditorGUI.indentLevel--; } if (FirstPrefabLink.gameObject.IsPrefab()) { PrefabLink.prefabOnlyOptions = EditorGUILayout.Foldout(PrefabLink.prefabOnlyOptions, "Prefab Options"); if (PrefabLink.prefabOnlyOptions) { EditorGUILayout.HelpBox("This is experimental and might blow your stuff up.", MessageType.Info); //TODO: Need to check if any prefab links refeence this since it you can revert from scene objects GUI.enabled = false; PrefabLink.propogateChanges = EditorGUILayout.Toggle("Auto Propogate Changes", PrefabLink.propogateChanges); EditorGUILayout.TextArea("Auto Propogate Changes doesn't work yet. It still can't \ncheck changes to avoid overwriting them."); GUI.enabled = true; if (!PrefabLink.propogateChanges) { if (GUILayout.Button("Revert Instances", GUILayout.Width(buttonWidth * 2))) { TriggerRevertAllInstances(); } } } } UpdateDirtyPrefabLinks(); }
public void CopyComponentsAndChildren(GameObject from, GameObject to, bool ignoreTransform = true, bool ignorePrefabLink = true) { bool copyEvenWhenEqual = true; if (from != null) { //Copy prefab children foreach (Transform child in from.transform) { if (!dirtyReport.Matched(child.gameObject)) { Transform newChild = Instantiate(child, to.transform, false); newChild.name = child.name; #if UNITY_EDITOR Undo.RegisterCreatedObjectUndo(newChild.gameObject, "Prefab Link: Copy child GameObject"); #endif } else { GameObject fromChild = child.gameObject; GameObject toChild = dirtyReport.GetMatch(fromChild) as GameObject; CopyComponentsAndChildren(fromChild, toChild, ignoreTransform, ignorePrefabLink); } } List <Component> needsAdding = new List <Component> { }; List <Component> needsCopying = new List <Component> { }; foreach (Component component in from.GetComponents <Component>()) { bool ignore = false; //Not using ignoreTransform and always ignoring no matter what. if (/*ignoreTransform &&*/ component.GetType() == typeof(Transform) || ignorePrefabLink && component.GetType() == typeof(PrefabLink)) { ignore = true; } if (!ignore) { if (!dirtyReport.Matched(component)) { needsAdding.Add(component); } else { ValueEqualsReportMatch match = dirtyReport.GetMatchDetails(component); if (match.Type == ValueEqualsReportMatchType.NAMES_EQUAL || copyEvenWhenEqual) { Component toComponent = match.Match as Component; toComponent.CopyComponent(component); } } } } while (needsAdding.Count > 0) { CopyComponentFromList(needsAdding[0], needsAdding, to, ignoreTransform, ignorePrefabLink); } //List<Component> componentsToAdd = from.GetComponents<Component>() // .Where((item) => !dirtyReport.Matched(item)) // .ToList(); ////Copy prefab components //while (componentsToAdd.Count > 0) //{ // CopyComponentAndRequiredComponents(componentsToAdd[0], componentsToAdd, to, ignoreTransform, ignorePrefabLink); //} if (ExtensionMethods.ExtensionMethods.includeNames) { if (to != null && from != null) { to.name = from.name; } } } }