Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save unitycoder/8ae1d5f4f07df1bd37ff424c574b4292 to your computer and use it in GitHub Desktop.
Save unitycoder/8ae1d5f4f07df1bd37ff424c574b4292 to your computer and use it in GitHub Desktop.
Code running pack! two property drawing scripts that make it super easy to trigger code via buttons in the inspector, and get feedback! [TestButton] draws you little buttons that call a method on your MonoBehaviour, and [ProgressBar] give you a great way to show feedback from long running methods. These are *super* helpful for things like proced…
using UnityEngine;
using System.Collections;
public class InspectorButtonsTest : MonoBehaviour
{
[TestButton("Generate world", "DoProcGen", isActiveInEditor = false)]
[TestButton("Clear world", "ClearWorld", 2, isActiveInEditor = false)]
[ProgressBar(hideWhenZero = true, label = "procGenFeedback")]
public float procgenProgress = -1;
[HideInInspector]
public string procGenFeedback;
// Silly little enumerator to test progress bars~
IEnumerator DoProcGen()
{
// lets pretend we have some code here that procedurally generates a map
procGenFeedback = "Initilizing";
procgenProgress = 0.01f;
yield return new WaitForSeconds(0.25f);
procGenFeedback = "Seeding terrain";
procgenProgress = 0.2f;
yield return new WaitForSeconds(0.25f);
procGenFeedback = "Plotting cities";
procgenProgress = 0.4f;
yield return new WaitForSeconds(0.25f);
procGenFeedback = "Drawing roads";
procgenProgress = 0.6f;
yield return new WaitForSeconds(0.25f);
procGenFeedback = "Reticulating splines";
procgenProgress = 0.8f;
yield return new WaitForSeconds(0.25f);
procGenFeedback = "Finalizing";
procgenProgress = 0.9f;
yield return new WaitForSeconds(0.25f);
procGenFeedback = "DONE in 6 seconds";
procgenProgress = 1f;
}
// resets values
void ClearWorld()
{
procgenProgress = 0;
}
}
using UnityEngine;
public class ProgressBarAttribute : PropertyAttribute
{
public bool hideWhenZero;
public string label;
}
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(ProgressBarAttribute))]
public class ProgressBarDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType != SerializedPropertyType.Float)
{
GUI.Label(position, "ERROR: can only apply progress bar onto a float");
return;
}
if ((attribute as ProgressBarAttribute).hideWhenZero && property.floatValue <= 0)
return;
var dynamicLabel = property.serializedObject.FindProperty((attribute as ProgressBarAttribute).label);
EditorGUI.ProgressBar(position, property.floatValue/1f, dynamicLabel == null ? property.name : dynamicLabel.stringValue);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if ((attribute as ProgressBarAttribute).hideWhenZero && property.floatValue <= 0)
return 0;
return base.GetPropertyHeight(property, label);
}
}
// NOTE DONT put in an editor folder
using UnityEngine;
using System;
[AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = true)]
public class TestButtonAttribute : PropertyAttribute
{
public string buttonLabel;
public string methodName;
// Set this false to make the button not work whilst in playmode
public bool isActiveAtRuntime = true;
// Set this to false to make the button not work when the game isnt running
public bool isActiveInEditor = true;
public TestButtonAttribute(string buttonLabel, string methodName, int order = 1)
{
this.buttonLabel = buttonLabel;
this.methodName = methodName;
this.order = order; // Defualt the order to 1 so this can draw under headder attribles
}
}
// NOTE put in a Editor folder
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(TestButtonAttribute))]
public class TestButtonDrawer : DecoratorDrawer
{
public override void OnGUI(Rect position)
{
// cast the attribute to make it easier to work with
var buttonAttribute = (attribute as TestButtonAttribute);
// check if the button is supposed to be enabled right now
if (EditorApplication.isPlaying && !buttonAttribute.isActiveAtRuntime)
GUI.enabled = false;
if (!EditorApplication.isPlaying && !buttonAttribute.isActiveInEditor)
GUI.enabled = false;
// figure out where were drawing the button
var pos = new Rect(position.x, position.y, position.width, position.height - EditorGUIUtility.standardVerticalSpacing);
// draw it and if its clicked...
if (GUI.Button(pos, buttonAttribute.buttonLabel))
{
// tell the current game object to find and run the method we asked for!
Selection.activeGameObject.BroadcastMessage(buttonAttribute.methodName);
}
// make sure the GUI is enabled when were done!
GUI.enabled = true;
}
public override float GetHeight()
{
return EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing*2;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment