首次提交
This commit is contained in:
267
Assets/Scripts/Editor/AnimatorParameterAnalyzer.cs
Normal file
267
Assets/Scripts/Editor/AnimatorParameterAnalyzer.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/AnimatorParameterAnalyzer.cs.meta
Normal file
3
Assets/Scripts/Editor/AnimatorParameterAnalyzer.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8f6792dcd794f6792af088b51bc6fbc
|
||||
timeCreated: 1743518603
|
||||
107
Assets/Scripts/Editor/AnimatorParametersGenerator.cs
Normal file
107
Assets/Scripts/Editor/AnimatorParametersGenerator.cs
Normal 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"
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7f538499bd74a61b5b6396b843e79da
|
||||
timeCreated: 1734175675
|
||||
3
Assets/Scripts/Editor/Builder.meta
Normal file
3
Assets/Scripts/Editor/Builder.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bef91460c2ca4315a394b30f54d62838
|
||||
timeCreated: 1735888145
|
||||
3
Assets/Scripts/Editor/Builder/Attributes.meta
Normal file
3
Assets/Scripts/Editor/Builder/Attributes.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fbc716d15a94418194d49806f957e327
|
||||
timeCreated: 1735888291
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41d2cb56d8994cc6ae893a33f19b3e76
|
||||
timeCreated: 1735888293
|
||||
10
Assets/Scripts/Editor/Builder/BuildContext.cs
Normal file
10
Assets/Scripts/Editor/Builder/BuildContext.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace NBF
|
||||
{
|
||||
public class BuildContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 版本号
|
||||
/// </summary>
|
||||
public string Ver;
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Builder/BuildContext.cs.meta
Normal file
3
Assets/Scripts/Editor/Builder/BuildContext.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a97905bd3c747f9ba3c6d1df484568c
|
||||
timeCreated: 1735888273
|
||||
166
Assets/Scripts/Editor/Builder/Builder.cs
Normal file
166
Assets/Scripts/Editor/Builder/Builder.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Builder/Builder.cs.meta
Normal file
3
Assets/Scripts/Editor/Builder/Builder.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a11d1aa017534b6195db306f958f5257
|
||||
timeCreated: 1735888155
|
||||
170
Assets/Scripts/Editor/Builder/BuilderWindow.cs
Normal file
170
Assets/Scripts/Editor/Builder/BuilderWindow.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Builder/BuilderWindow.cs.meta
Normal file
3
Assets/Scripts/Editor/Builder/BuilderWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89fa3eb5ebcd4df692e9a2a19815ae8b
|
||||
timeCreated: 1735890628
|
||||
3
Assets/Scripts/Editor/Builder/Def.meta
Normal file
3
Assets/Scripts/Editor/Builder/Def.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 153e12cafc9f4d86bbde017079fa5bf5
|
||||
timeCreated: 1735888397
|
||||
13
Assets/Scripts/Editor/Builder/Def/BuildTaskId.cs
Normal file
13
Assets/Scripts/Editor/Builder/Def/BuildTaskId.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Builder/Def/BuildTaskId.cs.meta
Normal file
3
Assets/Scripts/Editor/Builder/Def/BuildTaskId.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c621b4acadc844a6ae65dc15916355fc
|
||||
timeCreated: 1735888399
|
||||
3
Assets/Scripts/Editor/Builder/Tasks.meta
Normal file
3
Assets/Scripts/Editor/Builder/Tasks.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5bff86240194f81882a09430e3e9523
|
||||
timeCreated: 1735888252
|
||||
7
Assets/Scripts/Editor/Builder/Tasks/BaseBuildTask.cs
Normal file
7
Assets/Scripts/Editor/Builder/Tasks/BaseBuildTask.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace NBF
|
||||
{
|
||||
public abstract class BaseBuildTask
|
||||
{
|
||||
public abstract void Run(BuildContext context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d1fa1e3836b449ea0f81c0fa1ca7246
|
||||
timeCreated: 1735888255
|
||||
42
Assets/Scripts/Editor/Builder/Tasks/BuildABTask.cs
Normal file
42
Assets/Scripts/Editor/Builder/Tasks/BuildABTask.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Builder/Tasks/BuildABTask.cs.meta
Normal file
3
Assets/Scripts/Editor/Builder/Tasks/BuildABTask.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2acde0d91b8b47ad8abdd6febd62232c
|
||||
timeCreated: 1735888685
|
||||
121
Assets/Scripts/Editor/Builder/Tasks/BuildAppTask.cs
Normal file
121
Assets/Scripts/Editor/Builder/Tasks/BuildAppTask.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Builder/Tasks/BuildAppTask.cs.meta
Normal file
3
Assets/Scripts/Editor/Builder/Tasks/BuildAppTask.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2039f10c99ae4fa18259e438203cc78c
|
||||
timeCreated: 1735889001
|
||||
14
Assets/Scripts/Editor/Builder/Tasks/BuildExcelTask.cs
Normal file
14
Assets/Scripts/Editor/Builder/Tasks/BuildExcelTask.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 241caaeb76c54700bc0da1f73179fcf4
|
||||
timeCreated: 1735888813
|
||||
109
Assets/Scripts/Editor/EditorUtils.cs
Normal file
109
Assets/Scripts/Editor/EditorUtils.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/EditorUtils.cs.meta
Normal file
3
Assets/Scripts/Editor/EditorUtils.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54e51fb34aa14d6f8e631baadcc9ede5
|
||||
timeCreated: 1731427402
|
||||
3
Assets/Scripts/Editor/Excel.meta
Normal file
3
Assets/Scripts/Editor/Excel.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3c81bd4cd80406c85154732adfdb65d
|
||||
timeCreated: 1732008523
|
||||
487
Assets/Scripts/Editor/Excel/ExcelToJsonWindow.cs
Normal file
487
Assets/Scripts/Editor/Excel/ExcelToJsonWindow.cs
Normal 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
|
||||
// }
|
||||
// }
|
||||
3
Assets/Scripts/Editor/Excel/ExcelToJsonWindow.cs.meta
Normal file
3
Assets/Scripts/Editor/Excel/ExcelToJsonWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33a6f327da22471c96c66e7bb7e83de9
|
||||
timeCreated: 1732008526
|
||||
3
Assets/Scripts/Editor/FairyGUI.meta
Normal file
3
Assets/Scripts/Editor/FairyGUI.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3fa57e7cd335467f8be7158eef21edb8
|
||||
timeCreated: 1768704531
|
||||
329
Assets/Scripts/Editor/FairyGUI/DisplayObjectEditor.cs
Normal file
329
Assets/Scripts/Editor/FairyGUI/DisplayObjectEditor.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Assets/Scripts/Editor/FairyGUI/DisplayObjectEditor.cs.meta
Normal file
13
Assets/Scripts/Editor/FairyGUI/DisplayObjectEditor.cs.meta
Normal 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:
|
||||
142
Assets/Scripts/Editor/FairyGUI/EditorToolSet.cs
Normal file
142
Assets/Scripts/Editor/FairyGUI/EditorToolSet.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
13
Assets/Scripts/Editor/FairyGUI/EditorToolSet.cs.meta
Normal file
13
Assets/Scripts/Editor/FairyGUI/EditorToolSet.cs.meta
Normal 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:
|
||||
18
Assets/Scripts/Editor/FairyGUI/FairyGUI-Editor.asmdef
Normal file
18
Assets/Scripts/Editor/FairyGUI/FairyGUI-Editor.asmdef
Normal 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
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f11907887f480418c8c693a619e2dbf0
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
193
Assets/Scripts/Editor/FairyGUI/PackagesWindow.cs
Normal file
193
Assets/Scripts/Editor/FairyGUI/PackagesWindow.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Assets/Scripts/Editor/FairyGUI/PackagesWindow.cs.meta
Normal file
13
Assets/Scripts/Editor/FairyGUI/PackagesWindow.cs.meta
Normal 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:
|
||||
29
Assets/Scripts/Editor/FairyGUI/StageCameraEditor.cs
Normal file
29
Assets/Scripts/Editor/FairyGUI/StageCameraEditor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Assets/Scripts/Editor/FairyGUI/StageCameraEditor.cs.meta
Normal file
13
Assets/Scripts/Editor/FairyGUI/StageCameraEditor.cs.meta
Normal 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:
|
||||
226
Assets/Scripts/Editor/FairyGUI/UIConfigEditor.cs
Normal file
226
Assets/Scripts/Editor/FairyGUI/UIConfigEditor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Assets/Scripts/Editor/FairyGUI/UIConfigEditor.cs.meta
Normal file
13
Assets/Scripts/Editor/FairyGUI/UIConfigEditor.cs.meta
Normal 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:
|
||||
64
Assets/Scripts/Editor/FairyGUI/UIContentScalerEditor.cs
Normal file
64
Assets/Scripts/Editor/FairyGUI/UIContentScalerEditor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Assets/Scripts/Editor/FairyGUI/UIContentScalerEditor.cs.meta
Normal file
13
Assets/Scripts/Editor/FairyGUI/UIContentScalerEditor.cs.meta
Normal 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:
|
||||
88
Assets/Scripts/Editor/FairyGUI/UIPainterEditor.cs
Normal file
88
Assets/Scripts/Editor/FairyGUI/UIPainterEditor.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Assets/Scripts/Editor/FairyGUI/UIPainterEditor.cs.meta
Normal file
13
Assets/Scripts/Editor/FairyGUI/UIPainterEditor.cs.meta
Normal 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:
|
||||
157
Assets/Scripts/Editor/FairyGUI/UIPanelEditor.cs
Normal file
157
Assets/Scripts/Editor/FairyGUI/UIPanelEditor.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Assets/Scripts/Editor/FairyGUI/UIPanelEditor.cs.meta
Normal file
13
Assets/Scripts/Editor/FairyGUI/UIPanelEditor.cs.meta
Normal 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:
|
||||
3
Assets/Scripts/Editor/Fix.meta
Normal file
3
Assets/Scripts/Editor/Fix.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f6a32768faf4764b85c949a38093532
|
||||
timeCreated: 1743782370
|
||||
808
Assets/Scripts/Editor/Fix/RF4FixPrefab.cs
Normal file
808
Assets/Scripts/Editor/Fix/RF4FixPrefab.cs
Normal 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
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Fix/RF4FixPrefab.cs.meta
Normal file
3
Assets/Scripts/Editor/Fix/RF4FixPrefab.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d55d4f69aaa14fb2910c88c7230d7273
|
||||
timeCreated: 1743782400
|
||||
40
Assets/Scripts/Editor/FloatBobberControllerEditor.cs
Normal file
40
Assets/Scripts/Editor/FloatBobberControllerEditor.cs
Normal 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();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2e2de2e2fef459895d6c89eb7b66a34
|
||||
timeCreated: 1764169703
|
||||
40
Assets/Scripts/Editor/FloatBobberControllerProEditor.cs
Normal file
40
Assets/Scripts/Editor/FloatBobberControllerProEditor.cs
Normal 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();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a90396d330f942dea5b6ac1aff681614
|
||||
timeCreated: 1764167227
|
||||
89
Assets/Scripts/Editor/ImageViewerWindow.cs
Normal file
89
Assets/Scripts/Editor/ImageViewerWindow.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/ImageViewerWindow.cs.meta
Normal file
3
Assets/Scripts/Editor/ImageViewerWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80b182f8bcff401aaaad3abc44492871
|
||||
timeCreated: 1757316527
|
||||
78
Assets/Scripts/Editor/MeshAssetObjExporter.cs
Normal file
78
Assets/Scripts/Editor/MeshAssetObjExporter.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/MeshAssetObjExporter.cs.meta
Normal file
3
Assets/Scripts/Editor/MeshAssetObjExporter.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b31d593151854995a593d8ed391e8941
|
||||
timeCreated: 1751770498
|
||||
237
Assets/Scripts/Editor/MeshToSkinnedMeshConverter.cs
Normal file
237
Assets/Scripts/Editor/MeshToSkinnedMeshConverter.cs
Normal 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);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
3
Assets/Scripts/Editor/MeshToSkinnedMeshConverter.cs.meta
Normal file
3
Assets/Scripts/Editor/MeshToSkinnedMeshConverter.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad60a9b58ae14a4c8c2d5be59e01bcb4
|
||||
timeCreated: 1716886501
|
||||
3
Assets/Scripts/Editor/Preview.meta
Normal file
3
Assets/Scripts/Editor/Preview.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64b3d51f8cb04af485e1a07f8a6e15a5
|
||||
timeCreated: 1750822352
|
||||
13
Assets/Scripts/Editor/Preview/ModelViewEditWindow.cs
Normal file
13
Assets/Scripts/Editor/Preview/ModelViewEditWindow.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class ModelViewEditWindow : EditorWindow
|
||||
{
|
||||
[MenuItem("NBC/工具/模型预览&Icon编辑")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
GetWindow<RuntimePreviewEditor>("模型预览");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 792c7ab2386446f9b3bbc86da9c90989
|
||||
timeCreated: 1761634153
|
||||
389
Assets/Scripts/Editor/Preview/PreviewEditWindow.cs
Normal file
389
Assets/Scripts/Editor/Preview/PreviewEditWindow.cs
Normal 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();
|
||||
// }
|
||||
}
|
||||
3
Assets/Scripts/Editor/Preview/PreviewEditWindow.cs.meta
Normal file
3
Assets/Scripts/Editor/Preview/PreviewEditWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fe1f9c26314412880e299b87d998083
|
||||
timeCreated: 1750822614
|
||||
110
Assets/Scripts/Editor/RemoveMissingScripts.cs
Normal file
110
Assets/Scripts/Editor/RemoveMissingScripts.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/RemoveMissingScripts.cs.meta
Normal file
3
Assets/Scripts/Editor/RemoveMissingScripts.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28ee8e197e8248988e0e92d2110a7212
|
||||
timeCreated: 1746242929
|
||||
40
Assets/Scripts/Editor/RemoveMissingScriptsTool.cs
Normal file
40
Assets/Scripts/Editor/RemoveMissingScriptsTool.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/RemoveMissingScriptsTool.cs.meta
Normal file
3
Assets/Scripts/Editor/RemoveMissingScriptsTool.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5af09e9232b44575990e7962843fba61
|
||||
timeCreated: 1729655037
|
||||
152
Assets/Scripts/Editor/ReplaceStandardShaderWithURP.cs
Normal file
152
Assets/Scripts/Editor/ReplaceStandardShaderWithURP.cs
Normal 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.");
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69f745013fe24bf8b861acc1bfd99266
|
||||
timeCreated: 1745409560
|
||||
28
Assets/Scripts/Editor/RopeEditor.cs
Normal file
28
Assets/Scripts/Editor/RopeEditor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/RopeEditor.cs.meta
Normal file
3
Assets/Scripts/Editor/RopeEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f24add4ba0ae4e76acd98c4a5512c366
|
||||
timeCreated: 1771850618
|
||||
3
Assets/Scripts/Editor/Test.meta
Normal file
3
Assets/Scripts/Editor/Test.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63016c524b454431b06d891415ccdf5e
|
||||
timeCreated: 1767354854
|
||||
21
Assets/Scripts/Editor/Test/PlayerAnimatorEditor.cs
Normal file
21
Assets/Scripts/Editor/Test/PlayerAnimatorEditor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Test/PlayerAnimatorEditor.cs.meta
Normal file
3
Assets/Scripts/Editor/Test/PlayerAnimatorEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03298da249bf4d0d86c372beb4d5dc48
|
||||
timeCreated: 1767354859
|
||||
26
Assets/Scripts/Editor/Test/UIBlurEditor.cs
Normal file
26
Assets/Scripts/Editor/Test/UIBlurEditor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Test/UIBlurEditor.cs.meta
Normal file
3
Assets/Scripts/Editor/Test/UIBlurEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebaa0f203943458688dac255c2ea6441
|
||||
timeCreated: 1770124598
|
||||
52
Assets/Scripts/Editor/TestEditorUtil.cs
Normal file
52
Assets/Scripts/Editor/TestEditorUtil.cs
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/TestEditorUtil.cs.meta
Normal file
3
Assets/Scripts/Editor/TestEditorUtil.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 478469c8975248bc84312e8d7955fff5
|
||||
timeCreated: 1742652567
|
||||
145
Assets/Scripts/Editor/ZHWindow.cs
Normal file
145
Assets/Scripts/Editor/ZHWindow.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/ZHWindow.cs.meta
Normal file
3
Assets/Scripts/Editor/ZHWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 244825ec57ad4537a0834858490d694e
|
||||
timeCreated: 1735789432
|
||||
Reference in New Issue
Block a user