首次提交

This commit is contained in:
Bob.Song
2026-03-05 18:07:55 +08:00
commit e125bb869e
4534 changed files with 563920 additions and 0 deletions

View File

@@ -0,0 +1,267 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor.Animations;
public class AnimatorParameterDetailAnalyzer : EditorWindow
{
private AnimatorController selectedController;
private Dictionary<string, ParameterUsageData> parameterUsageData = new Dictionary<string, ParameterUsageData>();
private Vector2 scrollPosition;
private string analysisResult = "";
private bool showRawData = false;
private string targetLayerName = "";
[MenuItem("Tools/Animator Parameter Detail Analyzer")]
public static void ShowWindow()
{
GetWindow<AnimatorParameterDetailAnalyzer>("Animator Parameter Detail Analyzer");
}
private void OnGUI()
{
GUILayout.Label("Animator Parameter Detail Analyzer", EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
selectedController = (AnimatorController)EditorGUILayout.ObjectField("Animator Controller", selectedController, typeof(AnimatorController), false);
if (EditorGUI.EndChangeCheck())
{
AnalyzeController();
}
targetLayerName = EditorGUILayout.TextField("Target Layer Name (Empty for all)", targetLayerName);
if (GUILayout.Button("Analyze Selected Controller"))
{
AnalyzeController();
}
showRawData = EditorGUILayout.Toggle("Show Raw Data", showRawData);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
EditorGUILayout.TextArea(analysisResult, GUILayout.ExpandHeight(true));
EditorGUILayout.EndScrollView();
}
private void AnalyzeController()
{
parameterUsageData.Clear();
analysisResult = "";
if (selectedController == null)
{
Debug.LogWarning("No Animator Controller selected.");
return;
}
StringBuilder sb = new StringBuilder();
sb.AppendLine($"=== Animator Controller Analysis: {selectedController.name} ===");
if (string.IsNullOrEmpty(targetLayerName))
{
sb.AppendLine("Analyzing ALL layers");
}
else
{
sb.AppendLine($"Analyzing layer: {targetLayerName}");
}
sb.AppendLine();
foreach (var param in selectedController.parameters)
{
parameterUsageData[param.name] = new ParameterUsageData(param);
}
foreach (var layer in selectedController.layers)
{
if (string.IsNullOrEmpty(targetLayerName) || layer.name == targetLayerName)
{
AnalyzeStateMachine(layer.stateMachine, layer.name);
}
}
foreach (var paramData in parameterUsageData.Values.OrderBy(d => d.parameter.name))
{
AppendParameterReport(sb, paramData);
}
if (showRawData)
{
sb.AppendLine();
sb.AppendLine("=== Raw Transition Data ===");
foreach (var layer in selectedController.layers)
{
if (string.IsNullOrEmpty(targetLayerName) || layer.name == targetLayerName)
{
AppendRawTransitionData(sb, layer.stateMachine, layer.name);
}
}
}
analysisResult = sb.ToString();
}
private void AppendParameterReport(StringBuilder sb, ParameterUsageData paramData)
{
var param = paramData.parameter;
sb.AppendLine($"Parameter: {param.name} ({param.type})");
sb.Append(" Possible Values: ");
switch (param.type)
{
case AnimatorControllerParameterType.Int:
sb.AppendLine(string.Join(", ", paramData.possibleIntValues.OrderBy(v => v).Select(v => v.ToString())));
break;
case AnimatorControllerParameterType.Float:
sb.AppendLine(string.Join(", ", paramData.possibleFloatValues.OrderBy(v => v).Select(v => v.ToString("F2"))));
break;
case AnimatorControllerParameterType.Bool:
sb.AppendLine(string.Join(", ", paramData.possibleBoolValues.Select(v => v.ToString())));
break;
case AnimatorControllerParameterType.Trigger:
sb.AppendLine("Trigger (used in conditions)");
break;
}
if (paramData.transitionUsages.Count > 0)
{
sb.AppendLine(" Used in Transitions:");
foreach (var usage in paramData.transitionUsages)
{
sb.AppendLine($" {usage.fromState} -> {usage.toState} (Layer: {usage.layerName})");
sb.AppendLine($" Condition: {param.name} {GetConditionSymbol(usage.condition.mode)} {usage.condition.threshold}");
}
}
else
{
sb.AppendLine(" Not used in any transitions (may be used in scripts)");
}
sb.AppendLine();
}
private string GetConditionSymbol(AnimatorConditionMode mode)
{
switch (mode)
{
case AnimatorConditionMode.If: return "==";
case AnimatorConditionMode.IfNot: return "!=";
case AnimatorConditionMode.Greater: return ">";
case AnimatorConditionMode.Less: return "<";
case AnimatorConditionMode.Equals: return "==";
case AnimatorConditionMode.NotEqual: return "!=";
default: return "?";
}
}
private void AnalyzeStateMachine(AnimatorStateMachine stateMachine, string layerName)
{
foreach (var childState in stateMachine.states)
{
AnalyzeState(childState.state, layerName);
}
foreach (var childStateMachine in stateMachine.stateMachines)
{
AnalyzeStateMachine(childStateMachine.stateMachine, layerName);
}
}
private void AnalyzeState(AnimatorState state, string layerName)
{
foreach (var transition in state.transitions)
{
AnalyzeTransition(transition, state.name, layerName);
}
}
private void AnalyzeTransition(AnimatorStateTransition transition, string fromStateName, string layerName)
{
foreach (var condition in transition.conditions)
{
if (!parameterUsageData.ContainsKey(condition.parameter))
continue;
var paramData = parameterUsageData[condition.parameter];
var usage = new TransitionUsage
{
layerName = layerName,
fromState = fromStateName,
toState = transition.destinationState?.name ?? "Exit",
condition = condition
};
paramData.transitionUsages.Add(usage);
switch (paramData.parameter.type)
{
case AnimatorControllerParameterType.Int:
paramData.possibleIntValues.Add((int)condition.threshold);
break;
case AnimatorControllerParameterType.Float:
paramData.possibleFloatValues.Add(condition.threshold);
break;
case AnimatorControllerParameterType.Bool:
paramData.possibleBoolValues.Add(condition.threshold > 0.5f);
break;
}
}
}
private void AppendRawTransitionData(StringBuilder sb, AnimatorStateMachine stateMachine, string layerName)
{
foreach (var childState in stateMachine.states)
{
foreach (var transition in childState.state.transitions)
{
sb.AppendLine($"{layerName}: {childState.state.name} -> {transition.destinationState?.name ?? "Exit"}");
foreach (var condition in transition.conditions)
{
sb.AppendLine($" {condition.parameter} {condition.mode} {condition.threshold}");
}
}
}
foreach (var childStateMachine in stateMachine.stateMachines)
{
AppendRawTransitionData(sb, childStateMachine.stateMachine, layerName);
}
}
private class ParameterUsageData
{
public AnimatorControllerParameter parameter;
public HashSet<int> possibleIntValues = new HashSet<int>();
public HashSet<float> possibleFloatValues = new HashSet<float>();
public HashSet<bool> possibleBoolValues = new HashSet<bool>();
public List<TransitionUsage> transitionUsages = new List<TransitionUsage>();
public ParameterUsageData(AnimatorControllerParameter param)
{
parameter = param;
switch (param.type)
{
case AnimatorControllerParameterType.Int:
possibleIntValues.Add(param.defaultInt);
break;
case AnimatorControllerParameterType.Float:
possibleFloatValues.Add(param.defaultFloat);
break;
case AnimatorControllerParameterType.Bool:
possibleBoolValues.Add(param.defaultBool);
break;
}
}
}
private class TransitionUsage
{
public string layerName;
public string fromState;
public string toState;
public AnimatorCondition condition;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d8f6792dcd794f6792af088b51bc6fbc
timeCreated: 1743518603

View File

@@ -0,0 +1,107 @@
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
public class AnimatorParametersGenerator : Editor
{
[MenuItem("Tools/Generate Animator Parameters with Properties")]
public static void GenerateAnimatorParametersWithProperties()
{
// 获取选中的Animator Controller
var controller = Selection.activeObject as AnimatorController;
if (controller == null)
{
Debug.LogError("请选择一个Animator Controller文件");
return;
}
// 用于存储生成的代码
string className = controller.name + "Parameters";
string code = $"// Auto-generated class for {controller.name} parameters\n";
code += "using UnityEngine;\n\n";
code += "public class " + className + "\n{\n";
code += " private Animator _animator;\n\n";
code += $" public {className}(Animator animator)\n";
code += " {\n";
code += " _animator = animator;\n";
code += " }\n\n";
foreach (var parameter in controller.parameters)
{
string paramName = parameter.name;
string sanitizedName = SanitizeName(paramName); // 变量名合法化
string typeName = GetTypeName(parameter.type); // 获取类型名称
switch (parameter.type)
{
case AnimatorControllerParameterType.Bool:
code += $" public bool {sanitizedName}\n";
code += " {\n";
code += $" get => _animator.GetBool(\"{paramName}\");\n";
code += $" set => _animator.SetBool(\"{paramName}\", value);\n";
code += " }\n\n";
break;
case AnimatorControllerParameterType.Int:
code += $" public int {sanitizedName}\n";
code += " {\n";
code += $" get => _animator.GetInteger(\"{paramName}\");\n";
code += $" set => _animator.SetInteger(\"{paramName}\", value);\n";
code += " }\n\n";
break;
case AnimatorControllerParameterType.Float:
code += $" public float {sanitizedName}\n";
code += " {\n";
code += $" get => _animator.GetFloat(\"{paramName}\");\n";
code += $" set => _animator.SetFloat(\"{paramName}\", value);\n";
code += " }\n\n";
break;
case AnimatorControllerParameterType.Trigger:
code += $" public void Set{sanitizedName}Trigger()\n";
code += " {\n";
code += $" _animator.SetTrigger(\"{paramName}\");\n";
code += " }\n\n";
code += $" public void Reset{sanitizedName}Trigger()\n";
code += " {\n";
code += $" _animator.ResetTrigger(\"{paramName}\");\n";
code += " }\n\n";
break;
}
}
code += "}\n";
// 输出到控制台
Debug.Log(code);
// 可选:将代码写入到指定文件
string path = EditorUtility.SaveFilePanel("保存参数类", "Assets", className, "cs");
if (!string.IsNullOrEmpty(path))
{
System.IO.File.WriteAllText(path, code);
AssetDatabase.Refresh();
Debug.Log("生成的参数类已保存到:" + path);
}
}
// 对参数名进行安全处理,避免非法字符
private static string SanitizeName(string name)
{
return name.Replace(" ", "_").Replace("-", "_");
}
// 根据Animator参数类型返回对应的C#类型名
private static string GetTypeName(AnimatorControllerParameterType type)
{
return type switch
{
AnimatorControllerParameterType.Bool => "bool",
AnimatorControllerParameterType.Int => "int",
AnimatorControllerParameterType.Float => "float",
AnimatorControllerParameterType.Trigger => "void",
_ => "unknown"
};
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c7f538499bd74a61b5b6396b843e79da
timeCreated: 1734175675

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bef91460c2ca4315a394b30f54d62838
timeCreated: 1735888145

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fbc716d15a94418194d49806f957e327
timeCreated: 1735888291

View File

@@ -0,0 +1,20 @@
using System;
namespace NBF
{
[AttributeUsage(AttributeTargets.Class)]
public class BuildTaskInfoAttribute : Attribute
{
public string Name;
public int Id;
public bool Visable;
public BuildTaskInfoAttribute(int id, string name, bool visable = true)
{
Id = id;
Name = name;
Visable = visable;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 41d2cb56d8994cc6ae893a33f19b3e76
timeCreated: 1735888293

View File

@@ -0,0 +1,10 @@
namespace NBF
{
public class BuildContext
{
/// <summary>
/// 版本号
/// </summary>
public string Ver;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9a97905bd3c747f9ba3c6d1df484568c
timeCreated: 1735888273

View File

@@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NBC.Asset.Editor;
using UnityEditor;
using Debug = UnityEngine.Debug;
namespace NBF
{
/// <summary>
/// 打包器
/// </summary>
public class Builder
{
/// <summary>
/// 任务id对应的类型
/// </summary>
private static readonly Dictionary<int, Type> _buildTaskTypes = new Dictionary<int, Type>();
/// <summary>
/// 任务配置信息
/// </summary>
public static readonly List<BuildTaskInfoAttribute> BuildTaskInfo = new List<BuildTaskInfoAttribute>();
[InitializeOnLoadMethod]
private static void OnInitialize()
{
FindTasks();
}
private static void FindTasks()
{
var types = EditUtil.FindAllSubclass<BaseBuildTask>();
foreach (var t in types)
{
var attributes = t.GetCustomAttributes(typeof(BuildTaskInfoAttribute), true);
foreach (var attribute in attributes)
{
if (attribute is BuildTaskInfoAttribute idAttribute && idAttribute.Id > 0)
{
_buildTaskTypes[idAttribute.Id] = t;
BuildTaskInfo.Add(idAttribute);
}
}
}
BuildTaskInfo.Sort((a, b) => a.Id - b.Id);
}
private static Type GetTaskType(int id)
{
return _buildTaskTypes.GetValueOrDefault(id);
}
#region
/// <summary>
/// 供cmd调用的打包接口
/// </summary>
/// <exception cref="Exception"></exception>
public static void RunBuild()
{
var ver = string.Empty;
var ding = 0;
List<int> ids = new List<int>();
List<string> systemValue = new List<string>(Environment.GetCommandLineArgs());
foreach (var str in systemValue)
{
var arr = str.Split("=");
if (arr.Length > 1)
{
var key = arr[0];
var value = arr[1];
if (key == "v")
{
ver = value;
}
else if (key == "ids")
{
var idArr = value.Split(',');
if (idArr.Length > 0)
{
foreach (var id in idArr)
{
if (int.TryParse(id, out var i) && i > 0)
{
ids.Add(i);
}
}
}
}
}
}
if (string.IsNullOrEmpty(ver) || ids.Count < 1)
{
throw new Exception("参数错误");
}
BuildContext buildContext = new BuildContext
{
Ver = ver
};
RunBuildTasks(buildContext, ids.ToArray());
}
public static void RunBuildTasks(BuildContext buildContext, params int[] ids)
{
Debug.Log("开始执行构建任务");
List<Type> types = ids.Select(GetTaskType).Where(type => type != null).ToList();
if (types.Count < 1)
{
throw new Exception("task id error!");
}
List<BaseBuildTask> buildTasks = new List<BaseBuildTask>();
foreach (var type in types)
{
if (Activator.CreateInstance(type) is BaseBuildTask task)
{
buildTasks.Add(task);
}
}
foreach (var task in buildTasks)
{
var sw = new Stopwatch();
sw.Start();
task.Run(buildContext);
sw.Stop();
Debug.Log($"Run 任务={task.GetType().Name} time={sw.ElapsedMilliseconds / 1000f}s");
}
}
#endregion
public static BuildTargetGroup GetTargetGroup()
{
BuildTarget activeTarget = EditorUserBuildSettings.activeBuildTarget;
var targetGroup = BuildTargetGroup.Unknown;
if (activeTarget == BuildTarget.StandaloneWindows || activeTarget == BuildTarget.StandaloneWindows64)
{
targetGroup = BuildTargetGroup.Standalone;
}
else if (activeTarget == BuildTarget.Android)
{
targetGroup = BuildTargetGroup.Android;
}
else if (activeTarget == BuildTarget.iOS)
{
targetGroup = BuildTargetGroup.iOS;
}
return targetGroup;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a11d1aa017534b6195db306f958f5257
timeCreated: 1735888155

View File

@@ -0,0 +1,170 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace NBF
{
public class BuilderWindow : EditorWindow
{
public const int Width = 400;
public const int Height = 645;
[MenuItem("构建/打开构建面板", false, 9)]
public static void ShowWindow()
{
BuilderWindow wnd = GetWindow<BuilderWindow>("APP打包器", true);
wnd.minSize = new Vector2(Width, Height);
}
#region
private GUIStyle _styleTitleSmall;
private GUIStyle StyleTitleSmall
{
get
{
if (_styleTitleSmall == null)
{
_styleTitleSmall = new GUIStyle(EditorStyles.label)
{
fontStyle = FontStyle.Bold,
fontSize = 12
};
}
return _styleTitleSmall;
}
}
#endregion
private readonly HashSet<int> _selectTaskId = new HashSet<int>();
private string Ver;
protected void OnEnable()
{
Ver = PlayerSettings.bundleVersion;
_selectTaskId.Clear();
}
protected void OnGUI()
{
EditorGUILayout.Space();
DrawMenu();
ShowTitle($"环境选择");
Ver = EditorGUILayout.TextField("打包版本号", Ver);
ShowTitle("任务列表");
var tasks = Builder.BuildTaskInfo;
foreach (var task in tasks)
{
var select = _selectTaskId.Contains(task.Id);
GUI.color = select ? Color.white : Color.grey;
if (task.Visable)
{
//复选框
var s = EditorGUILayout.Toggle(task.Name, select, GUILayout.Height(20));
if (s)
{
_selectTaskId.Add(task.Id);
}
else
{
_selectTaskId.Remove(task.Id);
}
}
}
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
GUI.color = Color.white;
if (GUILayout.Button("执行打包", GUILayout.Height(45)))
{
Run();
}
}
private void Run(bool distributed = false, bool cloud = false)
{
var ids = _selectTaskId.ToArray();
if (!cloud)
{
BuildContext buildContext = new BuildContext
{
Ver = Ver,
};
Builder.RunBuildTasks(buildContext, ids);
}
else
{
Debug.LogError("远端构建暂未完成==");
}
}
private void DrawMenu()
{
ShowTitle("快速选中");
GUILayout.BeginHorizontal();
if (GUILayout.Button("提审包", GUILayout.Height(30)))
{
SelectAll();
}
if (GUILayout.Button("自测包", GUILayout.Height(30)))
{
SelectSelfTest();
}
if (GUILayout.Button("取消选择", GUILayout.Height(30)))
{
_selectTaskId.Clear();
}
EditorGUILayout.EndHorizontal();
}
#region
private void SelectAll()
{
_selectTaskId.Clear();
foreach (var task in Builder.BuildTaskInfo)
{
_selectTaskId.Add(task.Id);
}
}
private void SelectSelfTest()
{
_selectTaskId.Clear();
_selectTaskId.Add(BuildTaskId.Excel);
_selectTaskId.Add(BuildTaskId.AB);
_selectTaskId.Add(BuildTaskId.App);
_selectTaskId.Add(BuildTaskId.CopyShare);
}
#endregion
private void ShowTitle(string str)
{
EditorGUILayout.Space();
GUILayout.Label(str, StyleTitleSmall);
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
}
private bool HasSelectTask(int id)
{
return _selectTaskId.Contains(id);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 89fa3eb5ebcd4df692e9a2a19815ae8b
timeCreated: 1735890628

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 153e12cafc9f4d86bbde017079fa5bf5
timeCreated: 1735888397

View File

@@ -0,0 +1,13 @@
namespace NBF
{
public class BuildTaskId
{
public const int Excel = 1;
public const int AB = 2;
public const int App = 3;
public const int CopyShare = 4;
public const int DingTalkNotice = 5;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c621b4acadc844a6ae65dc15916355fc
timeCreated: 1735888399

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c5bff86240194f81882a09430e3e9523
timeCreated: 1735888252

View File

@@ -0,0 +1,7 @@
namespace NBF
{
public abstract class BaseBuildTask
{
public abstract void Run(BuildContext context);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2d1fa1e3836b449ea0f81c0fa1ca7246
timeCreated: 1735888255

View File

@@ -0,0 +1,42 @@
using System.IO;
using UnityEditor;
using UnityEngine;
namespace NBF
{
/// <summary>
/// 打包ab
/// </summary>
[BuildTaskInfo(BuildTaskId.AB, "打包AB")]
public class BuildABTask : BaseBuildTask
{
public override void Run(BuildContext context)
{
if (context.Ver != PlayerSettings.bundleVersion)
{
PlayerSettings.bundleVersion = context.Ver;
}
DeleteStreamingAssetsBundleCache();
NBC.Asset.Editor.Builder.Build();
// Builder.Build();
}
void DeleteStreamingAssetsBundleCache()
{
var mainFolder = Path.Combine(Application.streamingAssetsPath, "main").Replace("\\", "/");
if (Directory.Exists(mainFolder))
Directory.Delete(mainFolder, true);
string[] files = Directory.GetFiles(Application.streamingAssetsPath);
foreach (string file in files)
{
var filePath = file.Replace("\\", "/");
string fileName = Path.GetFileName(filePath);
if (fileName.Contains("packages_") || fileName.Contains("version"))
File.Delete(filePath);
}
AssetDatabase.Refresh();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2acde0d91b8b47ad8abdd6febd62232c
timeCreated: 1735888685

View File

@@ -0,0 +1,121 @@
using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace NBF
{
/// <summary>
/// 打包app
/// </summary>
[BuildTaskInfo(BuildTaskId.App, "打包App")]
public class BuildAppTask : BaseBuildTask
{
public static readonly string AppInfoPath = Application.dataPath + "/Scripts/Def/AppInfo.cs";
public static readonly string ProjectDir = Directory.GetParent(Application.dataPath)?.ToString();
private BuildContext _context;
public override void Run(BuildContext context)
{
_context = context;
ChangeAppInfo();
BuildAppByPath();
}
/// <summary>
/// 修改打包脚本信息
/// </summary>
private void ChangeAppInfo()
{
if (!File.Exists(AppInfoPath))
{
Debug.LogError("app info 脚本路径错误");
return;
}
EditorUserBuildSettings.exportAsGoogleAndroidProject = false;
if (_context.Ver != PlayerSettings.bundleVersion)
{
PlayerSettings.bundleVersion = _context.Ver;
}
var change = false;
var lines = File.ReadAllLines(AppInfoPath);
for (var i = 0; i < lines.Length; i++)
{
var str = lines[i];
if (str.Contains("string Code"))
{
if (!str.Contains(_context.Ver))
{
lines[i] = $"\t\tpublic const string Code = \"{_context.Ver}\";";
change = true;
}
}
}
if (change)
{
File.WriteAllLines(AppInfoPath, lines);
AssetDatabase.Refresh();
}
}
private void BuildAppByPath()
{
// 设置打包的输出路径
string outputPath = $"{ProjectDir}/Release";
string location =
$"{outputPath}/{_context.Ver}/Fishing.exe";
BuildTarget activeTarget = EditorUserBuildSettings.activeBuildTarget;
switch (activeTarget)
{
case BuildTarget.StandaloneWindows:
case BuildTarget.StandaloneWindows64:
case BuildTarget.Android:
case BuildTarget.iOS:
EditorSettings.spritePackerMode = SpritePackerMode.AlwaysOnAtlas;
PlayerSettings.gcIncremental = true;
break;
}
var targetGroup = Builder.GetTargetGroup();
if (targetGroup == BuildTargetGroup.Unknown)
{
Debug.LogError("不支持的平台");
return;
}
// 读取 Build Settings 中 “Scenes In Build” 勾选的场景
var scenes = EditorBuildSettings.scenes
.Where(s => s.enabled)
.Select(s => s.path)
.ToArray();
var buildOptions = BuildOptions.CompressWithLz4;
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
{
scenes = scenes, //new[] { "Assets/Scenes/StartUp.unity" }, //Assets/Scenes/StartUp.unity
locationPathName = location,
options = buildOptions,
target = activeTarget,
targetGroup = targetGroup,
};
var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
{
Debug.LogError("打包失败");
return;
}
#if UNITY_EDITOR
Application.OpenURL($"file:///{outputPath}");
#endif
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2039f10c99ae4fa18259e438203cc78c
timeCreated: 1735889001

View File

@@ -0,0 +1,14 @@
namespace NBF
{
/// <summary>
/// 导表
/// </summary>
[BuildTaskInfo(BuildTaskId.Excel, "导出Excel表")]
public class BuildExcelTask : BaseBuildTask
{
public override void Run(BuildContext context)
{
// ExcelToJsonWindow.GenConfig(false);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 241caaeb76c54700bc0da1f73179fcf4
timeCreated: 1735888813

View File

@@ -0,0 +1,109 @@
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace NBF
{
public static class EditorUtils
{
/// <summary>
/// 自动大小
/// </summary>
/// <param name="headerState"></param>
/// <param name="maxWidth">最大宽</param>
/// <param name="index">自由大小的序号</param>
public static void AutoWidth(this MultiColumnHeaderState headerState, float maxWidth, int index = 0)
{
var columns = headerState.columns;
if (columns == null) return;
var residue = maxWidth - 16;
for (int i = 0; i < columns.Length; i++)
{
var column = columns[i];
if (i != index)
{
residue -= column.width;
}
}
if (residue < 100) residue = 100;
columns[index].width = residue;
}
/// <summary>
/// 将一个文件夹复制到另一个文件夹,根据包含的字符串和是否排除参数过滤处理的文件
/// </summary>
/// <param name="sourceDir">源目录</param>
/// <param name="destDir">目标目录</param>
/// <param name="containStr">文件路径包含的字符串,用于过滤后缀名</param>
/// <param name="exclusion">是否排除包含字符串的路径</param>
public static void CopySourceDirToDestDir(string sourceDir, string destDir, string containStr = null,
bool exclusion = false)
{
IList<string> files = Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories);
if (!string.IsNullOrEmpty(containStr))
{
files = files.FindAll((f) =>
{
bool contain = f.Contains(containStr);
return exclusion ? !contain : contain;
});
}
foreach (string file in files)
{
string relativePath = file.Substring(sourceDir.Length + 1);
string destFilePath = Path.Combine(destDir, relativePath);
string destFileDir = Path.GetDirectoryName(destFilePath);
if (!Directory.Exists(destFileDir))
{
Directory.CreateDirectory(destFileDir);
}
File.Copy(file, destFilePath, true);
}
}
/// <summary>
/// 创建新的ScriptableObject资产文件
/// </summary>
public static void CreateAsset<T>(string fullPath) where T : ScriptableObject
{
T asset = ScriptableObject.CreateInstance<T>();
string directoryPath = Path.GetDirectoryName(fullPath);
if (!Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(fullPath);
AssetDatabase.CreateAsset(asset, assetPathAndName);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.FocusProjectWindow();
Selection.activeObject = asset;
}
/// <summary>
/// 获取或创建ScriptableObject资产文件
/// </summary>
public static T GetOrCreateAsset<T>(string fullPath) where T : ScriptableObject
{
T asset = AssetDatabase.LoadAssetAtPath<T>(fullPath);
if (asset == null)
{
CreateAsset<T>(fullPath);
asset = AssetDatabase.LoadAssetAtPath<T>(fullPath);
}
return asset;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 54e51fb34aa14d6f8e631baadcc9ede5
timeCreated: 1731427402

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c3c81bd4cd80406c85154732adfdb65d
timeCreated: 1732008523

View File

@@ -0,0 +1,487 @@
// using System;
// using System.Collections.Generic;
// using System.Data;
// using System.Diagnostics;
// using System.Globalization;
// using System.IO;
// using System.Linq;
// using System.Reflection;
// using System.Text;
// using ExcelDataReader;
// using NBC;
// using Newtonsoft.Json;
// using Newtonsoft.Json.Linq;
// using UnityEditor;
// using UnityEngine;
// using Debug = UnityEngine.Debug;
//
// namespace NBF
// {
// public static class ExcelToJsonWindow
// {
// #region 生成配置表
//
// public static void GenConfig(bool showMessageBox = true)
// {
// CfgEditorUtil.GenConfigScripts();
// GenConfig(Application.dataPath + "/../Config", showMessageBox);
// }
//
//
// public static void GenConfig(string path, bool showMessageBox = false)
// {
// List<string> list = new List<string>();
//
// GetFiles(path, fileList: ref list);
//
// AllJsonData.Clear();
// Stopwatch s = Stopwatch.StartNew();
//
// ReadExcel(list.ToArray());
//
// BuildAsset();
//
// s.Stop();
// if (showMessageBox)
// {
// EditorUtility.DisplayDialog("成功", $"导表完成,耗时{(s.ElapsedMilliseconds / 1000f):.00}秒", "知道了");
// EditorUtility.ClearProgressBar();
// }
// else
// {
// Debug.Log($"导表完成,耗时{(s.ElapsedMilliseconds / 1000f):.00}秒");
// }
//
// AssetDatabase.Refresh();
// }
//
//
// private static void BuildAsset()
// {
// var json = JsonConvert.SerializeObject(AllJsonData, Formatting.Indented, new JsonSerializerSettings
// {
// ReferenceLoopHandling = ReferenceLoopHandling.Ignore
// });
// var jsonObj = JObject.Parse(json);
//
// Dictionary<string, JToken> tokens = new Dictionary<string, JToken>(StringComparer.OrdinalIgnoreCase);
//
// foreach (var item in jsonObj)
// {
// try
// {
// var name = item.Key;
// var value = item.Value;
// if (value != null)
// {
// tokens[name] = value;
// }
// }
// catch (Exception e)
// {
// Log.Error($"读表异常请检查name={item.Key} ex={e}");
// }
// }
//
// var relativePath = ConfigAssets.SavePath;
//
// var asset = EditorUtils.GetOrCreateAsset<ConfigAssets>(relativePath);
//
// var types = Reflection.GetAllNonAbstractDerivedTypes<ConfigBase>();
// foreach (var type in types)
// {
// var tableNameAttribute = type.GetCustomAttribute<TableNameAttribute>();
// if (tableNameAttribute == null) continue;
// if (!tokens.TryGetValue(tableNameAttribute.Name, out var token))
// {
// Log.Warning($"{tableNameAttribute.Name} 解析失败tableName不一致");
// continue;
// }
//
// if (token is not JArray jArray) return;
// asset.Parse(jArray.ToArray(), type);
// }
//
// EditorUtility.SetDirty(asset);
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
// }
//
// #endregion
//
// #region 生成多语言
//
// public static void GenLanguage()
// {
// var path = Application.dataPath + "/../Config/language";
//
// List<string> list = new List<string>();
//
// GetFiles(path, fileList: ref list);
//
// AllJsonData.Clear();
// Stopwatch s = Stopwatch.StartNew();
//
// ReadExcel(list.ToArray());
//
// var savePath = Path.Combine(Application.dataPath, "Resources/config/language.json");
//
// BuildJson(savePath);
//
// s.Stop();
//
// Debug.Log($"导多语言完成,耗时{(s.ElapsedMilliseconds / 1000f):.00}秒");
//
// AssetDatabase.Refresh();
// }
//
// private static void BuildJson(string savaPath)
// {
// var json = JsonConvert.SerializeObject(AllJsonData, Formatting.Indented, new JsonSerializerSettings
// {
// ReferenceLoopHandling = ReferenceLoopHandling.Ignore
// });
// SaveJson(savaPath, json);
//
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
// }
//
// #endregion
//
// #region 文件读写
//
// private static void GetFiles(string path, ref List<string> fileList)
// {
// var files = Directory.GetFiles(path);
// if (files.Length > 0)
// {
// foreach (var file in files)
// {
// var fileName = Path.GetFileName(file);
//
// if ((fileName.EndsWith(".xls", true, CultureInfo.CurrentCulture) ||
// fileName.EndsWith(".xlsx", true, CultureInfo.CurrentCulture)) && !fileName.StartsWith(".") &&
// !fileName.StartsWith("~"))
// {
// fileList.Add(file.Replace('\\', '/'));
// }
// }
// }
// }
//
// private static void SaveJson(string jsonPath, string json)
// {
// try
// {
// if (File.Exists(jsonPath))
// {
// File.Delete(jsonPath);
// }
//
// File.WriteAllBytes(jsonPath, Encoding.UTF8.GetBytes(json));
// }
// catch (Exception e)
// {
// // Console.WriteLine(e);
// // throw;
// }
// }
//
// #endregion
//
// #region Excel读取
//
// private static readonly Dictionary<string, object> AllJsonData = new Dictionary<string, object>();
// private static bool _buildIng = false;
// private static int _buildTotal = 0;
//
// private static int _buildDoneCount = 0;
//
// private static void ReadExcel(IReadOnlyCollection<string> paths)
// {
// _buildTotal = paths.Count;
// _buildDoneCount = 0;
// _buildIng = true;
//
// foreach (var t in paths)
// {
// ReadSingleExcel(t);
// }
//
// _buildIng = false;
// }
//
// private static void ReadSingleExcelFunc(string xlsxPath, bool isThrow = false)
// {
// try
// {
// using FileStream stream = File.Open(xlsxPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
// DataSet result = excelReader.AsDataSet();
// // 读取第一张工资表
// DataTableCollection tc = result.Tables;
//
// if (tc.Count >= 1)
// {
// foreach (DataTable table in tc)
// {
// if (!table.TableName.StartsWith("!") && !table.TableName.StartsWith("Sheet"))
// {
// ReadSingleSheet(table, isThrow);
// }
// }
// }
// else
// {
// Debug.LogError("表名为空,请检查表");
// }
// }
// catch (Exception e)
// {
// Log.Error(e);
// }
// }
//
//
// public static void ReadSingleExcel(string xlsxPath, bool isThrow = false)
// {
// Stopwatch s = Stopwatch.StartNew();
// string xlsxName = Path.GetFileName(xlsxPath);
//
// if (!File.Exists(xlsxPath))
// {
// Debug.LogError("不存在该Excel");
// return;
// }
//
// try
// {
// ReadSingleExcelFunc(xlsxPath, isThrow);
//
// Debug.Log(xlsxName + ".xlsx" + "转换Json成功");
//
// s.Stop();
// Debug.Log($"导表{xlsxName},花费时间={s.ElapsedMilliseconds}毫秒");
// _buildDoneCount++;
// }
// catch (Exception e)
// {
// Debug.LogError(e);
// }
// }
//
// /// <summary>
// /// 读取一个工作表的数据
// /// </summary>
// /// <param name="dataTable">读取的工作表数据</param>
// /// <param name="isThrow">是否抛出异常</param>
// private static void ReadSingleSheet(DataTable dataTable, bool isThrow = false)
// {
// int rows = dataTable.Rows.Count;
// int columns = dataTable.Columns.Count;
// if (rows < 1 || columns < 1)
// {
// return;
// }
//
// // 工作表的行数据
// DataRowCollection collect = dataTable.Rows;
// // xlsx对应的数据字段规定是第二行
// string[] jsonFields = new string[columns];
// string[] jsonFieldsType = new string[columns];
// // 要保存成Json的obj
// List<object> objsToSave = new List<object>();
// for (int i = 0; i < columns; i++)
// {
// //字段
// jsonFields[i] = collect[1][i].ToString();
// //字段类型
// jsonFieldsType[i] = collect[2][i].ToString();
// }
//
// // _lastTableName = dataTable.TableName;
// // 从第三行开始
// for (int i = 3; i < rows; i++)
// {
// Dictionary<string, object> jObject = new Dictionary<string, object>();
//
// // _lastX = i;
// for (int j = 0; j < columns; j++)
// {
// var objectValue = collect[i][j].ToString();
// // _lastY = j;
// var lastValue = $"{collect[1][j]}---{objectValue}";
// try
// {
// if (isThrow)
// {
// Debug.Log($"{i}/{j}/{objectValue}");
// }
//
// Type type = GetTypeByString(jsonFieldsType[j]);
// // 获取字段
// string field = jsonFields[j];
// //过滤掉字段为空的值
// if (!string.IsNullOrEmpty(field))
// {
// object value = null;
// if (!string.IsNullOrEmpty(objectValue))
// {
// //需要先判断下是否为数组
// if (type != typeof(Array))
// {
// //需要判断一下是否为bool值 bool 直接返回int 0 或者 1
// if (type == typeof(bool))
// {
// value = int.Parse(objectValue);
// }
// else if (type == typeof(Vector2))
// {
// value = objectValue.ToVector2();
// }
// else if (type == typeof(Vector3))
// {
// value = objectValue.ToVector3();
// }
// else
// {
// value = Convert.ChangeType(objectValue, type);
// }
// }
// else
// {
// //这里在做二维数组的处理
// //一般到这都是Int数组当然还可以更细致的处理不同类型的数组
// string[] strs = objectValue.Split(',');
// string arrayType = jsonFieldsType[j];
//
// object[] ints = new object[strs.Length];
//
// for (int k = 0; k < strs.Length; k++)
// {
// switch (arrayType)
// {
// case "[int]":
// {
// int.TryParse(strs[k], out var v);
// ints[k] = v;
// break;
// }
// case "[float]":
// {
// float.TryParse(strs[k], out var v);
// ints[k] = v;
// break;
// }
// case "[string]":
// ints[k] = strs[k];
// break;
// default:
// ints[k] = strs[k];
// break;
// }
// }
//
// value = ints;
// }
// }
// else
// {
// // Log.I($"{dataTable.TableName} 字段{field}有空值存在 第{j + 1}列数据 请检查表格!!!");
// //如果值为空会出现导表失败 这里需要做一下处理
// value = GetDataType(type);
// }
//
// jObject[field] = value;
// }
// }
// catch (Exception)
// {
// Debug.LogError($"解析表错误table={dataTable.TableName} y={i} x={j} value={lastValue}");
// }
// }
//
// objsToSave.Add(jObject);
// }
//
// AllJsonData[dataTable.TableName] = objsToSave;
// }
//
//
// /// <summary>
// /// 判断一下数据类型
// /// </summary>
// /// <param name="type"></param>
// /// <returns></returns>
// public static object GetDataType(Type type)
// {
// object value = null;
// if (type == typeof(int) || type == typeof(float))
// {
// value = 0;
// }
// else if (type == typeof(string))
// {
// value = "";
// }
// else if (type == typeof(bool))
// {
// //如果boo值类型为空 默认显示
// value = 0;
// }
// else if (type == typeof(Array))
// {
// value = new List<object>().ToArray();
// }
// else
// {
// value = "";
// }
//
// return value;
// }
//
// /// <summary>
// /// 获取字段类型
// /// </summary>
// /// <param name="type"></param>
// /// <returns></returns>
// public static Type GetTypeByString(string type)
// {
// switch (type.ToLower())
// {
// case "bool":
// return typeof(bool);
// case "array":
// return typeof(Array);
// case "double":
// return typeof(double);
// case "float":
// return typeof(float);
// case "int":
// return typeof(int);
// case "long":
// return typeof(long);
// case "object":
// return typeof(object);
// case "string":
// return typeof(string);
// case "[float]":
// return typeof(Array);
// case "[int]":
// return typeof(Array);
// case "[string]":
// return typeof(Array);
// case "v2":
// return typeof(Vector2);
// case "v3":
// return typeof(Vector3);
// default:
// return typeof(string);
// }
// }
//
// #endregion
// }
// }

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 33a6f327da22471c96c66e7bb7e83de9
timeCreated: 1732008526

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3fa57e7cd335467f8be7158eef21edb8
timeCreated: 1768704531

View File

@@ -0,0 +1,329 @@
using UnityEngine;
using UnityEditor;
using FairyGUI;
namespace FairyGUIEditor
{
/// <summary>
///
/// </summary>
[CustomEditor(typeof(DisplayObjectInfo))]
public class DisplayObjectEditor : Editor
{
#if UNITY_2019_1_OR_NEWER
bool _guiControllersFoldout = true;
bool _guiTransitionsFoldout = true;
bool _guiTextFormatFoldout = true;
#endif
void OnEnable()
{
EditorApplication.update += _onEditorAppUpdate;
}
private void OnDisable()
{
EditorApplication.update -= _onEditorAppUpdate;
}
void _onEditorAppUpdate()
{
Repaint();
}
public override void OnInspectorGUI()
{
DisplayObject obj = (target as DisplayObjectInfo).displayObject;
if (obj == null)
return;
EditorGUILayout.LabelField(obj.GetType().Name + ": " + obj.id, (GUIStyle)"OL Title");
EditorGUILayout.Separator();
EditorGUI.BeginChangeCheck();
string name = EditorGUILayout.TextField("Name", obj.name);
if (EditorGUI.EndChangeCheck())
obj.name = name;
if (obj is Container)
{
EditorGUI.BeginChangeCheck();
bool fairyBatching = EditorGUILayout.Toggle("FairyBatching", ((Container)obj).fairyBatching);
if (EditorGUI.EndChangeCheck())
((Container)obj).fairyBatching = fairyBatching;
}
GObject gObj = obj.gOwner;
if (gObj != null)
{
EditorGUILayout.Separator();
EditorGUILayout.LabelField(gObj.GetType().Name + ": " + gObj.id, (GUIStyle)"OL Title");
EditorGUILayout.Separator();
if (!string.IsNullOrEmpty(gObj.resourceURL))
{
PackageItem pi = UIPackage.GetItemByURL(gObj.resourceURL);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Resource");
EditorGUILayout.LabelField(pi.name + "@" + pi.owner.name);
EditorGUILayout.EndHorizontal();
}
EditorGUI.BeginChangeCheck();
name = EditorGUILayout.TextField("Name", gObj.name);
if (EditorGUI.EndChangeCheck())
gObj.name = name;
if (gObj.parent != null)
{
string[] options = new string[gObj.parent.numChildren];
int[] values = new int[options.Length];
for (int i = 0; i < options.Length; i++)
{
options[i] = i.ToString();
values[i] = i;
}
EditorGUI.BeginChangeCheck();
int childIndex = EditorGUILayout.IntPopup("Child Index", gObj.parent.GetChildIndex(gObj), options, values);
if (EditorGUI.EndChangeCheck())
gObj.parent.SetChildIndex(gObj, childIndex);
}
else
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Child Index");
EditorGUILayout.LabelField("No Parent");
EditorGUILayout.EndHorizontal();
}
EditorGUI.BeginChangeCheck();
float alpha = EditorGUILayout.Slider("Alpha", gObj.alpha, 0, 1);
if (EditorGUI.EndChangeCheck())
gObj.alpha = alpha;
EditorGUI.BeginChangeCheck();
Vector3 position = EditorGUILayout.Vector3Field("Position", gObj.position);
if (EditorGUI.EndChangeCheck())
gObj.position = position;
EditorGUI.BeginChangeCheck();
Vector3 rotation = EditorGUILayout.Vector3Field("Rotation", new Vector3(gObj.rotationX, gObj.rotationY, gObj.rotation));
if (EditorGUI.EndChangeCheck())
{
gObj.rotationX = rotation.x;
gObj.rotationY = rotation.y;
gObj.rotation = rotation.z;
}
EditorGUI.BeginChangeCheck();
Vector2 scale = EditorGUILayout.Vector2Field("Scale", gObj.scale);
if (EditorGUI.EndChangeCheck())
gObj.scale = scale;
EditorGUI.BeginChangeCheck();
Vector2 skew = EditorGUILayout.Vector2Field("Skew", gObj.skew);
if (EditorGUI.EndChangeCheck())
gObj.skew = skew;
EditorGUI.BeginChangeCheck();
Vector2 size = EditorGUILayout.Vector2Field("Size", gObj.size);
if (EditorGUI.EndChangeCheck())
gObj.size = size;
EditorGUI.BeginChangeCheck();
Vector2 pivot = EditorGUILayout.Vector2Field("Pivot", gObj.pivot);
if (EditorGUI.EndChangeCheck())
gObj.pivot = pivot;
EditorGUI.BeginChangeCheck();
string text = EditorGUILayout.TextField("Text", gObj.text);
if (EditorGUI.EndChangeCheck())
gObj.text = text;
EditorGUI.BeginChangeCheck();
string icon = EditorGUILayout.TextField("Icon", gObj.icon);
if (EditorGUI.EndChangeCheck())
gObj.icon = icon;
//Draw Color Field
var objType = gObj.GetType();
var colorProperty = objType.GetProperty("color");
if (colorProperty != null)
{
EditorGUI.BeginChangeCheck();
Color color = (Color)colorProperty.GetValue(gObj);
color = EditorGUILayout.ColorField("Color", color);
if (EditorGUI.EndChangeCheck())
{
colorProperty.SetValue(gObj, color);
}
}
EditorGUI.BeginChangeCheck();
string tooltips = EditorGUILayout.TextField("Tooltips", gObj.tooltips);
if (EditorGUI.EndChangeCheck())
gObj.tooltips = tooltips;
if (!(gObj is GImage))
{
EditorGUI.BeginChangeCheck();
bool touchable = EditorGUILayout.Toggle("Touchable", gObj.touchable);
if (EditorGUI.EndChangeCheck())
gObj.touchable = touchable;
EditorGUI.BeginChangeCheck();
bool draggable = EditorGUILayout.Toggle("Draggable", gObj.draggable);
if (EditorGUI.EndChangeCheck())
gObj.draggable = draggable;
}
#if UNITY_2019_1_OR_NEWER
TextFormat textFormat = null;
if (gObj is GTextField gTxt)
{
textFormat = gTxt.textFormat;
}
if (textFormat != null)
{
_guiTextFormatFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(_guiTextFormatFoldout, "Text Format");
EditorGUI.BeginChangeCheck();
if (_guiTextFormatFoldout)
{
var initLabelWidth = EditorGUIUtility.labelWidth;
var richStyle = new GUIStyle(GUI.skin.label);
richStyle.richText = true;
EditorGUIUtility.labelWidth = 60;
textFormat.font = EditorGUILayout.TextField("Font", textFormat.font);
textFormat.align = (AlignType)EditorGUILayout.EnumPopup("Align", textFormat.align);
EditorGUIUtility.labelWidth = initLabelWidth;
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 40;
textFormat.size = EditorGUILayout.IntField("Size", textFormat.size);
textFormat.color = EditorGUILayout.ColorField("Color", textFormat.color);
EditorGUIUtility.labelWidth = initLabelWidth;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 40;
textFormat.outline = EditorGUILayout.FloatField("Outline", textFormat.outline);
textFormat.outlineColor = EditorGUILayout.ColorField("Color", textFormat.outlineColor);
EditorGUIUtility.labelWidth = initLabelWidth;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 50;
textFormat.shadowOffset = EditorGUILayout.Vector2Field("Shadow Offset", textFormat.shadowOffset);
textFormat.shadowColor = EditorGUILayout.ColorField("Color", textFormat.shadowColor);
EditorGUIUtility.labelWidth = initLabelWidth;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
textFormat.italic = EditorGUILayout.ToggleLeft("<i>I</i>", textFormat.italic, richStyle, GUILayout.Width(30));
textFormat.bold = EditorGUILayout.ToggleLeft("<b>B</b>", textFormat.bold, richStyle, GUILayout.Width(30));
textFormat.underline = EditorGUILayout.ToggleLeft("U̲", textFormat.underline, richStyle, GUILayout.Width(30));
textFormat.strikethrough = EditorGUILayout.ToggleLeft(" S̶ ̶ ̶", textFormat.strikethrough, richStyle, GUILayout.Width(36));
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 90;
textFormat.lineSpacing = EditorGUILayout.IntField("Line Spacing", textFormat.lineSpacing);
textFormat.letterSpacing = EditorGUILayout.IntField("Letter Spacing", textFormat.letterSpacing);
EditorGUIUtility.labelWidth = initLabelWidth;
EditorGUILayout.EndHorizontal();
textFormat.specialStyle = (TextFormat.SpecialStyle)EditorGUILayout.EnumPopup("Special Style", textFormat.specialStyle);
}
if (EditorGUI.EndChangeCheck())
gObj.asTextField.textFormat = textFormat;
EditorGUILayout.EndFoldoutHeaderGroup();
}
if (gObj is GComponent gComp)
{
EditorGUI.BeginChangeCheck();
bool opaque = EditorGUILayout.Toggle("Opaque", gComp.opaque);
if (EditorGUI.EndChangeCheck())
gComp.opaque = opaque;
var headerLabelStyle = new GUIStyle(GUI.skin.label);
headerLabelStyle.fontStyle = FontStyle.Bold;
if (gComp.Controllers.Count > 0)
{
_guiControllersFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(_guiControllersFoldout, "Controllers");
if (_guiControllersFoldout)
{
foreach (var ctl in gComp.Controllers)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(ctl.name, headerLabelStyle, GUILayout.MaxWidth(ctl.name.Length * 15));
for (var i = 0; i < ctl.pageCount; i++)
{
var btnName = ctl.GetPageId(i) + ": " + ctl.GetPageName(i);
var btnStyle = new GUIStyle("ButtonMid");
if (ctl.selectedIndex == i)
{
btnStyle.normal.textColor = Color.green;
btnStyle.hover.textColor = Color.yellow;
btnStyle.fontStyle = FontStyle.Bold;
}
if (GUILayout.Button(btnName, btnStyle))
{
ctl.selectedIndex = i;
}
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.EndFoldoutHeaderGroup();
}
if (gComp.Transitions.Count > 0)
{
_guiTransitionsFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(_guiTransitionsFoldout, "Transitions");
if (_guiTransitionsFoldout)
{
foreach (var transition in gComp.Transitions)
{
EditorGUILayout.BeginHorizontal();
var labelStyle = new GUIStyle(headerLabelStyle);
if (transition.playing)
{
labelStyle.normal.textColor = Color.yellow;
}
EditorGUILayout.LabelField($"{transition.name} - {transition.totalDuration}s", labelStyle, GUILayout.MinWidth(150));
EditorGUI.BeginChangeCheck();
var timeScale = transition.timeScale;
if (EditorGUI.EndChangeCheck())
transition.timeScale = timeScale;
if (GUILayout.Button("▶", GUILayout.Width(20)))
{
transition.Play();
}
if (GUILayout.Button("■", GUILayout.Width(20)))
{
transition.Stop();
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.EndFoldoutHeaderGroup();
}
}
#endif
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: a2f78faa29e5e1547837f976bf4b39f2
timeCreated: 1541149029
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,142 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using FairyGUI;
namespace FairyGUIEditor
{
/// <summary>
///
/// </summary>
public class EditorToolSet
{
public static GUIContent[] packagesPopupContents;
static bool _loaded;
[InitializeOnLoadMethod]
static void Startup()
{
EditorApplication.update += EditorApplication_Update;
}
[RuntimeInitializeOnLoadMethod]
static void InitializeOnLoad()
{
_loaded = false;
}
[MenuItem("GameObject/FairyGUI/UI Panel", false, 0)]
static void CreatePanel()
{
EditorApplication.update -= EditorApplication_Update;
EditorApplication.update += EditorApplication_Update;
StageCamera.CheckMainCamera();
GameObject panelObject = new GameObject("UIPanel");
if (Selection.activeGameObject != null)
{
panelObject.transform.parent = Selection.activeGameObject.transform;
panelObject.layer = Selection.activeGameObject.layer;
}
else
{
int layer = LayerMask.NameToLayer(StageCamera.LayerName);
panelObject.layer = layer;
}
panelObject.AddComponent<FairyGUI.UIPanel>();
Selection.objects = new Object[] { panelObject };
}
[MenuItem("GameObject/FairyGUI/UI Camera", false, 0)]
static void CreateCamera()
{
StageCamera.CheckMainCamera();
Selection.objects = new Object[] { StageCamera.main.gameObject };
}
[MenuItem("Window/FairyGUI - Refresh Packages And Panels")]
static void RefreshPanels()
{
ReloadPackages();
}
static void EditorApplication_Update()
{
if (Application.isPlaying)
return;
if (_loaded || !EMRenderSupport.hasTarget)
return;
LoadPackages();
}
public static void ReloadPackages()
{
if (!Application.isPlaying)
{
_loaded = false;
LoadPackages();
Debug.Log("FairyGUI - Refresh Packages And Panels complete.");
}
else
EditorUtility.DisplayDialog("FairyGUI", "Cannot run in play mode.", "OK");
}
public static void LoadPackages()
{
if (Application.isPlaying || _loaded)
return;
EditorApplication.update -= EditorApplication_Update;
EditorApplication.update += EditorApplication_Update;
_loaded = true;
UIPackage.RemoveAllPackages();
UIPackage.branch = null;
FontManager.Clear();
NTexture.DisposeEmpty();
UIObjectFactory.Clear();
string[] ids = AssetDatabase.FindAssets("_fui t:textAsset");
int cnt = ids.Length;
for (int i = 0; i < cnt; i++)
{
string assetPath = AssetDatabase.GUIDToAssetPath(ids[i]);
int pos = assetPath.LastIndexOf("_fui");
if (pos == -1)
continue;
assetPath = assetPath.Substring(0, pos);
if (AssetDatabase.AssetPathToGUID(assetPath) != null)
UIPackage.AddPackage(assetPath,
(string name, string extension, System.Type type, out DestroyMethod destroyMethod) =>
{
destroyMethod = DestroyMethod.Unload;
return AssetDatabase.LoadAssetAtPath(name + extension, type);
}
);
}
List<UIPackage> pkgs = UIPackage.GetPackages();
pkgs.Sort(CompareUIPackage);
cnt = pkgs.Count;
packagesPopupContents = new GUIContent[cnt + 1];
for (int i = 0; i < cnt; i++)
packagesPopupContents[i] = new GUIContent(pkgs[i].name);
packagesPopupContents[cnt] = new GUIContent("Please Select");
EMRenderSupport.Reload();
}
static int CompareUIPackage(UIPackage u1, UIPackage u2)
{
return u1.name.CompareTo(u2.name);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 35dcb233f95ffd54c94f09d731db89ae
timeCreated: 1535374214
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
{
"name": "FairyGUI-Editor",
"rootNamespace": "",
"references": [
"FairyGUI"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f11907887f480418c8c693a619e2dbf0
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,193 @@
using FairyGUI;
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.Collections.Generic;
#if UNITY_2018_3_OR_NEWER
using UnityEditor.Experimental.SceneManagement;
#endif
namespace FairyGUIEditor
{
/// <summary>
///
/// </summary>
public class PackagesWindow : EditorWindow
{
Vector2 scrollPos1;
Vector2 scrollPos2;
GUIStyle itemStyle;
int selectedPackage;
string selectedPackageName;
string selectedComponentName;
public PackagesWindow()
{
this.maxSize = new Vector2(550, 400);
this.minSize = new Vector2(550, 400);
}
public void SetSelection(string packageName, string componentName)
{
selectedPackageName = packageName;
selectedComponentName = componentName;
}
void OnGUI()
{
if (itemStyle == null)
itemStyle = new GUIStyle(GUI.skin.GetStyle("Tag MenuItem"));
EditorGUILayout.BeginHorizontal();
//package list start------
EditorGUILayout.BeginHorizontal();
GUILayout.Space(5);
EditorGUILayout.BeginVertical();
GUILayout.Space(10);
EditorGUILayout.LabelField("Packages", (GUIStyle)"OL Title", GUILayout.Width(300));
GUILayout.Space(5);
EditorGUILayout.BeginHorizontal();
GUILayout.Space(4);
scrollPos1 = EditorGUILayout.BeginScrollView(scrollPos1, (GUIStyle)"CN Box", GUILayout.Height(300), GUILayout.Width(300));
EditorToolSet.LoadPackages();
List<UIPackage> pkgs = UIPackage.GetPackages();
int cnt = pkgs.Count;
if (cnt == 0)
{
selectedPackage = -1;
selectedPackageName = null;
}
else
{
for (int i = 0; i < cnt; i++)
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Toggle(selectedPackageName == pkgs[i].name, pkgs[i].name, itemStyle, GUILayout.ExpandWidth(true)))
{
selectedPackage = i;
selectedPackageName = pkgs[i].name;
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.EndScrollView();
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
//package list end------
//component list start------
EditorGUILayout.BeginHorizontal();
GUILayout.Space(5);
EditorGUILayout.BeginVertical();
GUILayout.Space(10);
EditorGUILayout.LabelField("Components", (GUIStyle)"OL Title", GUILayout.Width(220));
GUILayout.Space(5);
EditorGUILayout.BeginHorizontal();
GUILayout.Space(4);
scrollPos2 = EditorGUILayout.BeginScrollView(scrollPos2, (GUIStyle)"CN Box", GUILayout.Height(300), GUILayout.Width(220));
if (selectedPackage >= 0)
{
List<PackageItem> items = pkgs[selectedPackage].GetItems();
int i = 0;
foreach (PackageItem pi in items)
{
if (pi.type == PackageItemType.Component && pi.exported)
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Toggle(selectedComponentName == pi.name, pi.name, itemStyle, GUILayout.ExpandWidth(true)))
selectedComponentName = pi.name;
i++;
EditorGUILayout.EndHorizontal();
}
}
}
EditorGUILayout.EndScrollView();
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
//component list end------
GUILayout.Space(10);
EditorGUILayout.EndHorizontal();
GUILayout.Space(20);
//buttons start---
EditorGUILayout.BeginHorizontal();
GUILayout.Space(180);
if (GUILayout.Button("Refresh", GUILayout.Width(100)))
EditorToolSet.ReloadPackages();
GUILayout.Space(20);
if (GUILayout.Button("OK", GUILayout.Width(100)) && selectedPackage >= 0)
{
UIPackage selectedPkg = pkgs[selectedPackage];
string tmp = selectedPkg.assetPath.ToLower();
string packagePath;
int pos = tmp.LastIndexOf("/resources/");
if (pos != -1)
packagePath = selectedPkg.assetPath.Substring(pos + 11);
else
{
pos = tmp.IndexOf("resources/");
if (pos == 0)
packagePath = selectedPkg.assetPath.Substring(pos + 10);
else
packagePath = selectedPkg.assetPath;
}
if (Selection.activeGameObject != null)
{
#if UNITY_2018_3_OR_NEWER
bool isPrefab = PrefabUtility.GetPrefabAssetType(Selection.activeGameObject) != PrefabAssetType.NotAPrefab;
#else
bool isPrefab = PrefabUtility.GetPrefabType(Selection.activeGameObject) == PrefabType.Prefab;
#endif
Selection.activeGameObject.SendMessage("OnUpdateSource",
new object[] { selectedPkg.name, packagePath, selectedComponentName, !isPrefab },
SendMessageOptions.DontRequireReceiver);
}
#if UNITY_2018_3_OR_NEWER
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null)
EditorSceneManager.MarkSceneDirty(prefabStage.scene);
else
ApplyChange();
#else
ApplyChange();
#endif
this.Close();
}
EditorGUILayout.EndHorizontal();
}
void ApplyChange()
{
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 83ed477a96af9c94f9f2ccc24b5a24c0
timeCreated: 1535374214
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
using UnityEditor;
using FairyGUI;
namespace FairyGUIEditor
{
/// <summary>
///
/// </summary>
[CustomEditor(typeof(StageCamera))]
public class StageCameraEditor : Editor
{
string[] propertyToExclude;
void OnEnable()
{
propertyToExclude = new string[] { "m_Script" };
}
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawPropertiesExcluding(serializedObject, propertyToExclude);
if (serializedObject.ApplyModifiedProperties())
(target as StageCamera).ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 2b99582678b83dc46986b02984c665a3
timeCreated: 1460480287
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,226 @@
using UnityEngine;
using UnityEditor;
using FairyGUI;
namespace FairyGUIEditor
{
/// <summary>
///
/// </summary>
[CustomEditor(typeof(UIConfig))]
public class UIConfigEditor : Editor
{
string[] propertyToExclude;
bool itemsFoldout;
bool packagesFoldOut;
int errorState;
private const float kButtonWidth = 18f;
void OnEnable()
{
propertyToExclude = new string[] { "m_Script", "Items", "PreloadPackages" };
itemsFoldout = EditorPrefs.GetBool("itemsFoldOut");
packagesFoldOut = EditorPrefs.GetBool("packagesFoldOut");
errorState = 0;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawPropertiesExcluding(serializedObject, propertyToExclude);
UIConfig config = (UIConfig)target;
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginChangeCheck();
itemsFoldout = EditorGUILayout.Foldout(itemsFoldout, "Config Items");
if (EditorGUI.EndChangeCheck())
EditorPrefs.SetBool("itemsFoldOut", itemsFoldout);
EditorGUILayout.EndHorizontal();
bool modified = false;
if (itemsFoldout)
{
Undo.RecordObject(config, "Items");
int len = config.Items.Count;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Add");
UIConfig.ConfigKey selectedKey = (UIConfig.ConfigKey)EditorGUILayout.EnumPopup((System.Enum)UIConfig.ConfigKey.PleaseSelect);
if (selectedKey != UIConfig.ConfigKey.PleaseSelect)
{
int index = (int)selectedKey;
if (index > len - 1)
{
for (int i = len; i < index; i++)
config.Items.Add(new UIConfig.ConfigValue());
UIConfig.ConfigValue value = new UIConfig.ConfigValue();
value.valid = true;
UIConfig.SetDefaultValue(selectedKey, value);
config.Items.Add(value);
}
else
{
UIConfig.ConfigValue value = config.Items[index];
if (value == null)
{
value = new UIConfig.ConfigValue();
value.valid = true;
UIConfig.SetDefaultValue(selectedKey, value);
config.Items[index] = value;
}
else if (!value.valid)
{
value.valid = true;
UIConfig.SetDefaultValue(selectedKey, value);
}
}
}
EditorGUILayout.EndHorizontal();
for (int i = 0; i < len; i++)
{
UIConfig.ConfigValue value = config.Items[i];
if (value == null || !value.valid)
continue;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(((UIConfig.ConfigKey)i).ToString());
switch ((UIConfig.ConfigKey)i)
{
case UIConfig.ConfigKey.ClickDragSensitivity:
case UIConfig.ConfigKey.DefaultComboBoxVisibleItemCount:
case UIConfig.ConfigKey.DefaultScrollStep:
case UIConfig.ConfigKey.TouchDragSensitivity:
case UIConfig.ConfigKey.TouchScrollSensitivity:
case UIConfig.ConfigKey.InputCaretSize:
value.i = EditorGUILayout.IntField(value.i);
break;
case UIConfig.ConfigKey.ButtonSound:
case UIConfig.ConfigKey.GlobalModalWaiting:
case UIConfig.ConfigKey.HorizontalScrollBar:
case UIConfig.ConfigKey.LoaderErrorSign:
case UIConfig.ConfigKey.PopupMenu:
case UIConfig.ConfigKey.PopupMenu_seperator:
case UIConfig.ConfigKey.TooltipsWin:
case UIConfig.ConfigKey.VerticalScrollBar:
case UIConfig.ConfigKey.WindowModalWaiting:
case UIConfig.ConfigKey.DefaultFont:
value.s = EditorGUILayout.TextField(value.s);
break;
case UIConfig.ConfigKey.DefaultScrollBounceEffect:
case UIConfig.ConfigKey.DefaultScrollTouchEffect:
case UIConfig.ConfigKey.RenderingTextBrighterOnDesktop:
case UIConfig.ConfigKey.AllowSoftnessOnTopOrLeftSide:
case UIConfig.ConfigKey.DepthSupportForPaintingMode:
value.b = EditorGUILayout.Toggle(value.b);
break;
case UIConfig.ConfigKey.ButtonSoundVolumeScale:
value.f = EditorGUILayout.Slider(value.f, 0, 1);
break;
case UIConfig.ConfigKey.ModalLayerColor:
case UIConfig.ConfigKey.InputHighlightColor:
value.c = EditorGUILayout.ColorField(value.c);
break;
case UIConfig.ConfigKey.Branch:
EditorGUI.BeginChangeCheck();
value.s = EditorGUILayout.TextField(value.s);
if (EditorGUI.EndChangeCheck())
modified = true;
break;
}
if (GUILayout.Button(new GUIContent("X", "Delete Item"), EditorStyles.miniButtonRight, GUILayout.Width(30)))
{
config.Items[i].Reset();
UIConfig.SetDefaultValue((UIConfig.ConfigKey)i, config.Items[i]);
modified = true;
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginChangeCheck();
packagesFoldOut = EditorGUILayout.Foldout(packagesFoldOut, "Preload Packages");
if (EditorGUI.EndChangeCheck())
EditorPrefs.SetBool("packagesFoldOut", packagesFoldOut);
EditorGUILayout.EndHorizontal();
if (packagesFoldOut)
{
Undo.RecordObject(config, "PreloadPackages");
EditorToolSet.LoadPackages();
if (EditorToolSet.packagesPopupContents != null)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Add");
int selected = EditorGUILayout.Popup(EditorToolSet.packagesPopupContents.Length - 1, EditorToolSet.packagesPopupContents);
EditorGUILayout.EndHorizontal();
if (selected != EditorToolSet.packagesPopupContents.Length - 1)
{
UIPackage pkg = UIPackage.GetPackages()[selected];
string tmp = pkg.assetPath.ToLower();
int pos = tmp.LastIndexOf("resources/");
if (pos != -1)
{
string packagePath = pkg.assetPath.Substring(pos + 10);
if (config.PreloadPackages.IndexOf(packagePath) == -1)
config.PreloadPackages.Add(packagePath);
errorState = 0;
}
else
{
errorState = 10;
}
}
}
if (errorState > 0)
{
errorState--;
EditorGUILayout.HelpBox("Package is not in resources folder.", MessageType.Warning);
}
int cnt = config.PreloadPackages.Count;
int pi = 0;
while (pi < cnt)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("" + pi + ".");
config.PreloadPackages[pi] = EditorGUILayout.TextField(config.PreloadPackages[pi]);
if (GUILayout.Button(new GUIContent("X", "Delete Item"), EditorStyles.miniButtonRight, GUILayout.Width(30)))
{
config.PreloadPackages.RemoveAt(pi);
cnt--;
}
else
pi++;
EditorGUILayout.EndHorizontal();
}
}
else
errorState = 0;
if (serializedObject.ApplyModifiedProperties() || modified)
(target as UIConfig).ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 74df68b10ee56a54a8105d88312571ce
timeCreated: 1460480288
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using UnityEditor;
using FairyGUI;
namespace FairyGUIEditor
{
/// <summary>
///
/// </summary>
[CustomEditor(typeof(UIContentScaler))]
public class UIContentScalerEditor : Editor
{
SerializedProperty scaleMode;
SerializedProperty screenMatchMode;
SerializedProperty designResolutionX;
SerializedProperty designResolutionY;
SerializedProperty fallbackScreenDPI;
SerializedProperty defaultSpriteDPI;
SerializedProperty constantScaleFactor;
SerializedProperty ignoreOrientation;
string[] propertyToExclude;
void OnEnable()
{
scaleMode = serializedObject.FindProperty("scaleMode");
screenMatchMode = serializedObject.FindProperty("screenMatchMode");
designResolutionX = serializedObject.FindProperty("designResolutionX");
designResolutionY = serializedObject.FindProperty("designResolutionY");
fallbackScreenDPI = serializedObject.FindProperty("fallbackScreenDPI");
defaultSpriteDPI = serializedObject.FindProperty("defaultSpriteDPI");
constantScaleFactor = serializedObject.FindProperty("constantScaleFactor");
ignoreOrientation = serializedObject.FindProperty("ignoreOrientation");
propertyToExclude = new string[] { "m_Script", "scaleMode", "screenMatchMode", "designResolutionX", "designResolutionY",
"fallbackScreenDPI", "defaultSpriteDPI", "constantScaleFactor", "ignoreOrientation"};
}
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawPropertiesExcluding(serializedObject, propertyToExclude);
EditorGUILayout.PropertyField(scaleMode);
if ((UIContentScaler.ScaleMode)scaleMode.enumValueIndex == UIContentScaler.ScaleMode.ScaleWithScreenSize)
{
EditorGUILayout.PropertyField(designResolutionX);
EditorGUILayout.PropertyField(designResolutionY);
EditorGUILayout.PropertyField(screenMatchMode);
EditorGUILayout.PropertyField(ignoreOrientation);
}
else if ((UIContentScaler.ScaleMode)scaleMode.enumValueIndex == UIContentScaler.ScaleMode.ConstantPhysicalSize)
{
EditorGUILayout.PropertyField(fallbackScreenDPI);
EditorGUILayout.PropertyField(defaultSpriteDPI);
}
else
EditorGUILayout.PropertyField(constantScaleFactor);
if (serializedObject.ApplyModifiedProperties())
(target as UIContentScaler).ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 69174d19fa9521b4283e0b8f0e85acc8
timeCreated: 1460480288
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,88 @@
using FairyGUI;
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
namespace FairyGUIEditor
{
/// <summary>
///
/// </summary>
[CustomEditor(typeof(UIPainter))]
public class UIPainterEditor : Editor
{
SerializedProperty packageName;
SerializedProperty componentName;
SerializedProperty renderCamera;
SerializedProperty fairyBatching;
SerializedProperty touchDisabled;
SerializedProperty sortingOrder;
string[] propertyToExclude;
void OnEnable()
{
packageName = serializedObject.FindProperty("packageName");
componentName = serializedObject.FindProperty("componentName");
renderCamera = serializedObject.FindProperty("renderCamera");
fairyBatching = serializedObject.FindProperty("fairyBatching");
touchDisabled = serializedObject.FindProperty("touchDisabled");
sortingOrder = serializedObject.FindProperty("sortingOrder");
propertyToExclude = new string[] { "m_Script", "packageName", "componentName", "packagePath",
"renderCamera", "fairyBatching", "touchDisabled","sortingOrder"
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();
UIPainter panel = target as UIPainter;
DrawPropertiesExcluding(serializedObject, propertyToExclude);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Package Name");
if (GUILayout.Button(packageName.stringValue, "ObjectField"))
EditorWindow.GetWindow<PackagesWindow>(true, "Select a UI Component").SetSelection(packageName.stringValue, componentName.stringValue);
if (GUILayout.Button("Clear", GUILayout.Width(50)))
{
#if UNITY_2018_3_OR_NEWER
bool isPrefab = PrefabUtility.GetPrefabAssetType(panel) != PrefabAssetType.NotAPrefab;
#else
bool isPrefab = PrefabUtility.GetPrefabType(panel) == PrefabType.Prefab;
#endif
panel.SendMessage("OnUpdateSource", new object[] { null, null, null, !isPrefab });
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Component Name");
if (GUILayout.Button(componentName.stringValue, "ObjectField"))
EditorWindow.GetWindow<PackagesWindow>(true, "Select a UI Component").SetSelection(packageName.stringValue, componentName.stringValue);
EditorGUILayout.EndHorizontal();
int oldSortingOrder = panel.sortingOrder;
EditorGUILayout.PropertyField(sortingOrder);
EditorGUILayout.PropertyField(renderCamera);
EditorGUILayout.PropertyField(fairyBatching);
EditorGUILayout.PropertyField(touchDisabled);
if (serializedObject.ApplyModifiedProperties())
{
#if UNITY_2018_3_OR_NEWER
bool isPrefab = PrefabUtility.GetPrefabAssetType(panel) != PrefabAssetType.NotAPrefab;
#else
bool isPrefab = PrefabUtility.GetPrefabType(panel) == PrefabType.Prefab;
#endif
if (!isPrefab)
{
panel.ApplyModifiedProperties(sortingOrder.intValue != oldSortingOrder);
}
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 5cb0f73c030157845aaa7b42a2b8d577
timeCreated: 1461566835
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,157 @@
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
namespace FairyGUIEditor
{
/// <summary>
///
/// </summary>
[CustomEditor(typeof(FairyGUI.UIPanel))]
public class UIPanelEditor : Editor
{
SerializedProperty packageName;
SerializedProperty componentName;
SerializedProperty packagePath;
SerializedProperty renderMode;
SerializedProperty renderCamera;
SerializedProperty sortingOrder;
SerializedProperty position;
SerializedProperty scale;
SerializedProperty rotation;
SerializedProperty fairyBatching;
SerializedProperty fitScreen;
SerializedProperty touchDisabled;
SerializedProperty hitTestMode;
SerializedProperty setNativeChildrenOrder;
string[] propertyToExclude;
void OnEnable()
{
packageName = serializedObject.FindProperty("packageName");
componentName = serializedObject.FindProperty("componentName");
packagePath = serializedObject.FindProperty("packagePath");
renderMode = serializedObject.FindProperty("renderMode");
renderCamera = serializedObject.FindProperty("renderCamera");
sortingOrder = serializedObject.FindProperty("sortingOrder");
position = serializedObject.FindProperty("position");
scale = serializedObject.FindProperty("scale");
rotation = serializedObject.FindProperty("rotation");
fairyBatching = serializedObject.FindProperty("fairyBatching");
fitScreen = serializedObject.FindProperty("fitScreen");
touchDisabled = serializedObject.FindProperty("touchDisabled");
hitTestMode = serializedObject.FindProperty("hitTestMode");
setNativeChildrenOrder = serializedObject.FindProperty("setNativeChildrenOrder");
propertyToExclude = new string[] { "m_Script", "packageName", "componentName", "packagePath", "renderMode",
"renderCamera", "sortingOrder", "position", "scale", "rotation", "fairyBatching", "fitScreen","touchDisabled",
"hitTestMode","cachedUISize","setNativeChildrenOrder"
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();
FairyGUI.UIPanel panel = target as FairyGUI.UIPanel;
DrawPropertiesExcluding(serializedObject, propertyToExclude);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Package Name");
if (GUILayout.Button(packageName.stringValue, "ObjectField"))
EditorWindow.GetWindow<PackagesWindow>(true, "Select a UI Component").SetSelection(packageName.stringValue, componentName.stringValue);
if (GUILayout.Button("Clear", GUILayout.Width(50)))
{
#if UNITY_2018_3_OR_NEWER
bool isPrefab = PrefabUtility.GetPrefabAssetType(panel) != PrefabAssetType.NotAPrefab;
#else
bool isPrefab = PrefabUtility.GetPrefabType(panel) == PrefabType.Prefab;
#endif
panel.SendMessage("OnUpdateSource", new object[] { null, null, null, !isPrefab });
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Component Name");
if (GUILayout.Button(componentName.stringValue, "ObjectField"))
EditorWindow.GetWindow<PackagesWindow>(true, "Select a UI Component").SetSelection(packageName.stringValue, componentName.stringValue);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Package Path");
EditorGUILayout.LabelField(packagePath.stringValue, (GUIStyle)"helpbox");
EditorGUILayout.EndHorizontal();
if (Application.isPlaying)
EditorGUILayout.EnumPopup("Render Mode", panel.container.renderMode);
else
EditorGUILayout.PropertyField(renderMode);
if ((RenderMode)renderMode.enumValueIndex != RenderMode.ScreenSpaceOverlay)
EditorGUILayout.PropertyField(renderCamera);
int oldSortingOrder = panel.sortingOrder;
EditorGUILayout.PropertyField(sortingOrder);
EditorGUILayout.PropertyField(fairyBatching);
EditorGUILayout.PropertyField(hitTestMode);
EditorGUILayout.PropertyField(touchDisabled);
EditorGUILayout.PropertyField(setNativeChildrenOrder);
EditorGUILayout.Separator();
EditorGUILayout.LabelField("UI Transform", (GUIStyle)"OL Title");
EditorGUILayout.Separator();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(position);
EditorGUILayout.PropertyField(rotation);
EditorGUILayout.PropertyField(scale);
EditorGUILayout.Space();
FairyGUI.FitScreen oldFitScreen = (FairyGUI.FitScreen)fitScreen.enumValueIndex;
EditorGUILayout.PropertyField(fitScreen);
if (serializedObject.ApplyModifiedProperties())
{
#if UNITY_2018_3_OR_NEWER
bool isPrefab = PrefabUtility.GetPrefabAssetType(panel) != PrefabAssetType.NotAPrefab;
#else
bool isPrefab = PrefabUtility.GetPrefabType(panel) == PrefabType.Prefab;
#endif
if (!isPrefab)
{
panel.ApplyModifiedProperties(sortingOrder.intValue != oldSortingOrder, (FairyGUI.FitScreen)fitScreen.enumValueIndex != oldFitScreen);
}
}
}
void OnSceneGUI()
{
FairyGUI.UIPanel panel = (target as FairyGUI.UIPanel);
if (panel.container == null)
return;
Vector3 pos = panel.GetUIWorldPosition();
float sizeFactor = HandleUtility.GetHandleSize(pos);
#if UNITY_2022_2_OR_NEWER
Vector3 newPos = Handles.FreeMoveHandle(pos, sizeFactor, Vector3.one, Handles.ArrowHandleCap);
#elif UNITY_2017_1_OR_NEWER
Vector3 newPos = Handles.FreeMoveHandle(pos, Quaternion.identity, sizeFactor, Vector3.one, Handles.ArrowHandleCap);
#else
Vector3 newPos = Handles.FreeMoveHandle(pos, Quaternion.identity, sizeFactor, Vector3.one, Handles.ArrowCap);
#endif
if (newPos != pos)
{
Vector2 v1 = HandleUtility.WorldToGUIPoint(pos);
Vector2 v2 = HandleUtility.WorldToGUIPoint(newPos);
Vector3 delta = v2 - v1;
delta.x = (int)delta.x;
delta.y = (int)delta.y;
panel.MoveUI(delta);
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 94949994c6eda08448145f618d0db72f
timeCreated: 1535374215
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7f6a32768faf4764b85c949a38093532
timeCreated: 1743782370

View File

@@ -0,0 +1,808 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RootMotion.FinalIK;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace NBF
{
public class RF4FixPrefab : Editor
{
#region
[MenuItem("Assets/Fix/修复圈", false, 1)]
private static void FixRings()
{
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixRing(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼圈失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixRing(GameObject prefab)
{
var rings = prefab.GetComponent<RodRingAsset>();
if (rings == null)
{
rings = prefab.AddComponent<RodRingAsset>();
}
List<Transform> list = new List<Transform>();
// 遍历所有直接子对象
for (int i = 0; i < prefab.transform.childCount; i++)
{
Transform child = prefab.transform.GetChild(i);
list.Add(child);
}
// rings.rings = list.ToArray();
List<Transform> points = new List<Transform>();
foreach (var tran in list)
{
for (int i = 0; i < tran.childCount; i++)
{
Transform c = tran.GetChild(i);
if (c.name.Contains("Collider"))
{
points.Add(c);
break;
}
}
}
// rings.points = points.ToArray();
List<RodRingNode> saveList = new List<RodRingNode>();
foreach (var node in list)
{
RodRingNode ringNode = new RodRingNode
{
ring = node
};
foreach (var point in points)
{
if (point.parent != node) continue;
ringNode.point = point;
var rig = point.GetComponent<Rigidbody>();
if (rig == null)
{
rig = point.gameObject.AddComponent<Rigidbody>();
}
if (rig != null)
{
rig.useGravity = false;
rig.isKinematic = true;
rig.mass = 1;
}
break;
}
saveList.Add(ringNode);
}
rings.rings = saveList.ToArray();
EditorUtility.SetDirty(prefab);
}
#endregion
#region 竿
//joint_root
[MenuItem("Assets/Fix/修复鱼竿", false, 2)]
private static void FixRods()
{
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixRod(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼竿失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixRod(GameObject prefab)
{
RemoveMissingScriptsFrom(prefab);
var lineRenderer = prefab.GetComponent<LineRenderer>();
if (lineRenderer == null)
{
lineRenderer = prefab.AddComponent<LineRenderer>();
}
lineRenderer.startWidth = 0.001f;
lineRenderer.endWidth = 0.001f;
var rod = prefab.GetComponent<RodAsset>();
if (rod == null)
{
rod = prefab.AddComponent<RodAsset>();
}
rod.lineRenderer = lineRenderer;
rod.root = FindTransformsByNameContainsOnes(prefab.transform, "joint_root");
rod.LeftHandConnector = FindTransformsByNameContainsOnes(prefab.transform, "l_hand_connector");
rod.RightHandConnector = FindTransformsByNameContainsOnes(prefab.transform, "r_hand_connector");
rod.ReelConnector = FindTransformsByNameContainsOnes(prefab.transform, "reel_connector");
rod.gripEnd = FindTransformsByNameContainsOnes(prefab.transform, "grip_end");
var trans = prefab.GetComponentsInChildren<Transform>(true);
List<Transform> joints = new List<Transform>();
List<Transform> rings = new List<Transform>();
foreach (var tran in trans)
{
if (tran == null) continue;
if (tran == rod.root) continue;
if (tran.name.Contains("_RING_"))
{
rings.Add(tran);
}
else if (tran.name.Contains("_joint_"))
{
joints.Add(tran);
}
}
var blancEnd = FindTransformByName(prefab.transform, "blanc_end");
if (blancEnd == null)
{
Debug.LogError($"blanc_end 为空name={prefab.name}");
}
else
{
joints.Add(blancEnd);
}
rod.rings = rings.ToArray();
rod.joints = joints.ToArray();
var ccdIK = prefab.GetComponent<CCDIK>();
if (ccdIK == null)
{
ccdIK = prefab.AddComponent<CCDIK>();
}
var solver = ccdIK.solver;
if (solver != null)
{
solver.maxIterations = 3;
var rootField = solver.GetType().GetField("root",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (rootField != null)
{
rootField.SetValue(solver, prefab.transform);
}
solver.bones = Array.Empty<IKSolver.Bone>();
for (var i = 1; i < rod.joints.Length; i++)
{
solver.AddBone(rod.joints[i]);
}
}
EditorUtility.SetDirty(rod);
EditorUtility.SetDirty(ccdIK);
EditorUtility.SetDirty(prefab);
}
#endregion
#region 线
private static List<AnimationClip> _animationClips;
[MenuItem("Assets/Fix/修复线轴", false, 3)]
private static void FixReels()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixReel(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复线轴失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixReel(GameObject prefab)
{
RemoveMissingScriptsFrom(prefab);
var reel = prefab.GetComponent<ReelAsset>();
if (reel == null)
{
reel = prefab.AddComponent<ReelAsset>();
}
reel.rootConnector = FindTransformsByNameContainsOnes(prefab.transform, "reel_root_connector");
reel.rootCompensator = FindTransformsByNameContainsOnes(prefab.transform, "reel_root_compensator");
reel.lineConnector = FindTransformsByNameContainsOnes(prefab.transform, "line_connector");
reel.lineIntersect = FindTransformsByNameContainsOnes(prefab.transform, "line_intersect");
reel.lineIntersectHelper = reel.lineIntersect.parent;
reel.handle = FindTransformsByNameContainsOnes(prefab.transform, "ik_locator_handle");
reel.handleEnd = reel.handle.parent;
var anim = reel.rootConnector.parent.GetComponent<Animator>();
if (anim == null)
{
anim = reel.rootConnector.parent.gameObject.AddComponent<Animator>();
}
reel.animator = anim;
// var anim = reel.rootConnector.parent.GetComponent<Animation>();
// if (anim == null)
// {
// anim = reel.rootConnector.parent.gameObject.AddComponent<Animation>();
// }
// List<AnimationClip> clips = _animationClips.Where(clip => clip.name.Contains(prefab.name)).ToList();
// foreach (var clip in clips)
// {
// anim.AddClip(clip, clip.name);
// var lowName = clip.name.ToLower();
// if (lowName.Contains("open"))
// {
// reel.openAnimation = clip;
// }
// else if (lowName.Contains("close"))
// {
// reel.closeAnimation = clip;
// }
// else if (lowName.Contains("handle_roll"))
// {
// reel.rollHandleAnimation = clip;
// }
// }
// anim.playAutomatically = true;
// reel.anim = anim;
}
#endregion
#region
[MenuItem("Assets/Fix/修复浮漂", false, 4)]
private static void FixBobbers()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixBobber(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼漂失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixBobber(GameObject prefab)
{
// RemoveMissingScriptsFrom(prefab);
var bobber = prefab.GetComponent<BobberAsset>();
if (bobber == null)
{
bobber = prefab.AddComponent<BobberAsset>();
}
bobber.body = FindTransformsByNameContainsOnes(prefab.transform, "_body");
bobber.stick = FindTransformsByNameContainsOnes(prefab.transform, "_stick");
bobber.topConnector = FindTransformsByNameContainsOnes(prefab.transform, "_topConnector");
bobber.bottomConnector = FindTransformsByNameContainsOnes(prefab.transform, "_bottomConnector");
bobber.waterline = FindTransformsByNameContainsOnes(prefab.transform, "_waterline");
// var boxCollider = prefab.GetComponent<BoxCollider>();
// if (boxCollider != null)
// {
// DestroyImmediate(boxCollider);
// // boxCollider = prefab.AddComponent<BoxCollider>();
// }
//
// boxCollider.center = new Vector3(0, -0.01f, 0);
// boxCollider.size = new Vector3(0.005f, 0.005f, 0.005f);
var rigidbody = prefab.GetComponent<Rigidbody>();
if (rigidbody == null)
{
rigidbody = prefab.AddComponent<Rigidbody>();
}
rigidbody.useGravity = false;
var configurableJoint = prefab.GetComponent<ConfigurableJoint>();
if (configurableJoint == null)
{
configurableJoint = prefab.AddComponent<ConfigurableJoint>();
}
configurableJoint.xMotion = ConfigurableJointMotion.Locked;
configurableJoint.yMotion = ConfigurableJointMotion.Locked;
configurableJoint.zMotion = ConfigurableJointMotion.Locked;
}
#endregion
#region
[MenuItem("Assets/Fix/修复鱼钩", false, 5)]
private static void FixHooks()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixHook(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼钩失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixHook(GameObject prefab)
{
// RemoveMissingScriptsFrom(prefab);
var hook = prefab.GetComponent<HookAsset>();
if (hook == null)
{
hook = prefab.AddComponent<HookAsset>();
}
hook.baitConnector = FindTransformsByNameContainsOnes(prefab.transform, "bait_connector");
var boxCollider = prefab.GetComponent<BoxCollider>();
if (boxCollider == null)
{
boxCollider = prefab.AddComponent<BoxCollider>();
}
boxCollider.center = new Vector3(0, -0.01f, 0);
boxCollider.size = new Vector3(0.005f, 0.005f, 0.005f);
var rigidbody = prefab.GetComponent<Rigidbody>();
if (rigidbody == null)
{
rigidbody = prefab.AddComponent<Rigidbody>();
}
rigidbody.useGravity = false;
var configurableJoint = prefab.GetComponent<ConfigurableJoint>();
if (configurableJoint == null)
{
configurableJoint = prefab.AddComponent<ConfigurableJoint>();
}
configurableJoint.xMotion = ConfigurableJointMotion.Locked;
configurableJoint.yMotion = ConfigurableJointMotion.Locked;
configurableJoint.zMotion = ConfigurableJointMotion.Locked;
}
#endregion
#region
[MenuItem("Assets/Fix/修复鱼饵", false, 6)]
private static void FixBaits()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixBait(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼钩失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixBait(GameObject prefab)
{
var bait = prefab.GetComponent<BaitAsset>();
if (bait == null)
{
bait = prefab.AddComponent<BaitAsset>();
}
bait.hook = FindTransformsByNameContainsOnes(prefab.transform, "_hook");
}
#endregion
#region 仿
[MenuItem("Assets/Fix/修复路亚饵", false, 6)]
private static void FixLures()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixLure(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼钩失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixLure(GameObject prefab)
{
RemoveMissingScriptsFrom(prefab);
var lure = prefab.GetComponent<LureAsset>();
if (lure == null)
{
lure = prefab.AddComponent<LureAsset>();
}
List<Transform> hookPoints = new List<Transform>();
for (int i = 1; i < 5; i++)
{
var hook = FindTransformByName(prefab.transform, $"hook_0{i}");
if (hook == null) break;
hookPoints.Add(hook);
}
lure.hookPoints = hookPoints.ToArray();
// hook_01
}
#endregion
#region
[MenuItem("Assets/Fix/修复鱼", false, 7)]
private static void FixFishs()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixFish(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼钩失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixFish(GameObject prefab)
{
var bait = prefab.GetComponent<FishAsset>();
if (bait == null)
{
bait = prefab.AddComponent<FishAsset>();
}
}
#endregion
#region
private static List<AnimationClip> GetAllClips()
{
List<AnimationClip> list = new List<AnimationClip>();
// 获取项目中所有的AnimationClip
string[] guids = AssetDatabase.FindAssets("t:AnimationClip");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(path);
if (clip != null)
{
list.Add(clip);
}
}
return list;
}
private static string GetPathToParent(Transform currentTransform)
{
if (currentTransform == null || currentTransform.parent == null)
{
return string.Empty; // 如果没有父级,返回空字符串
}
// 递归调用先获取父级的路径然后加上当前Transform的名字
return GetPathToParent(currentTransform.parent) + "/" + currentTransform.name;
}
private static T FindFirstComponentInChildren<T>(GameObject parent) where T : Component
{
// 检查当前对象
T component = parent.GetComponent<T>();
if (component != null)
{
return component;
}
// 递归检查子对象
foreach (Transform child in parent.transform)
{
T result = FindFirstComponentInChildren<T>(child.gameObject);
if (result != null)
{
return result;
}
}
return null;
}
private static Transform FindTransformByName(Transform parent, string name)
{
// 检查当前对象
if (parent.name == name)
{
return parent;
}
// 递归检查子对象
foreach (Transform child in parent)
{
Transform result = FindTransformByName(child, name);
if (result != null)
{
return result;
}
}
return null;
}
/// <summary>
///
/// </summary>
/// <param name="parent"></param>
/// <param name="namePrefix"></param>
/// <returns></returns>
private static List<Transform> FindTransformsByNamePrefix(Transform parent, string namePrefix)
{
List<Transform> result = new List<Transform>();
// 检查当前对象
if (parent.name.StartsWith(namePrefix))
{
result.Add(parent);
}
// 递归检查子对象
foreach (Transform child in parent)
{
result.AddRange(FindTransformsByNamePrefix(child, namePrefix));
}
return result;
}
private static Transform FindTransformsByNameContainsOnes(Transform parent, string nameContains)
{
var trans = FindTransformsByNameContains(parent, nameContains);
if (trans != null && trans.Count > 0)
{
return trans.First();
}
return null;
}
/// <summary>
/// 获取首个包含制定名字的tran
/// </summary>
/// <param name="parent"></param>
/// <param name="nameContains"></param>
/// <returns></returns>
private static List<Transform> FindTransformsByNameContains(Transform parent, string nameContains)
{
List<Transform> result = new List<Transform>();
// 检查当前对象
if (parent.name.Contains(nameContains))
{
result.Add(parent);
}
// 递归检查子对象
foreach (Transform child in parent)
{
result.AddRange(FindTransformsByNameContains(child, nameContains));
}
return result;
}
private static T[] GetSelectPrefab<T>(string ext = ".prefab") where T : Object
{
// 获取当前选中的路径
string selectedPath = GetSelectedFolderPath();
if (string.IsNullOrEmpty(selectedPath))
{
Debug.LogWarning("No folder selected.");
return Array.Empty<T>();
}
List<T> list = new List<T>();
// 获取该文件夹中的所有资产路径
string[] assetGuids = AssetDatabase.FindAssets("", new[] { selectedPath });
foreach (string guid in assetGuids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
// 检查路径是否以 ".prefab" 结尾
if (path.EndsWith(ext))
{
var prefab = AssetDatabase.LoadAssetAtPath<T>(path);
if (prefab != null)
{
list.Add(prefab);
}
}
}
return list.ToArray();
}
/// <summary>
/// 移除missing的脚步
/// </summary>
/// <param name="objects"></param>
/// <returns></returns>
private static int RemoveMissingScriptsFrom(params GameObject[] objects)
{
List<GameObject> forceSave = new();
int removedCounter = 0;
foreach (GameObject current in objects)
{
if (current == null) continue;
int missingCount = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(current);
if (missingCount == 0) continue;
GameObjectUtility.RemoveMonoBehavioursWithMissingScript(current);
EditorUtility.SetDirty(current);
if (EditorUtility.IsPersistent(current) && PrefabUtility.IsAnyPrefabInstanceRoot(current))
forceSave.Add(current);
Debug.Log($"Removed {missingCount} Missing Scripts from {current.gameObject.name}", current);
removedCounter += missingCount;
}
foreach (GameObject o in forceSave) PrefabUtility.SavePrefabAsset(o);
return removedCounter;
}
/// <summary>
/// 获取选中的文件夹路径
/// </summary>
/// <returns></returns>
private static string GetSelectedFolderPath()
{
// 获取当前选中的对象
Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);
if (selection.Length > 0)
{
string path = AssetDatabase.GetAssetPath(selection[0]);
if (AssetDatabase.IsValidFolder(path))
{
return path;
}
}
return null;
}
/// <summary>
/// 在所有子对象中查找名字为childName的对象
/// </summary>
/// <param name="parent"></param>
/// <param name="childName"></param>
/// <returns></returns>
public static Transform FindDeepChild(Transform parent, string childName)
{
Transform result = parent.Find(childName);
if (result != null)
return result;
foreach (Transform child in parent)
{
result = FindDeepChild(child, childName);
if (result != null)
return result;
}
return null;
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d55d4f69aaa14fb2910c88c7230d7273
timeCreated: 1743782400

View File

@@ -0,0 +1,40 @@
// using UnityEditor;
// using UnityEngine;
//
// namespace NBF
// {
// [CustomEditor(typeof(FloatBobberController))]
// public class FloatBobberControllerEditor : Editor
// {
// private FloatBobberController _target;
// void OnEnable()
// {
// _target = target as FloatBobberController;
// // lookAtPoint = serializedObject.FindProperty("lookAtPoint");
// }
//
// public override void OnInspectorGUI()
// {
// base.OnInspectorGUI();
// if (GUILayout.Button("TriggerDownPulse"))
// {
// _target.TriggerDownPulse();
// }
// if (GUILayout.Button("TriggerUpPulse"))
// {
// _target.TriggerUpPulse();
// }
// if (GUILayout.Button("AddFishPull"))
// {
// _target.AddFishPull(0.5f);
// }
// if (GUILayout.Button("AddFishPull"))
// {
// _target.ReleaseFishPull(0.5f);
// }
// // serializedObject.Update();
// // EditorGUILayout.PropertyField(lookAtPoint);
// // serializedObject.ApplyModifiedProperties();
// }
// }
// }

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d2e2de2e2fef459895d6c89eb7b66a34
timeCreated: 1764169703

View File

@@ -0,0 +1,40 @@
// using UnityEditor;
// using UnityEngine;
//
// namespace NBF
// {
// [CustomEditor(typeof(FloatBobberControllerPro))]
// public class FloatBobberControllerProEditor : Editor
// {
// private FloatBobberControllerPro _target;
// void OnEnable()
// {
// _target = target as FloatBobberControllerPro;
// // lookAtPoint = serializedObject.FindProperty("lookAtPoint");
// }
//
// public override void OnInspectorGUI()
// {
// base.OnInspectorGUI();
// if (GUILayout.Button("TriggerDownPulse"))
// {
// _target.TriggerDownPulse();
// }
// if (GUILayout.Button("TriggerUpPulse"))
// {
// _target.TriggerUpPulse();
// }
// if (GUILayout.Button("AddFishPull"))
// {
// _target.AddFishPull(0.5f);
// }
// if (GUILayout.Button("AddFishPull"))
// {
// _target.ReleaseFishPull(0.5f);
// }
// // serializedObject.Update();
// // EditorGUILayout.PropertyField(lookAtPoint);
// // serializedObject.ApplyModifiedProperties();
// }
// }
// }

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a90396d330f942dea5b6ac1aff681614
timeCreated: 1764167227

View File

@@ -0,0 +1,89 @@
using UnityEngine;
using UnityEditor;
public class SimpleImageViewerWindow : EditorWindow
{
private Texture2D image;
private string imagePath = "Assets/ResRaw/ZH/1.png";
private float setWidth = 750f;
private float setHeight = 1334f;
[MenuItem("NBC/ZH/Simple Image Viewer")]
public static void ShowWindow()
{
GetWindow<SimpleImageViewerWindow>("Game");
}
private void OnEnable()
{
// 加载图片
image = AssetDatabase.LoadAssetAtPath<Texture2D>(imagePath);
if (image == null)
{
Debug.LogError($"无法加载图片: {imagePath}");
}
}
private void OnGUI()
{
if (image == null)
{
EditorGUILayout.HelpBox($"图片加载失败: {imagePath}", MessageType.Error);
return;
}
// 计算图片的宽高比
float imageAspect = setWidth / setHeight;
// 获取窗口的可用区域(考虑一些边距)
float availableWidth = position.width;
float availableHeight = position.height;
// 计算自适应尺寸(保持宽高比)
float displayWidth = availableWidth;
float displayHeight = availableWidth / imageAspect;
// 如果高度超过可用高度,则根据高度重新计算
if (displayHeight > availableHeight)
{
displayHeight = availableHeight;
displayWidth = availableHeight * imageAspect;
}
// 计算居中位置
float horizontalSpace = (position.width - displayWidth) / 2;
float verticalSpace = (position.height - displayHeight) / 2;
horizontalSpace = Mathf.Max(0, horizontalSpace);
verticalSpace = Mathf.Max(0, verticalSpace);
// 使用垂直和水平布局来实现居中
GUILayout.BeginVertical();
{
// 顶部空白区域
GUILayout.Space(verticalSpace);
GUILayout.BeginHorizontal();
{
// 左侧空白区域
GUILayout.Space(horizontalSpace);
// 绘制图片
Rect imageRect = GUILayoutUtility.GetRect(displayWidth, displayHeight);
imageRect.width = displayWidth;
imageRect.height = displayHeight;
GUI.DrawTexture(imageRect, image);
// 右侧空白区域
GUILayout.Space(horizontalSpace);
}
GUILayout.EndHorizontal();
// 底部空白区域 - 使用 FlexibleSpace 来确保图片在垂直方向居中
GUILayout.FlexibleSpace();
}
GUILayout.EndVertical();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 80b182f8bcff401aaaad3abc44492871
timeCreated: 1757316527

View File

@@ -0,0 +1,78 @@
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text;
public class MeshAssetObjExporter
{
[MenuItem("Assets/Export Mesh (.asset) to OBJ", true)]
static bool ValidateExport()
{
return Selection.activeObject is Mesh;
}
[MenuItem("Assets/Export Mesh (.asset) to OBJ")]
static void ExportMeshAssetToObj()
{
Mesh mesh = Selection.activeObject as Mesh;
if (mesh == null)
{
Debug.LogWarning("Please select a Mesh .asset file in the Project window.");
return;
}
string path = EditorUtility.SaveFilePanel("Export OBJ", "", mesh.name + ".obj", "obj");
if (string.IsNullOrEmpty(path)) return;
ExportMeshToObj(mesh, path);
Debug.Log("Mesh exported to: " + path);
}
static Vector3 ConvertToBlender(Vector3 v)
{
// Unity坐标 (X, Y, Z) → Blender坐标 (X, Z, -Y)
return new Vector3(v.x, v.z, -v.y);
}
static void ExportMeshToObj(Mesh mesh, string path)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("# Exported from Unity MeshAssetObjExporter");
sb.AppendLine("g " + mesh.name);
// 顶点
foreach (Vector3 v in mesh.vertices)
{
Vector3 vBlender = ConvertToBlender(v);
sb.AppendFormat("v {0} {1} {2}\n", vBlender.x, vBlender.y, vBlender.z);
}
// 法线
foreach (Vector3 n in mesh.normals)
{
Vector3 nBlender = ConvertToBlender(n);
sb.AppendFormat("vn {0} {1} {2}\n", nBlender.x, nBlender.y, nBlender.z);
}
// UV
foreach (Vector2 uv in mesh.uv)
{
sb.AppendFormat("vt {0} {1}\n", uv.x, uv.y);
}
// 面
for (int i = 0; i < mesh.subMeshCount; i++)
{
int[] tris = mesh.GetTriangles(i);
for (int j = 0; j < tris.Length; j += 3)
{
int a = tris[j] + 1;
int b = tris[j + 1] + 1;
int c = tris[j + 2] + 1;
sb.AppendFormat("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n", a, b, c);
}
}
File.WriteAllText(path, sb.ToString());
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b31d593151854995a593d8ed391e8941
timeCreated: 1751770498

View File

@@ -0,0 +1,237 @@
using UnityEditor;
using UnityEngine;
public class MeshToSkinnedMeshConverter : EditorWindow
{
[MenuItem("Tools/Mesh to SkinnedMesh Converter")]
public static void ShowWindow()
{
GetWindow<MeshToSkinnedMeshConverter>("Mesh to SkinnedMesh Converter");
}
private GameObject selectedObject;
private Transform rootBone;
void OnGUI()
{
GUILayout.Label("Convert MeshRenderer to SkinnedMeshRenderer", EditorStyles.boldLabel);
selectedObject = (GameObject)EditorGUILayout.ObjectField("GameObject", selectedObject, typeof(GameObject), true);
rootBone = (Transform)EditorGUILayout.ObjectField("Root Bone", rootBone, typeof(Transform), true);
if (selectedObject != null)
{
MeshRenderer meshRenderer = selectedObject.GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
EditorGUILayout.HelpBox("Selected GameObject does not have a MeshRenderer component.", MessageType.Warning);
}
else
{
if (GUILayout.Button("Convert"))
{
ConvertToSkinnedMeshRenderer();
}
}
}
else
{
EditorGUILayout.HelpBox("Please select a GameObject.", MessageType.Info);
}
}
void ConvertToSkinnedMeshRenderer()
{
if (selectedObject == null) return;
MeshRenderer meshRenderer = selectedObject.GetComponent<MeshRenderer>();
MeshFilter meshFilter = selectedObject.GetComponent<MeshFilter>();
if (meshRenderer != null && meshFilter != null)
{
// 保存原来的网格和材质
Mesh mesh = meshFilter.sharedMesh;
Material[] materials = meshRenderer.sharedMaterials;
// 移除MeshRenderer和MeshFilter组件
DestroyImmediate(meshRenderer);
DestroyImmediate(meshFilter);
// 添加SkinnedMeshRenderer组件
SkinnedMeshRenderer skinnedMeshRenderer = selectedObject.AddComponent<SkinnedMeshRenderer>();
// 设置SkinnedMeshRenderer的网格
skinnedMeshRenderer.sharedMesh = mesh;
// 设置SkinnedMeshRenderer的材质
skinnedMeshRenderer.sharedMaterials = materials;
// 自动查找骨骼
Transform[] bones = FindBones(rootBone);
skinnedMeshRenderer.rootBone = rootBone;
skinnedMeshRenderer.bones = bones;
// 设置绑定姿态
skinnedMeshRenderer.sharedMesh.bindposes = GetBindPoses(bones);
// 设置骨骼权重
skinnedMeshRenderer.sharedMesh.boneWeights = GetBoneWeights(mesh, bones);
Debug.Log("Conversion complete!");
}
else
{
Debug.LogWarning("Selected GameObject does not have a MeshRenderer or MeshFilter component.");
}
}
Transform[] FindBones(Transform root)
{
if (root == null) return new Transform[0];
return root.GetComponentsInChildren<Transform>();
}
Matrix4x4[] GetBindPoses(Transform[] bones)
{
Matrix4x4[] bindPoses = new Matrix4x4[bones.Length];
for (int i = 0; i < bones.Length; i++)
{
bindPoses[i] = bones[i].worldToLocalMatrix * rootBone.localToWorldMatrix;
}
return bindPoses;
}
BoneWeight[] GetBoneWeights(Mesh mesh, Transform[] bones)
{
BoneWeight[] boneWeights = new BoneWeight[mesh.vertexCount];
// 这里假设每个顶点都绑定到第一个骨骼上权重为1
for (int i = 0; i < mesh.vertexCount; i++)
{
boneWeights[i].boneIndex0 = 0;
boneWeights[i].weight0 = 1.0f;
}
// 如果你的模型有复杂的骨骼权重分布,可以在这里实现
// 例如:
// for (int i = 0; i < mesh.vertexCount; i++)
// {
// boneWeights[i].boneIndex0 = ...;
// boneWeights[i].weight0 = ...;
// boneWeights[i].boneIndex1 = ...;
// boneWeights[i].weight1 = ...;
// boneWeights[i].boneIndex2 = ...;
// boneWeights[i].weight2 = ...;
// boneWeights[i].boneIndex3 = ...;
// boneWeights[i].weight3 = ...;
// }
return boneWeights;
}
}
// using System.Collections.Generic;
// using UnityEditor;
// using UnityEngine;
//
// public class MeshToSkinnedMeshConverter : EditorWindow
// {
// [MenuItem("Tools/Mesh to SkinnedMesh Converter")]
// public static void ShowWindow()
// {
// GetWindow<MeshToSkinnedMeshConverter>("Mesh to SkinnedMesh Converter");
// }
//
// private GameObject selectedObject;
// private Transform rootBone;
// private Transform[] bones;
//
// void OnGUI()
// {
// GUILayout.Label("Convert MeshRenderer to SkinnedMeshRenderer", EditorStyles.boldLabel);
//
// selectedObject =
// (GameObject)EditorGUILayout.ObjectField("GameObject", selectedObject, typeof(GameObject), true);
// rootBone = (Transform)EditorGUILayout.ObjectField("Root Bone", rootBone, typeof(Transform), true);
//
// if (selectedObject != null)
// {
// MeshRenderer meshRenderer = selectedObject.GetComponent<MeshRenderer>();
// if (meshRenderer == null)
// {
// EditorGUILayout.HelpBox("Selected GameObject does not have a MeshRenderer component.",
// MessageType.Warning);
// }
// else
// {
// if (GUILayout.Button("Convert"))
// {
// ConvertToSkinnedMeshRenderer();
// }
// }
// }
// else
// {
// EditorGUILayout.HelpBox("Please select a GameObject.", MessageType.Info);
// }
// }
//
// void ConvertToSkinnedMeshRenderer()
// {
// if (selectedObject == null) return;
//
// MeshRenderer meshRenderer = selectedObject.GetComponent<MeshRenderer>();
// MeshFilter meshFilter = selectedObject.GetComponent<MeshFilter>();
//
// if (meshRenderer != null && meshFilter != null)
// {
// // 保存原来的网格和材质
// Mesh mesh = meshFilter.sharedMesh;
// Material[] materials = meshRenderer.sharedMaterials;
//
// // 移除MeshRenderer和MeshFilter组件
// DestroyImmediate(meshRenderer);
// DestroyImmediate(meshFilter);
//
// // 添加SkinnedMeshRenderer组件
// SkinnedMeshRenderer skinnedMeshRenderer = selectedObject.AddComponent<SkinnedMeshRenderer>();
//
// // 设置SkinnedMeshRenderer的网格
// skinnedMeshRenderer.sharedMesh = mesh;
//
// // 设置SkinnedMeshRenderer的材质
// skinnedMeshRenderer.sharedMaterials = materials;
//
// // 自动查找骨骼
// List<Transform> bonesList = new List<Transform>();
// GetRodBones(rootBone.transform, bonesList);
// skinnedMeshRenderer.rootBone = rootBone;
// skinnedMeshRenderer.bones = bonesList.ToArray();
//
// Debug.Log("Conversion complete!");
// }
// else
// {
// Debug.LogWarning("Selected GameObject does not have a MeshRenderer or MeshFilter component.");
// }
// }
//
// private static void GetRodBones(Transform parent, List<Transform> list)
// {
// if (parent.childCount < 1) return;
// foreach (Transform child in parent)
// {
// if (child.name.StartsWith("rod"))
// {
// list.Add(child);
// }
//
// if (child.childCount > 0)
// {
// GetRodBones(child, list);
// }
// }
// }
// }

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ad60a9b58ae14a4c8c2d5be59e01bcb4
timeCreated: 1716886501

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 64b3d51f8cb04af485e1a07f8a6e15a5
timeCreated: 1750822352

View File

@@ -0,0 +1,13 @@
using UnityEditor;
namespace NBF
{
public class ModelViewEditWindow : EditorWindow
{
[MenuItem("NBC/工具/模型预览&Icon编辑")]
public static void ShowWindow()
{
GetWindow<RuntimePreviewEditor>("模型预览");
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 792c7ab2386446f9b3bbc86da9c90989
timeCreated: 1761634153

View File

@@ -0,0 +1,389 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using NBC;
using NBF;
public class RuntimePreviewEditor : EditorWindow
{
// 运行时实例引用
private GameObject runtimeInstance;
private PreviewableAsset runtimePreviewableAsset;
// 预制体列表
private List<GameObject> prefabList = new List<GameObject>();
private int selectedPrefabIndex = -1;
private Vector2 scrollPosition;
// 预览控制
private bool isPreviewing = false;
private PreviewPanel _previewPanel;
[MenuItem("Tools/Runtime Preview Editor")]
public static void ShowWindow()
{
GetWindow<RuntimePreviewEditor>("Runtime Preview");
}
private void OnEnable()
{
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
}
private void OnDisable()
{
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
ClearRuntimeInstance();
}
private void OnPlayModeStateChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.ExitingPlayMode)
{
ClearRuntimeInstance();
isPreviewing = false;
}
}
private void RefreshPrefabList()
{
Debug.LogError("重新加载所有预制体==");
prefabList.Clear();
string[] guids = AssetDatabase.FindAssets("t:Prefab");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (prefab.GetComponent<PreviewableAsset>() != null)
{
prefabList.Add(prefab);
}
}
}
private void OnGUI()
{
EditorGUILayout.BeginHorizontal();
// 左侧预制体列表
DrawPrefabList();
// 右侧预览和操作区域
DrawPreviewArea();
EditorGUILayout.EndHorizontal();
}
private void DrawPrefabList()
{
EditorGUILayout.BeginVertical(GUILayout.Width(250));
EditorGUILayout.LabelField("Available Prefabs", EditorStyles.boldLabel);
EditorGUILayout.Space();
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
for (int i = 0; i < prefabList.Count; i++)
{
bool isSelected = i == selectedPrefabIndex;
if (GUILayout.Toggle(isSelected, prefabList[i].name, "Button"))
{
if (!isSelected)
{
selectedPrefabIndex = i;
if (Application.isPlaying)
{
LoadRuntimeInstance();
}
}
}
}
EditorGUILayout.EndScrollView();
if (GUILayout.Button("Refresh List"))
{
RefreshPrefabList();
}
EditorGUILayout.EndVertical();
}
private void DrawPreviewArea()
{
EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true));
if (!Application.isPlaying)
{
EditorGUILayout.HelpBox("运行模式才可以编辑.", MessageType.Info);
EditorGUILayout.EndVertical();
return;
}
if (selectedPrefabIndex == -1)
{
EditorGUILayout.HelpBox("未选中预制体", MessageType.Info);
EditorGUILayout.EndVertical();
return;
}
GUILayout.BeginHorizontal();
if (GUILayout.Button("上一个"))
{
if (selectedPrefabIndex > 0)
{
selectedPrefabIndex--;
RefreshRuntimeInstance();
// EnsureSelectionVisible();
}
}
GUILayout.Space(20);
if (GUILayout.Button("下一个"))
{
if (selectedPrefabIndex < prefabList.Count - 1)
{
selectedPrefabIndex++;
RefreshRuntimeInstance();
// EnsureSelectionVisible();
}
}
GUILayout.EndHorizontal();
var selectedPrefab = prefabList[selectedPrefabIndex];
EditorGUILayout.LabelField("当前预览: " + selectedPrefab.name, EditorStyles.boldLabel);
// 预览控制按钮
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(isPreviewing ? "停止预览" : "开始预览"))
{
TogglePreview();
}
if (isPreviewing && GUILayout.Button("刷新实例"))
{
RefreshRuntimeInstance();
}
EditorGUILayout.EndHorizontal();
// 运行时实例预览和编辑
if (isPreviewing && runtimeInstance != null && runtimePreviewableAsset)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Transform Properties", EditorStyles.boldLabel);
// 记录变化开始
EditorGUI.BeginChangeCheck();
// 编辑Transform
var newPosition = EditorGUILayout.Vector3Field("位置", runtimeInstance.transform.localPosition);
var newRotation = EditorGUILayout.Vector3Field("旋转", runtimeInstance.transform.parent.localEulerAngles);
var newScale = EditorGUILayout.Vector3Field("形变", runtimeInstance.transform.localScale);
// var canZoom = EditorGUILayout.Toggle("允许缩放", runtimePreviewableAsset.canZoom);
// if (canZoom)
// {
// runtimePreviewableAsset.zoom = EditorGUILayout.Vector3Field("放大缩小配置", runtimePreviewableAsset.zoom);
// }
//
// var canPan = EditorGUILayout.Toggle("允许拖动", runtimePreviewableAsset.canPan);
// if (canPan)
// {
// runtimePreviewableAsset.pan = EditorGUILayout.RectField("拖动配置", runtimePreviewableAsset.pan);
// }
//
// // 应用Transform修改
// if (EditorGUI.EndChangeCheck())
// {
// runtimeInstance.transform.localPosition = new Vector3(newPosition.x, newPosition.y, 0);
// runtimeInstance.transform.parent.localEulerAngles = newRotation;
// runtimeInstance.transform.localScale = newScale;
//
// runtimePreviewableAsset.position = new Vector3(newPosition.x, newPosition.y, 0);
// runtimePreviewableAsset.rotation = newRotation;
// runtimePreviewableAsset.scale = newScale;
// runtimePreviewableAsset.canZoom = canZoom;
// runtimePreviewableAsset.canPan = canPan;
//
//
// var pos = runtimeInstance.transform.parent.localPosition;
// if (canZoom)
// {
// if (!Mathf.Approximately(pos.z, runtimePreviewableAsset.zoom.z))
// {
// runtimeInstance.transform.parent.localPosition =
// new Vector3(pos.x, pos.y, runtimePreviewableAsset.zoom.z);
// }
// }
// else
// {
// runtimeInstance.transform.parent.localPosition = new Vector3(pos.x, pos.y, 0);
// }
//
// // if (canZoom)
// // {
// // if (!Mathf.Approximately(runtimeInstance.transform.localPosition.z,
// // runtimePreviewableAsset.zoom.z))
// // {
// // var pos = runtimeInstance.transform.parent.localPosition;
// // runtimeInstance.transform.parent.localPosition =
// // new Vector3(pos.x, pos.y, runtimePreviewableAsset.zoom.z);
// // }
// // }
// // else
// // {
// // runtimeInstance.transform.parent.localPosition = Vector3.zero;
// // }
// }
EditorGUILayout.Space();
// 保存到预制体按钮
if (GUILayout.Button("保存到预制体", GUILayout.Height(30)))
{
SaveChangesToPrefab();
}
if (GUILayout.Button("生成ICON", GUILayout.Height(30)))
{
// SaveChangesToPrefab();
}
}
EditorGUILayout.EndVertical();
}
private void TogglePreview()
{
isPreviewing = !isPreviewing;
if (isPreviewing)
{
_previewPanel = UI.Inst.GetUI<PreviewPanel>();
if (_previewPanel == null)
{
isPreviewing = false;
Debug.LogError("显示UI面包未打开");
}
}
if (isPreviewing)
{
LoadRuntimeInstance();
}
else
{
ClearRuntimeInstance();
}
}
private void LoadRuntimeInstance()
{
ClearRuntimeInstance();
if (selectedPrefabIndex == -1 || !Application.isPlaying) return;
var prefab = prefabList[selectedPrefabIndex];
// 调用自定义实例化方法
// runtimeInstance = Instantiate(prefab);
// runtimeInstance.hideFlags = HideFlags.DontSave;
if (_previewPanel == null) return;
// runtimeInstance = _previewPanel.LoadModel(prefab);
runtimeInstance.hideFlags = HideFlags.DontSave;
if (runtimeInstance != null)
{
runtimePreviewableAsset = runtimeInstance.GetComponent<PreviewableAsset>();
Selection.activeGameObject = runtimeInstance;
}
}
private void RefreshRuntimeInstance()
{
if (selectedPrefabIndex == -1 || !Application.isPlaying) return;
ClearRuntimeInstance();
LoadRuntimeInstance();
}
private void SaveChangesToPrefab()
{
if (selectedPrefabIndex == -1 || runtimeInstance == null) return;
var prefab = prefabList[selectedPrefabIndex];
var previewableAsset = prefab.GetComponent<PreviewableAsset>();
if (previewableAsset && runtimePreviewableAsset)
{
// previewableAsset.position = runtimePreviewableAsset.position;
// previewableAsset.rotation = runtimePreviewableAsset.rotation;
// previewableAsset.scale = runtimePreviewableAsset.scale;
// previewableAsset.canPan = runtimePreviewableAsset.canPan;
// previewableAsset.canZoom = runtimePreviewableAsset.canZoom;
// previewableAsset.zoom = runtimePreviewableAsset.zoom;
// previewableAsset.pan = runtimePreviewableAsset.pan;
}
EditorUtility.SetDirty(prefab);
AssetDatabase.Refresh();
// // 默认实现 - 直接修改预制体
// PrefabUtility.SaveAsPrefabAsset(runtimeInstance, AssetDatabase.GetAssetPath(prefab));
// AssetDatabase.Refresh();
Debug.Log("Changes saved to prefab: " + prefab.name);
}
private void ClearRuntimeInstance()
{
if (runtimeInstance != null)
{
if (Application.isPlaying)
{
Destroy(runtimeInstance);
}
else
{
DestroyImmediate(runtimeInstance);
}
}
runtimeInstance = null;
runtimePreviewableAsset = null;
}
// // 确保选中项在可视区域内
// private void EnsureSelectionVisible()
// {
// // 计算选中项的大概位置
// float itemHeight = 24; // 每个列表项的大约高度
// float visibleHeight = position.height - 100; // 可视区域的大约高度
//
// // 计算选中项应该在的滚动位置范围
// float targetMin = selectedPrefabIndex * itemHeight;
// float targetMax = targetMin + itemHeight;
//
// // 调整滚动位置
// if (scrollPosition.y > targetMin)
// {
// scrollPosition.y = targetMin;
// }
// else if (scrollPosition.y + visibleHeight < targetMax)
// {
// scrollPosition.y = targetMax - visibleHeight;
// }
//
// // 重绘界面
// Repaint();
// }
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9fe1f9c26314412880e299b87d998083
timeCreated: 1750822614

View File

@@ -0,0 +1,110 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
public class RemoveMissingScripts
{
[MenuItem("Tools/Remove Missing Scripts/From Selected Objects in Hierarchy")]
private static void RemoveMissingScriptsFromSelection()
{
// 获取选中的对象
GameObject[] selectedObjects = Selection.gameObjects;
if (selectedObjects.Length == 0)
{
Debug.LogWarning("No objects selected in Hierarchy.");
return;
}
int totalRemoved = 0;
// 遍历所有选中的对象
foreach (GameObject go in selectedObjects)
{
// 包括所有子对象
int removed = RemoveMissingScriptsRecursively(go);
totalRemoved += removed;
Debug.Log($"Removed {removed} missing scripts from {go.name} and its children.");
}
Debug.Log($"Total removed missing scripts: {totalRemoved}");
}
[MenuItem("Tools/Remove Missing Scripts/From Prefabs in Selected Folder")]
private static void RemoveMissingScriptsFromPrefabsInFolder()
{
// 获取选中的文件夹
string[] selectedFolderGUIDs = Selection.assetGUIDs;
if (selectedFolderGUIDs.Length == 0)
{
Debug.LogWarning("No folder selected in Project window.");
return;
}
string folderPath = AssetDatabase.GUIDToAssetPath(selectedFolderGUIDs[0]);
if (!AssetDatabase.IsValidFolder(folderPath))
{
Debug.LogWarning("Selected asset is not a folder.");
return;
}
// 查找所有预制件
string[] prefabPaths = Directory.GetFiles(folderPath, "*.prefab", SearchOption.AllDirectories);
if (prefabPaths.Length == 0)
{
Debug.LogWarning("No prefabs found in selected folder.");
return;
}
int totalRemoved = 0;
int processedPrefabs = 0;
// 处理每个预制件
foreach (string path in prefabPaths)
{
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (prefab != null)
{
// 创建预制件的实例
GameObject instance = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
// 移除缺失脚本
int removed = RemoveMissingScriptsRecursively(instance);
totalRemoved += removed;
if (removed > 0)
{
// 应用修改到预制件
PrefabUtility.SaveAsPrefabAsset(instance, path);
Debug.Log($"Removed {removed} missing scripts from prefab: {path}");
}
// 销毁实例
Object.DestroyImmediate(instance);
processedPrefabs++;
}
}
Debug.Log($"Processed {processedPrefabs} prefabs. Total removed missing scripts: {totalRemoved}");
}
private static int RemoveMissingScriptsRecursively(GameObject gameObject)
{
int removedCount = 0;
// 处理当前对象
removedCount += GameObjectUtility.RemoveMonoBehavioursWithMissingScript(gameObject);
// 递归处理所有子对象
foreach (Transform child in gameObject.transform)
{
removedCount += RemoveMissingScriptsRecursively(child.gameObject);
}
return removedCount;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 28ee8e197e8248988e0e92d2110a7212
timeCreated: 1746242929

View File

@@ -0,0 +1,40 @@
using UnityEngine;
using UnityEditor;
public class RemoveMissingScriptsTool : MonoBehaviour
{
[MenuItem("Tools/Remove Missing Scripts")]
private static void RemoveAllMissingScripts()
{
// 计数器,用来记录删除了多少 missing script
int missingScriptCount = 0;
// 获取场景中所有的 GameObject
GameObject[] allGameObjects = FindObjectsOfType<GameObject>();
// 遍历每个GameObject
foreach (GameObject go in allGameObjects)
{
// 找到GameObject上所有的组件
Component[] components = go.GetComponents<Component>();
// 创建一个临时数组来存储组件
for (int i = 0; i < components.Length; i++)
{
if (components[i] == null)
{
// 发现missing script删除它
Undo.RegisterCompleteObjectUndo(go, "Remove Missing Scripts"); // 注册撤销操作
GameObjectUtility.RemoveMonoBehavioursWithMissingScript(go); // 删除 missing script
missingScriptCount++;
}
}
}
// 输出删除结果
Debug.Log($"Removed {missingScriptCount} missing scripts from the scene.");
// 提示用户删除成功
EditorUtility.DisplayDialog("Missing Scripts Removed", $"Removed {missingScriptCount} missing scripts from the scene.", "OK");
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5af09e9232b44575990e7962843fba61
timeCreated: 1729655037

View File

@@ -0,0 +1,152 @@
using UnityEngine;
using UnityEditor;
public class ReplaceStandardShaderWithURP : Editor
{
[MenuItem("Tools/一键转换Standard为URP材质")]
private static void ReplaceShadersInSelectedMaterials()
{
Material[] selectedMaterials = Selection.GetFiltered<Material>(SelectionMode.Assets);
if (selectedMaterials.Length == 0)
{
Debug.LogWarning("No materials selected. Please select materials in the Project window.");
return;
}
int replacedCount = 0;
foreach (Material material in selectedMaterials)
{
if (material.shader.name == "Standard" || material.shader.name == "Standard (Specular setup)")
{
// 保存原有属性
Texture albedoTexture = material.GetTexture("_MainTex");
Color albedoColor = material.GetColor("_Color");
Texture metallicMap = material.GetTexture("_MetallicGlossMap");
float metallic = material.GetFloat("_Metallic");
float smoothness = material.GetFloat("_Glossiness");
Texture normalMap = material.GetTexture("_BumpMap");
Texture emissionMap = material.GetTexture("_EmissionMap");
Color emissionColor = material.GetColor("_EmissionColor");
Texture occlusionMap = material.GetTexture("_OcclusionMap");
// 替换Shader
material.shader = Shader.Find("Universal Render Pipeline/Lit");
// 转换Albedo到BaseMap
if (albedoTexture != null)
{
material.SetTexture("_BaseMap", albedoTexture);
// 确保纹理导入设置正确
SetTextureImportSettings(albedoTexture);
}
material.SetColor("_BaseColor", albedoColor);
// 转换金属度和平滑度
if (metallicMap != null)
{
material.SetTexture("_MetallicGlossMap", metallicMap);
SetTextureImportSettings(metallicMap);
}
else
{
material.SetFloat("_Metallic", metallic);
}
material.SetFloat("_Smoothness", smoothness);
// 转换法线贴图
if (normalMap != null)
{
material.SetTexture("_BumpMap", normalMap);
SetTextureImportSettings(normalMap, true);
material.SetFloat("_BumpScale", 1.0f); // URP默认使用1.0的比例
}
// 转换自发光
if (emissionMap != null)
{
material.SetTexture("_EmissionMap", emissionMap);
material.SetColor("_EmissionColor", emissionColor);
material.EnableKeyword("_EMISSION");
SetTextureImportSettings(emissionMap);
}
// 转换环境光遮蔽
if (occlusionMap != null)
{
material.SetTexture("_OcclusionMap", occlusionMap);
SetTextureImportSettings(occlusionMap);
}
EditorUtility.SetDirty(material);
replacedCount++;
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"Replaced {replacedCount} materials with URP Lit shader.");
}
private static void SetTextureImportSettings(Texture texture, bool isNormalMap = false)
{
string path = AssetDatabase.GetAssetPath(texture);
TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
if (importer != null)
{
importer.sRGBTexture = !isNormalMap; // 法线贴图应该禁用sRGB
importer.textureType = isNormalMap ? TextureImporterType.NormalMap : TextureImporterType.Default;
importer.mipmapEnabled = true;
importer.SaveAndReimport();
}
}
}
// public class ReplaceStandardShaderWithURP : Editor
// {
// [MenuItem("Tools/Replace Standard Shader with URP")]
// private static void ReplaceShadersInSelectedMaterials()
// {
// // 获取选中的材质文件
// Material[] selectedMaterials = Selection.GetFiltered<Material>(SelectionMode.Assets);
//
// if (selectedMaterials.Length == 0)
// {
// Debug.LogWarning("No materials selected. Please select materials in the Project window.");
// return;
// }
//
// int replacedCount = 0;
//
// foreach (Material material in selectedMaterials)
// {
// if (material.shader.name == "Standard" || material.shader.name == "Standard (Specular setup)")
// {
// // 保存Albedo贴图
// Texture albedoTexture = material.GetTexture("_MainTex");
//
// // 替换Shader为Universal Render Pipeline/Lit
// material.shader = Shader.Find("Universal Render Pipeline/Lit");
//
// // 将保存的Albedo贴图赋值给Base Map
// if (albedoTexture != null)
// {
// material.SetTexture("_BaseMap", albedoTexture);
// }
//
// // 保存材质
// EditorUtility.SetDirty(material);
// replacedCount++;
// }
// }
//
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
//
// Debug.Log($"Replaced {replacedCount} materials with URP Lit shader.");
// }
// }

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 69f745013fe24bf8b861acc1bfd99266
timeCreated: 1745409560

View File

@@ -0,0 +1,28 @@
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(Rope))]
public class RopeFishLineEditor : Editor
{
private Rope _target;
void OnEnable()
{
_target = target as Rope;
// lookAtPoint = serializedObject.FindProperty("lookAtPoint");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("打印总长度"))
{
Debug.Log($"总长度={_target.GetCurrentLength()} 目标长度={_target.GetTargetLength()}");
}
// serializedObject.Update();
// EditorGUILayout.PropertyField(lookAtPoint);
// serializedObject.ApplyModifiedProperties();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f24add4ba0ae4e76acd98c4a5512c366
timeCreated: 1771850618

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 63016c524b454431b06d891415ccdf5e
timeCreated: 1767354854

View File

@@ -0,0 +1,21 @@
using UnityEditor;
namespace NBF
{
[CustomEditor(typeof(PlayerAnimator))]
public class PlayerAnimatorEditor : Editor
{
private PlayerAnimator _target;
void OnEnable()
{
_target = target as PlayerAnimator;
// lookAtPoint = serializedObject.FindProperty("lookAtPoint");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 03298da249bf4d0d86c372beb4d5dc48
timeCreated: 1767354859

View File

@@ -0,0 +1,26 @@
using UnityEditor;
using UnityEngine;
namespace NBF
{
[CustomEditor(typeof(UIBlur))]
public class UIBlurEditor : Editor
{
private UIBlur _target;
void OnEnable()
{
_target = target as UIBlur;
// lookAtPoint = serializedObject.FindProperty("lookAtPoint");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("Blur"))
{
_target.CaptureAndBlurOnce();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ebaa0f203943458688dac255c2ea6441
timeCreated: 1770124598

View File

@@ -0,0 +1,52 @@
using System.IO;
using UnityEditor;
using UnityEngine;
namespace NBF
{
public static class TestEditorUtil
{
[MenuItem("Assets/修改替换材质", false, 1)]
private static void ReplaceShadersInSelectedFolder()
{
// 获取选中的材质文件
Material[] selectedMaterials = Selection.GetFiltered<Material>(SelectionMode.Assets);
if (selectedMaterials.Length == 0)
{
Debug.LogWarning("No materials selected. Please select materials in the Project window.");
return;
}
int replacedCount = 0;
foreach (Material material in selectedMaterials)
{
if (material.shader.name == "Standard")
{
// 保存Albedo贴图
Texture albedoTexture = material.GetTexture("_MainTex");
// 替换Shader为Universal Render Pipeline/Lit
material.shader = Shader.Find("Universal Render Pipeline/Lit");
// 将保存的Albedo贴图赋值给Base Map
if (albedoTexture != null)
{
material.SetTexture("_BaseMap", albedoTexture);
}
// 保存材质
EditorUtility.SetDirty(material);
replacedCount++;
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"Replaced {replacedCount} materials with URP Lit shader.");
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 478469c8975248bc84312e8d7955fff5
timeCreated: 1742652567

View File

@@ -0,0 +1,145 @@
using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.Video;
using Object = UnityEngine.Object;
namespace NBF
{
public class ZHWindow : EditorWindow
{
[MenuItem("Window/ZH窗口")]
public static void ShowWindow()
{
GetWindow<ZHWindow>("Scene - ZH");
}
private bool _isInitialized;
private VideoPlayer _videoPlayer;
private RenderTexture _renderTexture;
private long _lastInitTime;
private int _videoIndex = 1;
private void OnEnable()
{
InitializePlayer();
// 注册更新回调
EditorApplication.update += OnEditorUpdate;
}
private void InitializePlayer()
{
if (_isInitialized) return;
_lastInitTime = DateTimeOffset.Now.ToUnixTimeSeconds();
var obj = GameObject.Find("ZHVideoPlayer");
if (obj == null) return;
_videoPlayer = GameObject.Find("ZHVideoPlayer").GetComponent<VideoPlayer>();
_videoPlayer.isLooping = true;
_renderTexture = _videoPlayer.targetTexture;
// 设置 RenderTexture
// _renderTexture = new RenderTexture(408, 720, 0);
_videoPlayer.renderMode = VideoRenderMode.RenderTexture;
// _videoPlayer.targetTexture = _renderTexture;
// _videoPlayer.playbackSpeed = 0.5f;
// 加载视频
string videoPath = $"ResRaw/Test/video{_videoIndex}.mp4"; // 修改为你的视频路径
var path = System.IO.Path.Combine(Application.dataPath, videoPath);
_videoPlayer.url = path;
_videoPlayer.Prepare();
_videoPlayer.Play();
_isInitialized = true;
_videoIndex++;
if (_videoIndex > 8)
{
_videoIndex = 1;
}
}
private void OnEditorUpdate()
{
if (_videoPlayer != null && _videoPlayer.isPrepared)
{
Repaint();
}
}
private void OnGUI()
{
var currentTime = DateTimeOffset.Now.ToUnixTimeSeconds();
if (currentTime - _lastInitTime > 30)
{
_isInitialized = false;
}
if (!_isInitialized)
{
// EditorGUILayout.HelpBox(
// "Video Player is not initialized. Please ensure the video file is properly set.",
// MessageType.Warning);
InitializePlayer();
return;
}
if (_videoPlayer == null || _renderTexture == null)
{
ReleaseResources();
InitializePlayer();
return;
}
if (!_videoPlayer.isPlaying)
{
_videoPlayer.Play();
}
if (_renderTexture != null)
{
float width = position.width;
float height = position.height;
// 计算视频显示比例
float targetAspect = (float)_renderTexture.width / _renderTexture.height;
float windowAspect = width / height;
float displayWidth, displayHeight;
if (windowAspect > targetAspect)
{
displayHeight = height;
displayWidth = height * targetAspect;
}
else
{
displayWidth = width;
displayHeight = width / targetAspect;
}
// 居中显示视频
float offsetX = (width - displayWidth) / 2f;
float offsetY = (height - displayHeight) / 2f;
GUI.DrawTexture(new Rect(offsetX, offsetY, displayWidth, displayHeight), _renderTexture);
}
}
private void OnDisable()
{
ReleaseResources();
// 移除更新回调
EditorApplication.update -= OnEditorUpdate;
}
private void ReleaseResources()
{
if (_videoPlayer != null)
{
_videoPlayer.Stop();
// DestroyImmediate(_videoPlayer.gameObject);
_videoPlayer = null;
}
_isInitialized = false;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 244825ec57ad4537a0834858490d694e
timeCreated: 1735789432