Repository navigation
ManeStyle
[ManeStyle] switches the default inspector to Mane layout: framed blocks, a fixed label column, and foldout groups. Put it on a MonoBehaviour, a ScriptableObject, or a custom inspector type. All ManeEditor subclasses inherit it.
using Mane.Unity;
using UnityEngine;
[ManeStyle]
public class TestComponent : MonoBehaviour
{
[SerializeField] private string name;
[Space]
[SerializeField] private float health;
[Header("Combat")]
[SerializeField] private float damage;
[Foldout("Advanced")]
[SerializeField] private float critChance;
[SerializeField] private float critMultiplier;
}In a ManeStyle inspector:
-
Spacestarts a new visual block. -
Header("Title")starts a new block and adds a section title. -
NonBreakingSpaceadds the same gap asSpacebut does not split: the fields stay in the current block. -
Foldout("Title")starts aFoldoutBlock(persisted in EditorPrefs). Fields stay in that foldout until the nextSpace/Header/Foldout.
Without [ManeStyle], Foldout still draws a stock Unity foldout via the default inspector path.

At first glance it can look bulkier and take more space, but for a large component it is a lifesaver that adds a strict visual structure. For a small one, use fewer splitters and you still gain that visual consistency.
Subclass ManeEditor (Mane.Unity.Editor), assign a UXML on the editor script, and override BuildInspector to bind controls. If the UXML field is empty, the inspector logs an error and stays empty.
using Mane.Unity.Editor;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
[CustomEditor(typeof(MyComponent))]
public class MyComponentEditor : ManeEditor
{
protected override void BuildInspector(VisualElement root)
{
// Query named fields from the assigned UXML and wire them up.
SerializedProperty maxWidth = serializedObject.FindProperty("_maxWidth");
root.Require<PropertyField>("compactWidthField")?.ShowWhen(() => maxWidth.floatValue > 0f, maxWidth);
}
}Do not also put [ManeStyle] on a type that already has a custom ManeEditor with its own USS. The attribute is for default inspectors (or editors that should share Mane chrome).
| Type | Use |
|---|---|
ManeEditorStyles.Apply(root) |
Attach USS (mie-root, optional field layout). |
ManeInspectorLayout.Fill(...) |
Build default Mane blocks from serialized properties. |
FoldoutBlock |
Framed foldout with persisted state. |
HeaderToggle |
Section checkbox that shows/hides content. |
LimitedIntField |
Int field with custom labels for 0 / negative. |
LimitedFloatField |
Same as LimitedIntField, but decimal. |
ChildFields.CreateRow(field, last) |
Row for a field that belongs to a parent field (see below). |
UIElementsTools helps with custom inspectors:
-
LoadUSS/LoadUXMLload assets next to a script type. -
AddStyleSheet(element, typeof(MyControl))attachesMyControl.ussfrom next to the script, once per element. The sheet is loaded once and shared; a missing file is logged once. -
element.SetVisible(bool)shows or hides an element through its display style. -
element.ShowWhen(condition, properties)keeps an element shown only whileconditionholds. It is checked right away and again whenever one of the properties changes. -
root.Require<T>("name")finds an element the UXML must have, and logs an error naming it when it is missing. -
field.BindField(serializedObject, "m_Path")binds a field by property path and logs an error when the path does not exist.
A field that belongs to the field above it, like the curve under an EasingCurve dropdown or the fields of a SerializeInterface instance, is drawn as a child field: a branch mark in a fixed 15px slot, then the field. ChildFields gives these the same layout everywhere.
This is the ManeStyle look. In a default inspector a SerializeInterface instance and the EasingCurve curve row follow Unity's own nested fields instead (no branch marks; for SerializeInterface also the fold arrow in the margin and indented children), so they sit next to a plain serializable class without looking different.

Wrap each child with ChildFields.CreateRow(field, last) and add the returned row where the child should go. The row attaches its own stylesheet, so nothing else is needed.
VisualElement parent = new();
parent.Add(ChildFields.CreateRow(new PropertyField(first), last: false)); // ├
parent.Add(ChildFields.CreateRow(new PropertyField(second), last: true)); // └-
last: falsedraws├(ChildFields.MiddleMark) andlast: truedraws└(ChildFields.LastMark). A single child is alwayslast. - The mark is outside the layout flow, so a row is exactly as tall as its field and spacing matches standard fields.
- A wrapped
PropertyFielddrops its own left margin, so labels of every child start at the same x. Inside a ManeStyle inspector, its input also sits 6px further right than a standard input. - USS classes, if you need to style them:
mie-child-row,mie-child-branch,mie-child-content.
openupm add com.manefunction.tools-unity