Skip to main content
Version: 2.0.6

(PRO) Custom editor controls

In this guide, we will see how to override the default look of level graph editor rooms and connections in order to add custom icons.

Note: This pages is not meant to be an in-depth guide. Please look at the source code of this example for more information.

Result of this guide. Custom icons for rooms and connection.

Note: All files from this example can be found at Examples/Grid2D/CustomEditorControls.

Create custom room type​

Create a custom room type as documented here. I also created a RoomType enum which will control if a room has an icon next to it.

/// <summary>
/// Simple custom room to demonstrate custom editor controls.
/// </summary>
public class CustomEditorControlsRoom : RoomBase
{
/// <summary>
/// Each room has a type that determines the display name and icon.
/// </summary>
public enum RoomType
{
Basic,
Treasure,
Shop,
Boss,
Spawn
}

/// <summary>
/// Type of the room.
/// </summary>
public RoomType Type = RoomType.Basic;

public override List<GameObject> GetRoomTemplates()
{
// Not implemented in this example
throw new System.NotImplementedException();
}

public override string GetDisplayName()
{
return Type.ToString();
}

/* ... */
}

Create custom room control​

Create a class that will override the default look of rooms in the level graph editor. First, create a class that inherits from RoomControl. Then, add the CustomRoomControl attribute and specify for which room should the custom control be used.

After that, you can override the default implementation of the RoomControl class. In this example, I extended the default implementation with a logic that checks the type of the room and displays an icon if there is any assigned to that room type. You can find more details in the source code.

/// <summary>
/// Simple example of a custom editor control for the CustomEditorControlsRoom room type.
/// </summary>
[CustomRoomControl(typeof(CustomEditorControlsRoom))]
private class Control : RoomControl
{
/// <summary>
/// Mapping from room types to icon textures.
/// </summary>
private static readonly Dictionary<RoomType, Texture2D> RoomTypeIcons;

static Control()
{
// Initialize icons in the static constructor
RoomTypeIcons = new Dictionary<RoomType, Texture2D>()
{
{RoomType.Treasure, CustomEditorControlsIcons.Base64ToTexture(CustomEditorControlsIcons.TreasureIcon, FilterMode.Point)},
{RoomType.Shop, CustomEditorControlsIcons.Base64ToTexture(CustomEditorControlsIcons.ShopIcon, FilterMode.Point)},
{RoomType.Boss, CustomEditorControlsIcons.Base64ToTexture(CustomEditorControlsIcons.BossIcon, FilterMode.Point)},
{RoomType.Spawn, CustomEditorControlsIcons.Base64ToTexture(CustomEditorControlsIcons.SpawnIcon, FilterMode.Point)},
};
}

/// <summary>
/// Override the Draw method to draw a custom control.
/// </summary>
public override void Draw(Vector2 gridOffset, float zoom)
{
// Draw the base control
base.Draw(gridOffset, zoom);

// Make sure that we work with the correct room type
var room = Room as CustomEditorControlsRoom;
if (room == null)
{
return;
}

// If we have an icon for the current room type, we will draw it
if (RoomTypeIcons.TryGetValue(room.Type, out var icon))
{
// Use the default control rect as a base for position and size of icon
var rect = GetRect(gridOffset, zoom);
rect.y -= rect.height / 4;
rect.height /= 2;

// Make the icon larger if it is the boss room
if (room.Type == RoomType.Boss)
{
rect.height *= 1.5f;
}

// Compute correct rect width
var textureRatio = icon.width / (float) icon.height;
rect.width = rect.height * textureRatio;

// Draw the icon
GUI.DrawTexture(rect, icon);
}
}
}

Custom connections and connection editors​

The process of creating custom connection editors is exactly the same as for rooms. Just replace the word room with connection in class names.