I been looking around and cannot seem to find if there is a way to load and save editor layouts in C#.
I got this editor below.
As you can see your workspaces appear in Unity’s toolbar as buttons. You define the workspaces in preferences under “workspace”.
This is what I need help exactly on.
- When I press “Capture Workspace Layout” it will save layout for current selected workspace.
- When I press workspace button in toolbar the correct workspace will be loaded and set.
Here is my code so far for capturing workspace layout.
// Gui (Capture)
EditorGUILayout.LabelField("Capture", EditorStyles.boldLabel);
selectedWorkspaceItemsPropertyIndex = EditorGUILayout.Popup("Selected Workspace", selectedWorkspaceItemsPropertyIndex, GetOrCreatePreferences().workspaces.Select(workspace => workspace.name).ToArray());
if (GUILayout.Button("Capture Workspace Layout"))
{
// Get Selected Workspace Item
var selectedWorkspaceItem = GetOrCreatePreferences().workspaces[selectedWorkspaceItemsPropertyIndex];
// Specify the path and filename for the layout file
string layoutAssetName = "workspaces." + selectedWorkspaceItem.name;
string layoutPath = "Assets/Editor/Layouts/" + layoutAssetName +".layout";
// Save the current layout
// Output Message
Debug.Log("Layout saved at: " + layoutPath);
}
// https://discussions.unity.com/t/programmatically-change-editor-layout/60774/4
using System;
using System.IO;
using System.Reflection;
public static class LayoutUtility
{
private enum MethodType {Save, Load};
static MethodInfo GetMethod(MethodType method_type)
{
Type layout = Type.GetType("UnityEditor.WindowLayout,UnityEditor");
if (layout == null) return null;
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
if (method_type == MethodType.Save)
return layout.GetMethod("SaveWindowLayout", flags, null, new Type[] {typeof(string)}, null);
if (method_type == MethodType.Load)
return layout.GetMethod("LoadWindowLayout", flags, null, new Type[] {typeof(string), typeof(bool)}, null);
return null;
}
public static void SaveLayout(string path)
{
path = Path.Combine(Directory.GetCurrentDirectory(), path);
GetMethod(MethodType.Save).Invoke(null, new object[] {path});
}
public static void LoadLayout(string path)
{
path = Path.Combine(Directory.GetCurrentDirectory(), path);
GetMethod(MethodType.Load).Invoke(null, new object[] {path, false});
}
}
This works but Load will reopen Unity window. I wonder how to make it not reopen and instead just load like when changing layouts manually in the upper right corner.
This method has several overloads and one is taking an argument called “keepMainWindow”. You most likely have to pass true here. The actual method has a signature like this:
public static bool LoadWindowLayout(string path, bool newProjectLayoutWasCreated, bool setLastLoadedLayoutName, bool keepMainWindow)
You’re using a wrapper that looks like this:
public static bool LoadWindowLayout(string path, bool newProjectLayoutWasCreated)
{
return LoadWindowLayout(path, newProjectLayoutWasCreated, setLastLoadedLayoutName: true, keepMainWindow: false);
}
@Bunny83 yep, thanks
using System;
using System.IO;
using System.Reflection;
public static class LayoutUtility
{
private enum MethodType {Save, Load};
static MethodInfo GetMethod(MethodType method_type)
{
Type layoutType = Type.GetType("UnityEditor.WindowLayout,UnityEditor");
if (layoutType == null) return null;
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
if (method_type == MethodType.Save)
return layoutType.GetMethod("SaveWindowLayout", bindingFlags, null, new Type[] {
typeof(string), // path
}, null);
if (method_type == MethodType.Load)
return layoutType.GetMethod("LoadWindowLayout", bindingFlags, null, new Type[] {
typeof(string), // path
typeof(bool), // newProjectLayoutWasCreated
typeof(bool), // setLastLoadedLayoutName
typeof(bool), // keepMainWindow
}, null);
return null;
}
public static void SaveLayout(string path)
{
path = Path.Combine(Directory.GetCurrentDirectory(), path);
GetMethod(MethodType.Save).Invoke(null, new object[] {path});
}
public static void LoadLayout(string path)
{
path = Path.Combine(Directory.GetCurrentDirectory(), path);
GetMethod(MethodType.Load).Invoke(null, new object[] {path, false, false, true});
}
}
As of Unity 2023 (maybe before ?) the API slightly changed. Here is an updated version :
using System;
using System.IO;
using System.Reflection;
public static class LayoutUtility
{
private enum MethodType { Save, Load };
static MethodInfo GetMethod(MethodType method_type)
{
Type layoutType = Type.GetType("UnityEditor.WindowLayout,UnityEditor");
if (layoutType == null) return null;
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
if (method_type == MethodType.Save)
return layoutType.GetMethod("SaveWindowLayout", bindingFlags, null, new Type[] {
typeof(string), // path
}, null);
if (method_type == MethodType.Load)
{
return layoutType.GetMethod("LoadWindowLayout", bindingFlags, null, new Type[] {
typeof(string), // path
typeof(bool), // newProjectLayoutWasCreated
typeof(bool), // setLastLoadedLayoutName
typeof(bool), // keepMainWindow
typeof(bool), // LogErrorToConsole
}, null);
}
return null;
}
public static void SaveLayout(string path)
{
path = Path.Combine(Directory.GetCurrentDirectory(), path);
GetMethod(MethodType.Save).Invoke(null, new object[] { path });
}
public static void LoadLayout(string path)
{
path = Path.Combine(Directory.GetCurrentDirectory(), path);
GetMethod(MethodType.Load).Invoke(null, new object[] { path, false, false, true, true});
}
}