Unity辅助工具_头部与svn
Unity调用者按钮增加PlaySideButton
using QQu;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class PlaySideButton
{
static PlaySideButton()
{
UnityEditorToolbar.RightToolbarGUI.Add(OnRightToolbarGUI);
UnityEditorToolbar.LeftToolbarGUI.Add(OnLeftToolbarGUI);
}
private static bool mIsOpenPreview = false;
private static void OnRightToolbarGUI()
{
if (GUILayout.Button("GM | 格子坐标 | 格子使用", GUILayout.MaxWidth(150), GUILayout.Height(21)))
{
if (Event.current.button == 0)
{
AudioController.GetInstance().PlayClickSound();
UIMgr.Ins.Show<QQu.UI.GMView>().Task();
}
else if (Event.current.button == 2)
{
BuildingGridTileMgr.Ins.SetTestShowCell();
}
else if (Event.current.button == 1)
{
if(mIsOpenPreview==false)
SceneMapManager.Ins.PreviewCell(PreviewCellTypeEnum.CanBuilding);
else
SceneMapManager.Ins.ClosePreviewCell();
mIsOpenPreview = !mIsOpenPreview;
}
}
}
private static void OnLeftToolbarGUI()
{
GUILayout.FlexibleSpace(); //从右开始排
if (GUILayout.Button("更新 | 日志 | 提交", GUILayout.MaxWidth(110), GUILayout.Height(21)))
{
if (Application.isPlaying)
{
Debug.LogError("你游戏正在运行中");
return;
}
string[] strCMD = { "update", "commit", "log" }; //更新 查看日志 提交
string path = Application.dataPath.Replace("Assets", "");
SVNHelper.StartSvnProc(strCMD[Event.current.button], path);
}
}
}
unity头部扩展基类ToolbarCallback
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
#if UNITY_2019_1_OR_NEWER
using UnityEngine.UIElements;
#else
using UnityEngine.Experimental.UIElements;
#endif
//https://github.com/marijnz/unity-toolbar-extender
public static class ToolbarCallback
{
static Type m_toolbarType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.Toolbar");
static Type m_guiViewType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.GUIView");
#if UNITY_2020_1_OR_NEWER
static Type m_iWindowBackendType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.IWindowBackend");
static PropertyInfo m_windowBackend = m_guiViewType.GetProperty("windowBackend",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
static PropertyInfo m_viewVisualTree = m_iWindowBackendType.GetProperty("visualTree",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#else
static PropertyInfo m_viewVisualTree = m_guiViewType.GetProperty("visualTree",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#endif
static FieldInfo m_imguiContainerOnGui = typeof(IMGUIContainer).GetField("m_OnGUIHandler",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
static ScriptableObject m_currentToolbar;
/// <summary>
/// Callback for toolbar OnGUI method.
/// </summary>
public static Action OnToolbarGUI;
public static Action OnToolbarGUILeft;
public static Action OnToolbarGUIRight;
static ToolbarCallback()
{
EditorApplication.update -= OnUpdate;
EditorApplication.update += OnUpdate;
}
static void OnUpdate()
{
// Relying on the fact that toolbar is ScriptableObject and gets deleted when layout changes
if (m_currentToolbar == null)
{
// Find toolbar
var toolbars = Resources.FindObjectsOfTypeAll(m_toolbarType);
m_currentToolbar = toolbars.Length > 0 ? (ScriptableObject)toolbars[0] : null;
if (m_currentToolbar != null)
{
#if UNITY_2021_1_OR_NEWER
var root = m_currentToolbar.GetType().GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance);
var rawRoot = root.GetValue(m_currentToolbar);
var mRoot = rawRoot as VisualElement;
RegisterCallback("ToolbarZoneLeftAlign", OnToolbarGUILeft);
RegisterCallback("ToolbarZoneRightAlign", OnToolbarGUIRight);
void RegisterCallback(string root, Action cb)
{
var toolbarZone = mRoot.Q(root);
var parent = new VisualElement()
{
style = {
flexGrow = 1,
flexDirection = FlexDirection.Row,
}
};
var container = new IMGUIContainer();
container.style.flexGrow = 1;
container.onGUIHandler += () =>
{
cb?.Invoke();
};
parent.Add(container);
toolbarZone.Add(parent);
}
#else
#if UNITY_2020_1_OR_NEWER
var windowBackend = m_windowBackend.GetValue(m_currentToolbar);
// Get it's visual tree
var visualTree = (VisualElement) m_viewVisualTree.GetValue(windowBackend, null);
#else
// Get it's visual tree
var visualTree = (VisualElement)m_viewVisualTree.GetValue(m_currentToolbar, null);
#endif
// Get first child which 'happens' to be toolbar IMGUIContainer
var container = (IMGUIContainer)visualTree[0];
// (Re)attach handler
var handler = (Action)m_imguiContainerOnGui.GetValue(container);
handler -= OnGUI;
handler += OnGUI;
m_imguiContainerOnGui.SetValue(container, handler);
#endif
}
}
}
static void OnGUI()
{
var handler = OnToolbarGUI;
if (handler != null) handler();
}
}
[InitializeOnLoad]
public static class UnityEditorToolbar
{
static int m_toolCount;
static GUIStyle m_commandStyle = null;
public static readonly List<Action> LeftToolbarGUI = new List<Action>();
public static readonly List<Action> RightToolbarGUI = new List<Action>();
static UnityEditorToolbar()
{
Type toolbarType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.Toolbar");
#if UNITY_2019_1_OR_NEWER
string fieldName = "k_ToolCount";
#else
string fieldName = "s_ShownToolIcons";
#endif
FieldInfo toolIcons = toolbarType.GetField(fieldName,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
#if UNITY_2019_3_OR_NEWER
m_toolCount = toolIcons != null ? ((int)toolIcons.GetValue(null)) : 8;
#elif UNITY_2019_1_OR_NEWER
m_toolCount = toolIcons != null ? ((int) toolIcons.GetValue(null)) : 7;
#elif UNITY_2018_1_OR_NEWER
m_toolCount = toolIcons != null ? ((Array) toolIcons.GetValue(null)).Length : 6;
#else
m_toolCount = toolIcons != null ? ((Array) toolIcons.GetValue(null)).Length : 5;
#endif
ToolbarCallback.OnToolbarGUI = OnGUI;
ToolbarCallback.OnToolbarGUILeft = GUILeft;
ToolbarCallback.OnToolbarGUIRight = GUIRight;
}
#if UNITY_2019_3_OR_NEWER
public const float space = 8;
#else
public const float space = 10;
#endif
public const float largeSpace = 20;
public const float buttonWidth = 32;
public const float dropdownWidth = 80;
#if UNITY_2019_1_OR_NEWER
public const float playPauseStopWidth = 140;
#else
public const float playPauseStopWidth = 100;
#endif
static void OnGUI()
{
// Create two containers, left and right
// Screen is whole toolbar
if (m_commandStyle == null)
{
m_commandStyle = new GUIStyle("CommandLeft");
}
var screenWidth = EditorGUIUtility.currentViewWidth;
// Following calculations match code reflected from Toolbar.OldOnGUI()
float playButtonsPosition = Mathf.RoundToInt((screenWidth - playPauseStopWidth) / 2);
Rect leftRect = new Rect(0, 0, screenWidth, Screen.height);
leftRect.xMin += space; // Spacing left
leftRect.xMin += buttonWidth * m_toolCount; // Tool buttons
#if UNITY_2019_3_OR_NEWER
leftRect.xMin += space; // Spacing between tools and pivot
#else
leftRect.xMin += largeSpace; // Spacing between tools and pivot
#endif
leftRect.xMin += 64 * 2; // Pivot buttons
leftRect.xMax = playButtonsPosition;
Rect rightRect = new Rect(0, 0, screenWidth, Screen.height);
rightRect.xMin = playButtonsPosition;
rightRect.xMin += m_commandStyle.fixedWidth * 3; // Play buttons
rightRect.xMax = screenWidth;
rightRect.xMax -= space; // Spacing right
rightRect.xMax -= dropdownWidth; // Layout
rightRect.xMax -= space; // Spacing between layout and layers
rightRect.xMax -= dropdownWidth; // Layers
#if UNITY_2019_3_OR_NEWER
rightRect.xMax -= space; // Spacing between layers and account
#else
rightRect.xMax -= largeSpace; // Spacing between layers and account
#endif
rightRect.xMax -= dropdownWidth; // Account
rightRect.xMax -= space; // Spacing between account and cloud
rightRect.xMax -= buttonWidth; // Cloud
rightRect.xMax -= space; // Spacing between cloud and collab
rightRect.xMax -= 78; // Colab
// Add spacing around existing controls
leftRect.xMin += space;
leftRect.xMax -= space;
rightRect.xMin += space;
rightRect.xMax -= space;
// Add top and bottom margins
#if UNITY_2019_3_OR_NEWER
leftRect.y = 4;
leftRect.height = 22;
rightRect.y = 4;
rightRect.height = 22;
#else
leftRect.y = 5;
leftRect.height = 24;
rightRect.y = 5;
rightRect.height = 24;
#endif
if (leftRect.width > 0)
{
GUILayout.BeginArea(leftRect);
GUILayout.BeginHorizontal();
foreach (var handler in LeftToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
if (rightRect.width > 0)
{
GUILayout.BeginArea(rightRect);
GUILayout.BeginHorizontal();
foreach (var handler in RightToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
}
public static void GUILeft()
{
GUILayout.BeginHorizontal();
foreach (var handler in LeftToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
}
public static void GUIRight()
{
GUILayout.BeginHorizontal();
foreach (var handler in RightToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
}
}
svn工具辅助类 SVNHelper
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using UnityEditor;
using UnityEngine;
public static class SVNHelper
{
//Log
[MenuItem("Assets/SVN/日志",false,1)]
private static void RightClickLog()
{
var path = MySelectActiveObj();
if (string.IsNullOrEmpty(path) == false)
{
StartSvnProc("log", path);
}
}
//更新
[MenuItem("Assets/SVN/更新", false, 1)]
private static void RightClickUpdate()
{
var path = MySelectActiveObj();
if (string.IsNullOrEmpty(path) == false)
{
StartSvnProc("update", path);
}
}
//提交
[MenuItem("Assets/SVN/提交", false, 1)]
private static void RightClickCommit()
{
var path= MySelectActiveObj();
if (string.IsNullOrEmpty(path)==false)
{
StartSvnProc("commit", path);
}
}
// 获取选中的对象
private static string MySelectActiveObj()
{
var selectedObjects = Selection.objects;
if (selectedObjects.Length > 0)
{
foreach (var obj in selectedObjects)
{
// 检查选定对象是否是文件夹
string path = AssetDatabase.GetAssetPath(obj);
if (AssetDatabase.IsValidFolder(path))
{
string target = Application.dataPath.Replace("Assets", "")+path;
return target;
}
}
}
return null;
}
public static int StartSvnProc(string cmd, string path, string url = "", bool closeOnEnd = false,
string logMsg = "")
{
ProcessStartInfo startInfo = new ProcessStartInfo();
#if UNITY_EDITOR_WIN
var tortoiseProcPath = GetTortoiseProcSvnPath();
if (string.IsNullOrEmpty(tortoiseProcPath))
{
UnityEngine.Debug.LogError("TortoiseProc未找到");
return 0;
}
startInfo.FileName = tortoiseProcPath;
if (cmd.Equals("commit") && !string.IsNullOrEmpty(logMsg))
{
if (string.IsNullOrEmpty(url))
startInfo.Arguments =
$"/command:{cmd} /path:\"{path}\" /logmsg:{logMsg} /closeonend:{(closeOnEnd ? 2 : 0)}";
else
startInfo.Arguments =
$"/command:{cmd} /path:\"{path}\" /url:\"{url}\" /logmsg:{logMsg} /closeonend:{(closeOnEnd ? 2 : 0)}";
}
else
{
if (string.IsNullOrEmpty(url))
startInfo.Arguments = $"/command:{cmd} /path:\"{path}\" /closeonend:{(closeOnEnd ? 2 : 0)}";
else
startInfo.Arguments =
$"/command:{cmd} /path:\"{path}\" /url:\"{url}\" /closeonend:{(closeOnEnd ? 2 : 0)}";
}
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
#elif UNITY_EDITOR_OSX
startInfo.CreateNoWindow = true;
startInfo.ErrorDialog = true;
startInfo.UseShellExecute = false;
startInfo.FileName = "/usr/local/bin/svn";
startInfo.Arguments = $"{cmd} {url} {path}";
startInfo.RedirectStandardOutput = true;
UnityEngine.Debug.Log("start process = " + startInfo.Arguments);
#endif
Process svnUpProcess = new Process();
svnUpProcess.StartInfo = startInfo;
svnUpProcess.Start();
svnUpProcess.WaitForExit();
string output = svnUpProcess.StandardOutput.ReadToEnd();
UnityEngine.Debug.Log("process output = " + output);
var exitCode = svnUpProcess.ExitCode;
svnUpProcess.Close();
AssetDatabase.Refresh();
return exitCode;
}
private static string GetTortoiseProcSvnPath()
{
try
{
RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
var path = key.OpenSubKey("SOFTWARE").OpenSubKey("TortoiseSVN").GetValue("ProcPath").ToString();
return path;
}
catch (Exception)
{
string[] vols = { "C", "D", "E", "F", "G", "H" };
string[] dirs =
{
@"Program Files",
@"Program Files (x86)",
};
foreach (var vol in vols)
foreach (var dir in dirs)
{
string file = $"{vol}:\\{dir}\\TortoiseSVN\\bin\\TortoiseProc.exe";
if (File.Exists(file))
return file;
}
return null;
}
}
}
git工具辅助类 GitHelper
using Microsoft.Win32;
using System;
using System.Diagnostics;
using UnityEditor;
public class GitHelper
{
public static bool StartGitProc(string cmd, string path, string outPath = "")
{
string gitProcPath = GetTortoiseGitProcPath();
if (string.IsNullOrEmpty(gitProcPath))
{
UnityEngine.Debug.LogError("TortoiseGitProc未找到");
return false;
}
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = gitProcPath;
startInfo.Arguments = $"/command:{cmd} /path:\"{path}\"/closeonend:2";
Process gitProcess = new Process();
gitProcess.StartInfo = startInfo;
gitProcess.Start();
gitProcess.WaitForExit();
if (gitProcess.ExitCode > 0)
{
EditorUtility.DisplayDialog("提示", $"git {cmd} exit with code:{gitProcess.ExitCode}", "确定");
return false;
}
return true;
}
public static string GetTortoiseGitProcPath()
{
try
{
RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
var path = key.OpenSubKey("SOFTWARE").OpenSubKey("TortoiseGit").GetValue("ProcPath").ToString();
return path;
}
catch (Exception)
{
return null;
}
}
}