Merge pull request #154 from XiaoBojun/main

toolbar拓展布局自适应优化,以及场景切换分组:初始场景、默认包、其他场景。
This commit is contained in:
ALEX
2025-05-26 14:10:33 +08:00
committed by GitHub
15 changed files with 298 additions and 225 deletions

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: fb0502859d7561142a3408d0ce2a19d8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,88 +0,0 @@
using UnityEditor;
using UnityEngine;
using UnityToolbarExtender;
namespace TEngine
{
[InitializeOnLoad]
public class EditorPlayMode
{
static class ToolbarStyles
{
public static readonly GUIStyle ToolBarExtenderBtnStyle;
public static readonly GUIStyle ToolBarTextStyle;
public static readonly GUIStyle ToolBarButtonGuiStyle;
static ToolbarStyles()
{
ToolBarExtenderBtnStyle = new GUIStyle("Command")
{
fontSize = 12,
alignment = TextAnchor.MiddleCenter,
imagePosition = ImagePosition.ImageAbove,
fontStyle = FontStyle.Normal,
fixedWidth = 60
};
ToolBarTextStyle = new GUIStyle(BUTTON_STYLE_NAME)
{
padding = new RectOffset(2, 8, 2, 2),
alignment = TextAnchor.MiddleCenter,
fontStyle = FontStyle.Bold
};
ToolBarButtonGuiStyle = new GUIStyle(BUTTON_STYLE_NAME)
{
padding = new RectOffset(2, 8, 2, 2),
alignment = TextAnchor.MiddleCenter,
fontStyle = FontStyle.Bold
};
}
}
static EditorPlayMode()
{
ToolbarExtender.RightToolbarGUI.Add(OnToolbarGUI);
_resourceModeIndex = EditorPrefs.GetInt("EditorPlayMode", 0);
}
private const string BUTTON_STYLE_NAME = "Tab middle";
static GUIStyle _buttonGuiStyle;
private static readonly string[] _resourceModeNames =
{
"EditorMode (编辑器下的模拟模式)",
"OfflinePlayMode (单机模式)",
"HostPlayMode (联机运行模式)",
"WebPlayMode (WebGL运行模式)"
};
private static int _resourceModeIndex = 0;
public static int ResourceModeIndex => _resourceModeIndex;
static void OnToolbarGUI()
{
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
// GUILayout.Label("资源加载模式:",ToolbarStyles.ToolBarTextStyle);
//GUILayout.Space(10);
//GUILayout.FlexibleSpace();
// 资源模式
int selectedIndex = EditorGUILayout.Popup("", _resourceModeIndex, _resourceModeNames, ToolbarStyles.ToolBarButtonGuiStyle);
// ReSharper disable once RedundantCheckBeforeAssignment
if (selectedIndex != _resourceModeIndex)
{
Debug.Log($"更改编辑器资源运行模式 : {_resourceModeNames[selectedIndex]}");
_resourceModeIndex = selectedIndex;
EditorPrefs.SetInt("EditorPlayMode", selectedIndex);
}
//GUILayout.FlexibleSpace();
//GUILayout.Space(400);
}
EditorGUI.EndDisabledGroup();
}
}
}

View File

