How to add and remove component with the same toggle in editor?
Hello, I need the possibility to add component with a click inside the editor view. In Particular i would like to add a component when the toggle is flagged and remove it when it is unflagged. I tried different solutions but each of them present the same problem, the toggle is unflagged instantly.
I don't want to use button because, i should create a button to add and one to remove the component and this for each component i want on the object....
I prefer the toggle because if it is flagged you undestand soon which component is added.
Any help is appreciated, also if you suggest a different way without toggles to do it.
My Solutions:
1st try:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
[CustomEditor(typeof(Initializer))]
public class InitializerEditor : Editor
{
bool component1 = false;
bool component2 = false;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
Initializer script = (Initializer)target;
component1= GUILayout.Toggle(component1, "Component 1");
component2= GUILayout.Toggle(component2, "Component 2");
if (component1)
{
if (script.gameObject.GetComponent<Component1>() == null)
{
script.gameObject.AddComponent<Component1>();
}
}
else
{
Component1 c1= script.gameObject.GetComponent<Component1>();
if (c1 != null)
{
DestroyImmediate(c1);
}
}
if (component2)
{
if (script.gameObject.GetComponent<Component2>() == null)
{
script.gameObject.AddComponent<Component2>();
}
}
else
{
Component2 c2= script.gameObject.GetComponent<Component2>();
if (c2 != null)
{
DestroyImmediate(c2);
}
}
}
}
2nd try
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
[CustomEditor(typeof(Initializer))]
public class InitializerEditor : Editor
{
bool component1 = false;
bool component2 = false;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
Initializer script = (Initializer)target;
component1= GUILayout.Toggle(component1, "Component 1");
component2= GUILayout.Toggle(component2, "Component 2");
if (component1)
{
if (script.gameObject.GetComponent<Component1>() == null)
{
script.gameObject.AddComponent<Component1>();
}
component1 = true;
}
else
{
Component1 c1= script.gameObject.GetComponent<Component1>();
if (c1 != null)
{
DestroyImmediate(c1);
}
}
if (component2)
{
if (script.gameObject.GetComponent<Component2>() == null)
{
script.gameObject.AddComponent<Component2>();
}
component2 = true;
}
else
{
Component2 c2= script.gameObject.GetComponent<Component2>();
if (c2 != null)
{
DestroyImmediate(c2);
}
}
}
}
3rd try
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
[CustomEditor(typeof(Initializer))]
public class InitializerEditor : Editor
{
bool component1 = false;
bool component2 = false;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
Initializer script = (Initializer)target;
component1= GUILayout.Toggle(component1, "Component 1");
component2= GUILayout.Toggle(component2, "Component 2");
if (component1)
{
script.addComponent("Component1"); //i made all the checks into the initializer script
}
else
{
script.removeComponent("Component1");
}
if (component2)
{
script.addComponent("Component2");
}
else
{
script.removeComponent("Component2");
}
}
}
If i try the following, all works perfectly and the flag remains falgged and i can unflag whenever i want.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
[CustomEditor(typeof(Initializer))]
public class InitializerEditor : Editor
{
bool component1 = false;
bool component2 = false;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
Initializer script = (Initializer)target;
component1= GUILayout.Toggle(component1, "Component 1");
component2= GUILayout.Toggle(component2, "Component 2");
if (component1)
{
Debug.Log("Component1 added!");
}
else
{
Debug.Log("Component1 removed!");
}
if (component1)
{
Debug.Log("Component2 added!");
}
else
{
Debug.Log("Component2 removed!");
}
}
}
Answer by Hellium · Sep 29, 2021 at 04:31 PM
SIMPLE VERSION
[CustomEditor(typeof(Initializer))]
public class InitializerEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
Initializer script = (Initializer)target;
DrawToggleComponent<MeshRenderer>(script.gameObject);
DrawToggleComponent<MeshFilter>(script.gameObject);
}
private void DrawToggleComponent<T>(GameObject targetObject) where T : Component
{
EditorGUI.BeginChangeCheck();
{
bool hadComponent = targetObject.TryGetComponent(out T component);
bool hasComponent = GUILayout.Toggle(hadComponent, typeof(T).Name);
if(EditorGUI.EndChangeCheck())
{
if (hasComponent && !hadComponent)
{
targetObject.AddComponent<T>();
}
else if(!hasComponent && hadComponent)
{
DestroyImmediate(component);
}
}
}
}
}
MORE COMPLEX VERSION
[CustomEditor(typeof(Initializer))]
public class InitializerEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
Initializer script = (Initializer)target;
if(DrawToggleComponent(script.gameObject, out MeshRenderer meshRenderer, onAdd: mr => Debug.Log("MeshRenderer added")))
{
Debug.Log("The object has a MeshFilter");
}
DrawToggleComponent(script.gameObject, out MeshFilter meshFilter, "My super component!");
}
private bool DrawToggleComponent<T>(GameObject targetObject, out T component, string label = null, Action<T> onAdd = null, Action<T> onRemove = null)
where T : Component
{
bool hadComponent = targetObject.TryGetComponent(out component);
bool hasComponent = hadComponent;
EditorGUI.BeginChangeCheck();
{
hasComponent = GUILayout.Toggle(hadComponent, label ?? typeof(T).Name);
if (EditorGUI.EndChangeCheck())
{
if (hasComponent && !hadComponent)
{
component = targetObject.AddComponent<T>();
onAdd?.Invoke(component);
}
else if(!hasComponent && hadComponent)
{
onRemove?.Invoke(component);
DestroyImmediate(component);
}
}
}
return hasComponent;
}
}
Your answer
Follow this Question
Related Questions
[Help] GUI Button - Enables Raycast Which Selects The Object In Scene Hierarchy Through Play Window 0 Answers
GUI.Window. Wanting to allow clickthrough 0 Answers
Do Unity Editor GUI Utilities (Handles.DrawLine & EditorGUI.DrawRect) have limitations? 2 Answers
Unity Editor - Group Public GameObjects 0 Answers
How to change the text of EditorGUILayout.TextField 2 Answers