@@ -1,115 +0,0 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
namespace UnityToolbarExtender.Examples
{
[InitializeOnLoad]
public sealed class SceneSwitchLeftButton
{
private static List<(string sceneName, string scenePath)> m_Scenes;
private static string[] m_SceneName;
private static string[] m_ScenePath;
private static int sceneSelected = 0;
static SceneSwitchLeftButton()
{
EditorApplication.projectChanged += UpdateCurrent;
UpdateCurrent();
ToolbarExtender.RightToolbarGUI.Add(OnToolbarGUI);
}
static void UpdateCurrent()
{
m_Scenes = SceneSwitcher.GetAllScenesInProject();
m_SceneName = new string[m_Scenes.Count];
m_ScenePath = new string[m_Scenes.Count];
for (int i = 0; i < m_Scenes.Count; i++)
{
var (name, path) = m_Scenes[i];
m_SceneName[i] = name;
m_ScenePath[i] = path;
if (SceneManager.GetActiveScene().path == path)
sceneSelected = i;
}
}
static void OnToolbarGUI()
{
if (sceneSelected >= m_SceneName.Length) //空项目0场景判断
return;
var size = EditorStyles.popup.CalcSize(new GUIContent(m_SceneName[sceneSelected]));
// 创建水平布局
//EditorGUILayout.BeginHorizontal();
GUILayout.Space(20);
// 将控件推到左边和右边
//GUILayout.FlexibleSpace(); // 先占用左边的所有空间
EditorGUILayout.LabelField("当前场景:", GUILayout.Width(55));
int sceneSelectedNew = EditorGUILayout.Popup(sceneSelected, m_SceneName, GUILayout.Width(size.x + 5f),
GUILayout.MinWidth(55));
GUILayout.FlexibleSpace();
// 结束水平布局
//EditorGUILayout.EndHorizontal();
if (sceneSelectedNew != sceneSelected)
{
sceneSelected = sceneSelectedNew;
SceneSwitcher.PromptSaveCurrentScene();
EditorSceneManager.OpenScene(m_ScenePath[sceneSelectedNew]);
}
}
}
static class SceneSwitcher
{
public static bool PromptSaveCurrentScene()
{
// 检查当前场景是否已保存
if (SceneManager.GetActiveScene().isDirty)
{
// 提示用户是否要保存当前场景
bool saveScene = EditorUtility.DisplayDialog(
"Save Current Scene",
"The current scene has unsaved changes. Do you want to save it?",
"Save",
"Cancel"
);
// 如果用户选择“保存”,则保存当前场景
if (saveScene)
{
EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
}
return saveScene;
}
// 如果场景已保存或者用户选择了“取消”,则返回 true表示继续执行后续操作
return true;
}
/// <summary>
/// 获取项目中所有的场景文件,并以 (场景名, 场景路径) 的形式返回。
/// </summary>
public static List<(string sceneName, string scenePath)> GetAllScenesInProject()
{
List<(string sceneName, string scenePath)> scenes = new List<(string sceneName, string scenePath)>();
// 查找所有场景文件
string[] guids = AssetDatabase.FindAssets("t:Scene");
for (int i = 0; i < guids.Length; i++)
{
var guid = guids[i];
string path = AssetDatabase.GUIDToAssetPath(guid);
string sceneName = $"{i + 1}_{Path.GetFileNameWithoutExtension(path)}";
scenes.Add((sceneName, path));
}
return scenes;
}
}
}
#endif

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 075130c21aee41b49b3977adc2bfa288
guid: 443dd03b960c78d449f988aa5f00322a
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -4,10 +4,9 @@ using UnityEngine;
using UnityEngine.SceneManagement;
using UnityToolbarExtender;
namespace TEngine.SceneLauncher
namespace TEngine
{
[InitializeOnLoad]
public class SceneSwitchLeftButton
public partial class UnityToolbarExtenderLeft
{
private const string PreviousSceneKey = "TEngine_PreviousScenePath"; // 用于存储之前场景路径的键
private const string IsLauncherBtn = "TEngine_IsLauncher"; // 用于存储之前是否按下launcher
@@ -17,14 +16,7 @@ namespace TEngine.SceneLauncher
private static readonly string ButtonStyleName = "Tab middle";
private static GUIStyle _buttonGuiStyle;
static SceneSwitchLeftButton()
{
ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
EditorApplication.quitting += OnEditorQuit;
}
private static void OnToolbarGUI()
private static void OnToolbarGUI_SceneLauncher()
{
_buttonGuiStyle ??= new GUIStyle(ButtonStyleName)
{

View File

@@ -0,0 +1,16 @@
using UnityEditor;
using UnityToolbarExtender;
namespace TEngine
{
[InitializeOnLoad]
public partial class UnityToolbarExtenderLeft
{
static UnityToolbarExtenderLeft()
{
ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI_SceneLauncher);
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
EditorApplication.quitting += OnEditorQuit;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c4485948c7a944af943177214f7f5033
timeCreated: 1748228552

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 20dbf6614352aaf488de29690deeab68
guid: a225fc80e4bc4e24caa14cb50ce08109
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,79 @@
using UnityEditor;
using UnityEngine;
using UnityToolbarExtender;
namespace TEngine
{
/// <summary>
/// EditorPlayMode 控件(资源模式选择器)
/// </summary>
public partial class UnityToolbarExtenderRight
{
private const string BUTTON_STYLE_NAME = "Tab middle";
private static readonly string[] _resourceModeNames =
{
"EditorMode (编辑器下的模拟模式)",
"OfflinePlayMode (单机模式)",
"HostPlayMode (联机运行模式)",
"WebPlayMode (WebGL运行模式)"
};
private static int _resourceModeIndex = 0;
public static int ResourceModeIndex => _resourceModeIndex;
static class ToolbarStyles
{
public static readonly GUIStyle PopupStyle;
static ToolbarStyles()
{
PopupStyle = new GUIStyle(EditorStyles.popup)
{
//fontSize = 11,
alignment = TextAnchor.MiddleLeft,
padding = new RectOffset(6, 6, 0, 0)
};
}
}
static void OnToolbarGUI_EditorPlayMode()
{
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
GUILayout.Space(8);
// 自动计算最长文本宽度
float maxWidth = 0;
foreach (string mode in _resourceModeNames)
{
Vector2 size = ToolbarStyles.PopupStyle.CalcSize(new GUIContent(mode));
if (size.x > maxWidth)
maxWidth = size.x;
}
// 加点缓冲宽度最多不超过220像素
float popupWidth = Mathf.Clamp(maxWidth + 20, 100, 220);
GUILayout.BeginHorizontal();
//GUILayout.Label("资源模式:", GUILayout.Width(65));
int selectedIndex = EditorGUILayout.Popup(
_resourceModeIndex,
_resourceModeNames,
ToolbarStyles.PopupStyle,
GUILayout.Width(popupWidth)
);
if (selectedIndex != _resourceModeIndex)
{
Debug.Log($"更改编辑器资源运行模式:{_resourceModeNames[selectedIndex]}");
_resourceModeIndex = selectedIndex;
EditorPrefs.SetInt("EditorPlayMode", selectedIndex);
}
GUILayout.EndHorizontal();
}
EditorGUI.EndDisabledGroup();
}
}
}

View File

@@ -0,0 +1,170 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
namespace TEngine
{
/// <summary>
/// SceneSwitcher
/// </summary>
public partial class UnityToolbarExtenderRight
{
private static List<(string sceneName, string scenePath)> m_InitScenes;
private static List<(string sceneName, string scenePath)> m_DefaultScenes;
private static List<(string sceneName, string scenePath)> m_OtherScenes;
private static string initScenePath = "Assets/Scenes";
private static string defaultScenePath = "Assets/AssetRaw/Scenes";
static void UpdateScenes()
{
// 获取初始化场景和默认场景
m_InitScenes = SceneSwitcher.GetScenesInPath(initScenePath);
m_DefaultScenes = SceneSwitcher.GetScenesInPath(defaultScenePath);
// 获取所有场景路径
List<(string sceneName, string scenePath)> allScenes = SceneSwitcher.GetAllScenes();
// 排除初始化场景和默认场景,获得其他场景
m_OtherScenes = new List<(string sceneName, string scenePath)>(allScenes);
m_OtherScenes.RemoveAll(scene =>
m_InitScenes.Exists(init => init.scenePath == scene.scenePath) ||
m_DefaultScenes.Exists(defaultScene => defaultScene.scenePath == scene.scenePath)
);
}
static void OnToolbarGUI_SceneSwitch()
{
// 如果没有场景,直接返回
if (m_InitScenes.Count == 0 && m_DefaultScenes.Count == 0 && m_OtherScenes.Count == 0)
return;
// 获取当前场景名称
string currentSceneName = SceneManager.GetActiveScene().name;
EditorGUILayout.LabelField("当前场景:", GUILayout.Width(52));
// 使用 GUI.skin.button.CalcSize 计算文本的精确宽度
GUIContent content = new GUIContent(currentSceneName);
Vector2 textSize = GUI.skin.button.CalcSize(content);
// 设置按钮宽度为文本的宽度,并限制最大值
float buttonWidth = textSize.x;
// 创建弹出菜单
var menu = new GenericMenu();
// 添加 "初始化路径" 下的场景按钮
AddScenesToMenu(m_InitScenes, "初始化场景", menu);
// 添加 "默认路径" 下的场景按钮
AddScenesToMenu(m_DefaultScenes, "默认场景", menu);
// 添加 "其他路径" 下的场景按钮
AddScenesToMenu(m_OtherScenes, "其他场景", menu);
// 自定义GUIStyle
GUIStyle buttonStyle = new GUIStyle(GUI.skin.button)
{
alignment = TextAnchor.MiddleLeft // 左对齐
};
// 在工具栏中显示菜单
if (GUILayout.Button(currentSceneName, buttonStyle, GUILayout.Width(buttonWidth)))
{
menu.ShowAsContext();
}
}
private static void AddScenesToMenu(List<(string sceneName, string scenePath)> scenes, string category, GenericMenu menu)
{
if (scenes.Count > 0)
{
foreach (var scene in scenes)
{
menu.AddItem(new GUIContent($"{category}/{scene.sceneName}"), false, () => SwitchScene(scene.scenePath));
}
}
}
static void SwitchScene(string scenePath)
{
// 保证场景是否保存
if (SceneSwitcher.PromptSaveCurrentScene())
{
// 保存场景后切换到新场景
EditorSceneManager.OpenScene(scenePath);
}
}
}
static class SceneSwitcher
{
public static bool PromptSaveCurrentScene()
{
// 检查当前场景是否有未保存的更改
if (SceneManager.GetActiveScene().isDirty)
{
// 弹出保存对话框
bool saveScene = EditorUtility.DisplayDialog(
"是否保存当前场景",
"当前场景有未保存的更改. 你是否想保存?",
"保存",
"取消"
);
// 如果选择保存,保存场景
if (saveScene)
{
EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
}
else
{
// 如果选择取消,跳转到目标场景
return false; // 表示取消
}
return true;
}
return true; // 如果场景没有更改,直接返回 true
}
public static List<(string sceneName, string scenePath)> GetScenesInPath(string path)
{
var scenes = new List<(string sceneName, string scenePath)>();
// 查找指定路径下的所有场景文件
string[] guids = AssetDatabase.FindAssets("t:Scene", new[] { path });
foreach (var guid in guids)
{
var scenePath = AssetDatabase.GUIDToAssetPath(guid);
var sceneName = Path.GetFileNameWithoutExtension(scenePath);
scenes.Add((sceneName, scenePath));
}
return scenes;
}
// 获取项目中所有场景
public static List<(string sceneName, string scenePath)> GetAllScenes()
{
var allScenes = new List<(string sceneName, string scenePath)>();
// 查找项目中所有场景文件
string[] guids = AssetDatabase.FindAssets("t:Scene");
foreach (var guid in guids)
{
var scenePath = AssetDatabase.GUIDToAssetPath(guid);
var sceneName = Path.GetFileNameWithoutExtension(scenePath);
allScenes.Add((sceneName, scenePath));
}
return allScenes;
}
}
}
#endif

View File

@@ -0,0 +1,21 @@
using UnityEditor;
using UnityToolbarExtender;
namespace TEngine
{
[InitializeOnLoad]
public partial class UnityToolbarExtenderRight
{
static UnityToolbarExtenderRight()
{
// 添加自定义按钮到右上工具栏
ToolbarExtender.RightToolbarGUI.Add(OnToolbarGUI_SceneSwitch);
// 订阅项目变化事件
EditorApplication.projectChanged += UpdateScenes;
UpdateScenes();
ToolbarExtender.RightToolbarGUI.Add(OnToolbarGUI_EditorPlayMode);
_resourceModeIndex = EditorPrefs.GetInt("EditorPlayMode", 0);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6240714bc0004010a4d6ca42a4f4305e
timeCreated: 1748227857