Merge branch '00.StaryEvo' into master1

# Conflicts:
#	.gitlab-ci.yml
#	Assets/00.StaryEvo.meta
#	Assets/02.InformationSave/Editor/CustomEditorBaseEditor.cs.meta
#	Assets/02.InformationSave/RunTime/Abstract.meta
#	Assets/02.InformationSave/RunTime/Abstract/AbstractInformation.cs.meta
#	Assets/02.InformationSave/RunTime/Base.meta
#	Assets/04.AudioCore/RunTime/Abstract/IAudio.cs.meta
#	Assets/04.AudioCore/RunTime/Base/AudioSourcePool.cs.meta
#	Assets/05.TableTextConversion/RunTime/Abstract.meta
#	Assets/05.TableTextConversion/RunTime/Base.meta
#	Packages/com.code-philosophy.hybridclr/Editor.meta
#	Packages/com.code-philosophy.hybridclr/Editor/3rds/UnityHook/CodePatcher.cs.meta
#	Packages/com.code-philosophy.hybridclr/Editor/3rds/UnityHook/HookPool.cs.meta
#	Packages/com.code-philosophy.hybridclr/Editor/HybridCLR.Editor.asmdef.meta
#	Packages/com.code-philosophy.hybridclr/Runtime/HybridCLR.Runtime.asmdef.meta
This commit is contained in:
2025-04-07 11:55:28 +08:00
552 changed files with 29469 additions and 19 deletions

12
Assets/00.StaryEvo.meta Normal file
View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
<<<<<<<< HEAD:Assets/05.TableTextConversion/RunTime/Base.meta
guid: f458924b47972e344ab95e73c17cec83
========
guid: c96ccfb3a14425d4e81a3d31ba25bede
>>>>>>>> 00.StaryEvo:Assets/00.StaryEvo.meta
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 426d0ca955a34a89853bcd019777299a
timeCreated: 1625564841

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: dc0c6a9a74c33bb45b7529d86d820e2e
guid: 71921b49d6fa2df40bcb9538075ce8fb
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,241 @@
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
using YooAsset;
using YooAsset.Editor;
namespace Stary.Evo.Editor
{
[CreateAssetMenu(fileName = "BuildAssetDataSetting", menuName = "Evo/BuildAssetDataSetting")]
public class BuildAssetDataSetting : SerializedScriptableObject
{
public void OnEnable()
{
buildTarget = EditorUserBuildSettings.activeBuildTarget.ToString();
GetPackageVersion();
oldVersionX = packageVersionX;
oldVersionY = packageVersionY;
oldVersionZ = packageVersionZ;
}
[HideInInspector] public string packageName;
[HideInInspector]public int packageVersionX = 1;
[HideInInspector]public int packageVersionY;
[HideInInspector]public int packageVersionZ;
private int oldVersionX = 1;
private int oldVersionY;
private int oldVersionZ;
[Title("目标环境", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("BuildSetting"), HideLabel]
[OnValueChanged("SetEnvironmentType")]
public EnvironmentType environmentType;
[Title("当前打包平台", titleAlignment: TitleAlignments.Centered)]
[ReadOnly]
[HorizontalGroup("BuildSetting"), HideLabel]
public string buildTarget;
private const string VerSersionMessage = "(小版本由打包叠加,中版本、大版本更新会重置小版本,如误操作,点击重置按钮即可)";
[TitleGroup("当前打包版本号", alignment: TitleAlignments.Centered)]
[ReadOnly]
[HorizontalGroup("当前打包版本号/PackageVersion"), HideLabel]
public string packageVersion;
[HorizontalGroup("当前打包版本号/PackageVersion"), HideLabel, EnumToggleButtons]
[HideIf("environmentType", EnvironmentType.Debug)]
public VersionPosType VersionType;
[HorizontalGroup("当前打包版本号/PackageVersion"), HideLabel, Button(Icon = SdfIconType.Plus)]
[HideIf("environmentType", EnvironmentType.Debug)]
public void AddBigVersion()
{
if (VersionType == VersionPosType.X)
{
packageVersionX++;
}
else if (VersionType == VersionPosType.Y)
{
packageVersionY++;
}
if (packageVersionZ > 0)
packageVersionZ = 0;
GetPackageVersion();
}
[HorizontalGroup("当前打包版本号/PackageVersion"), HideLabel, Button(Icon = SdfIconType.Dash)]
[HideIf("environmentType", EnvironmentType.Debug)]
public void SubBigVersion()
{
if (VersionType == VersionPosType.X)
{
packageVersionX--;
}
else if (VersionType == VersionPosType.Y)
{
packageVersionY--;
}
if (packageVersionZ > 0)
packageVersionZ = 0;
GetPackageVersion();
}
[HorizontalGroup("当前打包版本号/PackageVersion"), HideLabel, Button(Icon = SdfIconType.ArrowRepeat)]
[HideIf("environmentType", EnvironmentType.Debug)]
public void RepeatVersion()
{
packageVersionX = oldVersionX;
packageVersionY = oldVersionY;
packageVersionZ = oldVersionZ;
GetPackageVersion();
}
[Title("构建列表", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("BuildPipeline"), HideLabel]
[OnValueChanged("SetBuildPipelines")]
public EBuildPipeline selectedBuildPipelines;
[Title("加密列表", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("BuildPipeline"), HideLabel]
[ValueDropdown("GetEncryptionServices")]
[OnValueChanged("SetEncryptionServices")]
public Type encryption;
[HideLabel] public AbstractBuildPipelineViewer viewer;
[HideLabel] private Dictionary<EBuildPipeline, AbstractBuildPipelineViewer> _viewers;
public void SetEnvironmentType()
{
GetPackageVersion();
}
public string GetBuildPackageVersion(bool isUpdate = false)
{
if (environmentType == EnvironmentType.Debug)
{
return "Simulate";
}
if (environmentType == EnvironmentType.Release)
{
string version =
$"{packageVersionX}.{packageVersionY}.{packageVersionZ}";
if (isUpdate)
packageVersionZ++;
packageVersion = $"{packageVersionX}.{packageVersionY}.{packageVersionZ}";
return version;
}
return null;
}
public void GetPackageVersion()
{
SetBuildPipelines();
if (environmentType == EnvironmentType.Debug)
{
viewer.clearBuildCacheToggle = true;
selectedBuildPipelines = EBuildPipeline.EditorSimulateBuildPipeline;
packageVersion = "Simulate";
}
else if (environmentType == EnvironmentType.Release)
{
viewer.clearBuildCacheToggle = false;
selectedBuildPipelines = EBuildPipeline.BuiltinBuildPipeline;
packageVersionX = packageVersionX > 1 ? packageVersionX : 1;
packageVersionY =
packageVersionY > 0 ? packageVersionY : 0;
packageVersion =
$"{packageVersionX}.{packageVersionY}.{packageVersionZ}";
}
viewer.SetBuildCacheToggle();
AssetDatabase.SaveAssets();
//BuildServerPath();
}
/// <summary>
/// 设置当前构建管线
/// </summary>
/// <returns></returns>
private void SetBuildPipelines()
{
BuildPipelineViewer();
}
/// <summary>
/// 生成打包实例
/// </summary>
public void BuildPipelineViewer()
{
if (_viewers == null)
_viewers = new Dictionary<EBuildPipeline, AbstractBuildPipelineViewer>();
if (_viewers.ContainsKey(selectedBuildPipelines))
{
viewer = _viewers[selectedBuildPipelines];
}
else
{
switch (selectedBuildPipelines)
{
case EBuildPipeline.EditorSimulateBuildPipeline:
viewer = new SimulateBuildPipelineViewer(this);
break;
case EBuildPipeline.BuiltinBuildPipeline:
viewer = new BuiltinBuildPipelineViewer(this);
break;
case EBuildPipeline.ScriptableBuildPipeline:
viewer = new ScriptableBuildPipelineViewer(this);
break;
case EBuildPipeline.RawFileBuildPipeline:
viewer = new RawfileBuildpipelineViewer(this);
break;
}
_viewers.Add(selectedBuildPipelines, viewer);
}
}
private List<Type> GetEncryptionServices()
{
var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
if (encryption.IsNull())
{
encryption = encryptionClassTypes[0];
}
return encryptionClassTypes;
}
private void SetEncryptionServices()
{
AssetBundleBuilderSetting.SetPackageEncyptionClassName(packageName, selectedBuildPipelines,
encryption.FullName);
}
}
public enum VersionPosType
{
X,
Y,
}
public enum EnvironmentType
{
Debug,
Release,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 39a67460f559484da2b52def8ff05571
timeCreated: 1741844184

View File

@@ -0,0 +1,60 @@
using System;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Stary.Evo.Editor
{
[Serializable]
public class BuildAssetEntity
{
public BuildAssetEntity(string HorizontalGroupName,string ButtonName ,Action OnClickAction )
{
this.HorizontalGroupName = HorizontalGroupName;
this.ButtonName = ButtonName;
this.OnClickAction = OnClickAction;
}
private Color messageColor = Color.white;
private string messageText = "点击开始进程!!!!!";
private bool showInfoBox = true;
private string HorizontalGroupName;
private string ButtonName;
private Action OnClickAction;
[HorizontalGroup("@ HorizontalGroupName")]
[Button("@ ButtonName", ButtonSizes.Large)]
[InfoBox("@ messageText", InfoMessageType.Error, "@ showInfoBox==false")]
[InfoBox("@ messageText", InfoMessageType.Info, "@ showInfoBox==true")]
private void CopyDll()
{
try
{
OnClickAction?.Invoke();
showInfoBox = true;
messageColor = Color.green;
messageText = "进程结束!!!!!";
}
catch (Exception e)
{
Debug.LogError(e);
showInfoBox = false;
messageText =$"进程存在异常,异常信息为:【{e.Message}】" ;
messageColor = Color.red;
}
}
[HorizontalGroup("@ HorizontalGroupName", Width = 68)]
[Button(ButtonSizes.Large, Icon = SdfIconType.CheckCircleFill, IconAlignment = IconAlignment.RightEdge,
ButtonHeight = 68),
GUIColor("@messageColor")]
private void CopyDll1()
{
}
public void SetButtonName(string ButtonName)
{
this.ButtonName = ButtonName;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 689d3c7b06e841668647fc00ff0a3dd8
timeCreated: 1741593629

View File

@@ -0,0 +1,281 @@
/****************************************************
文件BuildAssetWindow.cs
作者xosmo_
邮箱:
日期2025/3/10 10:43:20
功能:
*****************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using EditorFramework;
using HybridCLR.Editor;
using HybridCLR.Editor.Commands;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.Serialization;
using YooAsset;
using YooAsset.Editor;
namespace Stary.Evo.Editor
{
public class BuildAssetWindow : OdinEditorWindow
{
private static BuildAssetWindow window;
[MenuItem("Evo/资源打包工具")]
static void ShowWindows()
{
if (CreatAssetWindow.GetCreatDomainAll().Count <= 0)
{
EditorUtility.DisplayDialog("提示", "不存在Domain元素无法打开此面板请先创建Domain元素", "确定" );
return;
}
window = (BuildAssetWindow)EditorWindow.GetWindow(typeof(BuildAssetWindow));
window.Show();
}
protected override void Initialize()
{
base.Initialize();
GetBuildPackageNames();
}
public static void RemoveBuildAssetWindow()
{
if(window != null)
window.Close();
}
protected void OnSelectionChange()
{
EditorUtility.SetDirty(BuildAssetDataSetting);
AssetDatabase.SaveAssets();
//AssetDatabase.Refresh();
}
[Title("包裹列表", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("BuildPipeline"), HideLabel]
[ValueDropdown("GetBuildPackageNames")]
[OnValueChanged("SetBuildPackageNames")]
public string selectedPackageNames;
public static string packageName;
#region HyBridCLRBuild
[Title("HyBridCLRBuild", titleAlignment: TitleAlignments.Centered)] [HideLabel]
public BuildAssetEntity hyBridClrBuildEntity =
new BuildAssetEntity("HyBridCLRBuild", "DllBuildTarget", () =>
{
//PrebuildCommand.GenerateAll();
CompileDllCommand.CompileDllActiveBuildTarget();
});
#endregion
#region MarkAsset
[Title("MarkAsset", titleAlignment: TitleAlignments.Centered)] [HideLabel]
public BuildAssetEntity markAssetEntity =
new BuildAssetEntity("MarkAsset", "MarkAsset", MarkAdressable.AddMark);
#endregion
#region BuildAsset
[InlineEditor(InlineEditorObjectFieldModes.CompletelyHidden)]
[HideLabel] public BuildAssetDataSetting BuildAssetDataSetting;
/// <summary>
/// 检测当前所有包裹
/// </summary>
/// <returns></returns>
private List<string> GetBuildPackageNames()
{
List<string> result = new List<string>();
foreach (var name in CreatAssetWindow.GetCreatDomainAllName())
{
result.Add(name);
}
if (selectedPackageNames.IsNullOrEmpty())
{
// string buildPackageName = DataSetting.packageName;
// if (result.Exists(p => p == buildPackageName))
// {
// selectedPackageNames = buildPackageName;
// }
// else
// {
selectedPackageNames = result[0];
//}
}
SetBuildPackageNames();
return result;
}
/// <summary>
/// 设置当前包裹
/// </summary>
/// <returns></returns>
private void SetBuildPackageNames()
{
//PlayerPrefs.SetString("BuildPackageNames", selectedPackageNames);
// DataSetting.packageName = selectedPackageNames;
packageName = selectedPackageNames;
// DataSetting = Resources.Load<BuildAssetDataSetting>("BuildAssetDataSetting");
string buildAssetDataSettingPath = $"Assets/Domain/{selectedPackageNames}/Conf/BuildAssetDataSetting.asset";
BuildAssetDataSetting buildAssetDataSetting =
AssetDatabase.LoadAssetAtPath<BuildAssetDataSetting>(buildAssetDataSettingPath);
if (buildAssetDataSetting != null)
{
BuildAssetDataSetting = buildAssetDataSetting;
Init();
}
else
{
Debug.LogError($"UnityEvo:BuildAssetDataSetting 不存在,请检查路径{buildAssetDataSettingPath}");
}
}
/// <summary>
/// 获取当前包裹
/// </summary>
/// <returns></returns>
public static string GetBuildPackageName()
{
return packageName;
}
#endregion
#region Update
[Title("BuildAssetButton", titleAlignment: TitleAlignments.Centered)] [HideLabel]
public BuildAssetEntity onBuildPipelineEntity;
[FormerlySerializedAs("UpdateServerPath")]
[TitleGroup("UpdateAssetButton", alignment: TitleAlignments.Centered)][ShowIf("@ BuildAssetDataSetting.environmentType== EnvironmentType.Release",true)]
[ReadOnly]
[InfoBox("服务器资源盘位未存在", InfoMessageType.Error, "@ _isCheckDriveExist==false")]
[InfoBox("1、映射网络驱动器\n2、添加http://192.168.31.100:5005/alist/HotRefresh地址\n3、设置盘符为Z盘", InfoMessageType.Info,
"@ _isCheckDriveExist==false")]
public string updateServerPath;
private bool _isCheckDriveExist;
[TitleGroup("UpdateAssetButton", alignment: TitleAlignments.Centered)] [HideLabel][ShowIf("@ _isCheckDriveExist&&BuildAssetDataSetting.environmentType== EnvironmentType.Release",true)]
public BuildAssetEntity onUpdateBuildPipelineEntity;
private void OnBuildPipeline()
{
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{selectedPackageNames}]", "Yes", "No"))
{
EditorTools.ClearUnityConsole();
EditorApplication.delayCall += BuildAssetDataSetting.viewer.ExecuteBuild;
}
else
{
Debug.LogWarning("[Build] 打包已经取消");
}
}
private void OnUpdateBuildPipeline()
{
if (EditorUtility.DisplayDialog("提示", $"开始上传至服务器[{selectedPackageNames}]", "Yes", "No"))
{
Stary.Evo.Editor.FileUtility.CopyDirectory(
$"{AssetBundleBuilderHelper.GetDefaultBuildOutputRoot()}/{EditorUserBuildSettings.activeBuildTarget}/{BuildAssetDataSetting.packageName}/{BuildAssetDataSetting.packageVersion}",
updateServerPath);
CreatePackageVersionJson();
BuildAssetDataSetting.GetBuildPackageVersion(true);
EditorUtility.DisplayDialog("提示", $"上传服务器完成!", "确定");
}
else
{
Debug.LogWarning("[Update] 上传已经取消");
}
}
#endregion
protected void Init()
{
//Update
//检测Z盘
_isCheckDriveExist = Stary.Evo.Editor.FileUtility.CheckDriveExists("Z");
onBuildPipelineEntity =
new BuildAssetEntity("打包", $"打包资源包【版本:{BuildAssetDataSetting.packageVersion}】", OnBuildPipeline);
onUpdateBuildPipelineEntity =
new BuildAssetEntity("更新", $"更新至服务器【版本:{BuildAssetDataSetting.packageVersion}】", OnUpdateBuildPipeline);
}
private Vector2 scroll;
protected override void DrawEditor(int index)
{
scroll = GUILayout.BeginScrollView(scroll);
{
base.DrawEditor(index);
BuildServerPath();
}
GUILayout.EndScrollView();
}
/// <summary>
/// 生成服务器路径
/// </summary>
private void BuildServerPath()
{
if (!_isCheckDriveExist)
{
return;
}
updateServerPath =
$"Z:/{Application.productName}/{BuildAssetDataSetting.packageName}/{EditorUserBuildSettings.activeBuildTarget}/{BuildAssetDataSetting.packageVersion}";
if (!Directory.Exists(updateServerPath))
Directory.CreateDirectory(updateServerPath);
//更新Button文字
onBuildPipelineEntity.SetButtonName($"打包资源包【版本:{BuildAssetDataSetting.packageVersion}】");
onUpdateBuildPipelineEntity.SetButtonName($"更新至服务器【版本:{BuildAssetDataSetting.packageVersion}】");
}
private void CreatePackageVersionJson()
{
string mainResDomainPath = $"Assets/Domain/{selectedPackageNames}/Conf/HotfixMainResDomain.asset";
HotfixMainResDomain mainResDomain =
AssetDatabase.LoadAssetAtPath<HotfixMainResDomain>(mainResDomainPath);
if (mainResDomain != null)
{
mainResDomain.hotfixMainResDomainEntity.packageVersion = BuildAssetDataSetting.packageVersion;
mainResDomain.hotfixMainResDomainEntity.pathconfig =
$"{Application.productName}/{BuildAssetDataSetting.packageName}/{EditorUserBuildSettings.activeBuildTarget}/{BuildAssetDataSetting.packageVersion}";
}
AssetDatabase.Refresh();
// 保存更改
AssetDatabase.SaveAssets();
string serverPath = $"Z:/HybridclrConfigData/{BuildAssetDataSetting.packageName}/{EditorUserBuildSettings.activeBuildTarget}/";
//直接保存服务器路径下,本地不保存
EditorFrameworkUtils.SaveJson(mainResDomain.hotfixMainResDomainEntity, serverPath, Application.productName);
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 00771a0cc2a1d7a42bb8d06ae6dce935
guid: 80143df6d596f664f97e7139d7811d2d
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,49 @@
using System;
using UnityEditor;
using YooAsset;
using YooAsset.Editor;
namespace Stary.Evo.Editor
{
[Serializable]
public class BuiltinBuildPipelineViewer :AbstractBuildPipelineViewer
{
public BuiltinBuildPipelineViewer(BuildAssetDataSetting packageName) : base(packageName)
{
}
public override void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(dataSetting.packageName, dataSetting.selectedBuildPipelines);
BuiltinBuildParameters buildParameters = new BuiltinBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = dataSetting.selectedBuildPipelines.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.AssetBundle;
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
buildParameters.PackageName = dataSetting.packageName;
buildParameters.PackageVersion =dataSetting.GetBuildPackageVersion();
buildParameters.EnableSharePackRule = true;
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.EncryptionServices = CreateEncryptionInstance();
BuiltinBuildPipeline pipeline = new BuiltinBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
base.ExecuteBuild();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ac3d61d6f0744f02a2f038fdeed98b75
timeCreated: 1741830306

View File

@@ -0,0 +1,272 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using EditorFramework;
using HybridCLR.Editor;
using HybridCLR.Editor.Settings;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace Stary.Evo.Editor
{
public class CreatAssetWindow : OdinEditorWindow
{
[MenuItem("Evo/创建Domain作用域")]
static void Init()
{
// Get existing open window or if none, make a new one:
CreatAssetWindow window = (CreatAssetWindow)EditorWindow.GetWindow(typeof(CreatAssetWindow));
window.Show();
}
[TitleGroup("创建Domain作用域")] public string domain;
[TitleGroup("创建Domain作用域")]
[Button("创建Domain", ButtonSizes.Large)]
public async void CreatDomain()
{
if (GetCreatDomainAll().Count>0)
{
EditorUtility.DisplayDialog("错误!", "Domain仅可以创建一个请在下方删除存在的Domain", "确定");
return;
}
if (string.IsNullOrEmpty(domain))
{
EditorUtility.DisplayDialog("错误!", "请输入将要创建Domain的编号", "确定");
return;
}
string domainPath = $"{Application.dataPath}/Domain/{domain}";
if (Directory.Exists(domainPath+"/AddressableRes/Config/DomainConfig.asset"))
{
EditorUtility.DisplayDialog("错误!", $"\"{domain}\"已经存在,无法创建", "确定");
return;
}
Directory.CreateDirectory(domainPath);
//美术资源存放文件夹
string resPath = $"{domainPath}/AddressableRes";
Directory.CreateDirectory(resPath);
//创建音频文件夹
Directory.CreateDirectory(resPath + "/Audios");
//创建Config文件夹
Directory.CreateDirectory(resPath + "/Config");
//创建Dll文件夹
Directory.CreateDirectory(resPath + "/Dll");
//创建Prefabs文件夹
Directory.CreateDirectory(resPath + "/Prefabs");
//创建Scenes文件夹
Directory.CreateDirectory(resPath + "/Scenes");
//创建SpriteAtlas文件夹
Directory.CreateDirectory(resPath + "/SpriteAtlas");
//创建Sprites文件夹
Directory.CreateDirectory(resPath + "/Sprites");
//创建Video文件夹
Directory.CreateDirectory(resPath + "/Video");
await File.WriteAllTextAsync($"{resPath}/这里放所有参与热更的资源.hint", "");
//主入口预制件
GameObject gameObj = new GameObject(domain);
gameObj.transform.position = Vector3.zero;
gameObj.transform.rotation = Quaternion.identity;
gameObj.name = domain;
Directory.CreateDirectory($"{resPath}/Prefabs");
string rootPfbFilePath = $"Assets/Domain/{domain}/AddressableRes/Prefabs/{domain}.prefab";
var localPath = AssetDatabase.GenerateUniqueAssetPath(rootPfbFilePath);
PrefabUtility.SaveAsPrefabAsset(gameObj, localPath);
//存放脚本文件夹
string scriptsPath = $"{domainPath}/HotUpdate";
Directory.CreateDirectory(scriptsPath);
await File.WriteAllTextAsync($"{scriptsPath}/这里放所有参与热更的脚本文件.hint", "该文件夹中的程序集定义文件,请勿删除,非常重要。");
//创建配置文件夹
string confPath = $"{domainPath}/Conf";
Directory.CreateDirectory(confPath);
//程序集配置资源
string hotfixDomain = $"HotUpdate_{domain}";
string hotfixDomainAsmdef = $"{scriptsPath}/{hotfixDomain}.asmdef";
await using (var writer = new StreamWriter(hotfixDomainAsmdef))
{
string body = Resources.Load<TextAsset>("AssemblyDefinitionTemplate").text;
body = body.Replace("MODULE_IDENT", hotfixDomain);
body = body.Replace("ROOT_NAMESPACE", hotfixDomain);
await writer.WriteAsync(body);
}
// await File.WriteAllTextAsync($"{scriptsPath}/{hotfixDomain}.asmdef", body);
// string architectureClassName = $"{domain}Architecture";
// string architectureClassPath = $"{scriptsPath}/{architectureClassName}.txt";
// //await File.WriteAllTextAsync($"{scriptsPath}/{architectureClassName}.cs", architectureTemplate);
//
// await using (var writer = new StreamWriter(architectureClassPath))
// {
//
// string architectureTemplate = Resources.Load<TextAsset>("ArchitectureTemplate").text;
// architectureTemplate = architectureTemplate.Replace("XXXX", architectureClassName);
// await writer.WriteAsync(architectureTemplate);
// }
//模块化脚本生成配置
string domainClassName = $"{domain}Domain";
string architectureClassName = $"{domain}Architecture";
//模块配置资源
DomainConfig moduleConfig = CreateInstance<DomainConfig>();
moduleConfig.domain = domain;
moduleConfig.className = domainClassName;
moduleConfig.mainPrefab = "Prefabs_" + gameObj.name;
moduleConfig.@namespace = domain;
AssetDatabase.CreateAsset(moduleConfig, $"Assets/Domain/{domain}/AddressableRes/Config/DomainConfig.asset");
//
//模块服务器配置资源
HotfixMainResDomain hotfixMainResDomain = CreateInstance<HotfixMainResDomain>();
hotfixMainResDomain.hotfixMainResDomainEntity = new HotfixMainResDomainEntity();
hotfixMainResDomain.hotfixMainResDomainEntity.domain = domain;
AssetDatabase.CreateAsset(hotfixMainResDomain, $"Assets/Domain/{domain}/Conf/HotfixMainResDomain.asset");
//编辑器配置资源
BuildAssetDataSetting buildAssetDataSetting = CreateInstance<BuildAssetDataSetting>();
buildAssetDataSetting.packageName = domain;
AssetDatabase.CreateAsset(buildAssetDataSetting,
$"Assets/Domain/{domain}/Conf/BuildAssetDataSetting.asset");
AssetDatabase.Refresh();
string configPath = $"Assets/Domain/{domain}/HotUpdate/{hotfixDomain}.asmdef";
AssemblyDefinitionAsset assemblyDefinitionAsset =
AssetDatabase.LoadAssetAtPath<AssemblyDefinitionAsset>(configPath);
// 将程序集定义添加到 HybridCLR 热更列表
var settings = SettingsUtil.HybridCLRSettings;
if (!settings.hotUpdateAssemblyDefinitions.Contains(assemblyDefinitionAsset))
{
var assemblyList = settings.hotUpdateAssemblyDefinitions.ToList();
assemblyList.Add(assemblyDefinitionAsset);
SettingsUtil.HybridCLRSettings.hotUpdateAssemblyDefinitions = assemblyList.ToArray();
}
List<AssemblyDefinitionAsset> assemblies = new List<AssemblyDefinitionAsset>();
for (int i = 0; i < settings.hotUpdateAssemblyDefinitions.Length; i++)
{
if (settings.hotUpdateAssemblyDefinitions[i] != null)
{
assemblies.Add(settings.hotUpdateAssemblyDefinitions[i]);
}
}
HybridCLRSettings.Instance.hotUpdateAssemblyDefinitions = assemblies.ToArray();
HybridCLRSettings.Save();
AssetDatabase.SaveAssets();
string domainClassPath = $"{scriptsPath}/{domainClassName}.cs";
//await File.WriteAllTextAsync($"{scriptsPath}/{domainClassName}.cs", domainTemplate);
await using (var writer = new StreamWriter(domainClassPath))
{
string domainTemplate = Resources.Load<TextAsset>("DomainTemplate").text;
domainTemplate = domainTemplate.Replace("ClassNameXX", domainClassName)
.Replace("ReturnArchitecture", architectureClassName)
.Replace("ArchitectureX", architectureClassName)
.Replace("NamespaceX", domain);
await writer.WriteAsync(domainTemplate);
}
}
public void CreateDomainClass()
{
}
public void CreateArchitectureClass()
{
}
[TitleGroup("预览Domain作用域")] public List<CreatDomainEntity> domainList;
protected override void Initialize()
{
base.Initialize();
domainList = GetCreatDomainAll();
}
/// <summary>
/// 获取全部作用域
/// </summary>
public static string[] GetCreatDomainAllName()
{
string domainPath = $"{Application.dataPath}/Domain";
string[] domains;
// 新增目录获取代码
if (Directory.Exists(domainPath))
{
var dirInfo = new DirectoryInfo(domainPath);
// 获取直接子目录(不递归)
domains = dirInfo.GetDirectories("*", SearchOption.TopDirectoryOnly)
.Select(d => d.Name)
.ToArray();
}
else
{
domains = Array.Empty<string>();
}
return domains;
}
/// <summary>
/// 获取全部作用域
/// </summary>
public static List<CreatDomainEntity> GetCreatDomainAll()
{
string domainPath = $"{Application.dataPath}/Domain";
string[] domains;
// 新增目录获取代码
if (Directory.Exists(domainPath))
{
var dirInfo = new DirectoryInfo(domainPath);
// 获取直接子目录(不递归)
domains = dirInfo.GetDirectories("*", SearchOption.TopDirectoryOnly)
.Select(d => d.Name)
.ToArray();
}
else
{
domains = Array.Empty<string>();
}
List<CreatDomainEntity> domainList = new List<CreatDomainEntity>();
foreach (var item in domains)
{
if (File.Exists($"{domainPath}/{item}/AddressableRes/Config/DomainConfig.asset"))
{
CreatDomainEntity domainEntity = new CreatDomainEntity(domainList)
{
DomainName = item,
domainPath = $"{domainPath}/{item}"
};
domainList.Add(domainEntity);
}
}
return domainList;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7d162e11fd4c47ee9f6995ad7bb6bac1
timeCreated: 1742377890

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7380165adc3342dbacef4abe80ac2bb7
timeCreated: 1742867444

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.IO;
using EditorFramework;
using Sirenix.OdinInspector;
using UnityEditor;
namespace Stary.Evo.Editor
{
[Serializable]
public class CreatDomainEntity
{
private List<CreatDomainEntity> domainList;
[HorizontalGroup] [ReadOnly] public string DomainName;
[ReadOnly]
public string domainPath;
public CreatDomainEntity(List<CreatDomainEntity> domainList)
{
this.domainList = domainList;
}
[HorizontalGroup(Width = 60)]
[Button("", Icon = SdfIconType.XCircle, IconAlignment = IconAlignment.RightEdge)]
public void CloseDomain()
{
bool isOk = EditorUtility.DisplayDialog("提示", "是否删除此Domain", "是", "否");
if (isOk)
{
BuildAssetWindow.RemoveBuildAssetWindow();
EditorFrameworkUtils.DeleteAllChild(domainPath, FileAttributes.Normal);
domainList.Clear();
AssetDatabase.Refresh();
AssetDatabase.SaveAssets();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b99d72d55efd48e099adf77d4608689d
timeCreated: 1742867433

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using Stary.Evo.Editor;
using UnityEditor;
using UnityEngine;
using YooAsset;
using YooAsset.Editor;
namespace Stary.Evo.Editor
{
[Serializable]
public class AbstractBuildPipelineViewer
{
protected BuildAssetDataSetting dataSetting;
protected bool isSimulate;
protected bool isRaw;
[Title("清理构建缓存", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("BuildCache")]
[InfoBox("当不勾选此项的时候,引擎会开启增量打包模式,会极大提高构建速度!")]
[OnValueChanged("SetBuildCacheToggle")]
[HideIf("isSimulate", true)]
public bool clearBuildCacheToggle;
[Title("依赖数据库", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("BuildCache")]
[InfoBox("当开启此项的时候,会极大提高构建速度!")]
[OnValueChanged("SetUseAssetDependencyDB")]
[HideIf("isSimulate", true)]
public bool useAssetDependencyDBToggle;
[Title("资源包的压缩方式", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("FileStyle"), HideLabel]
[OnValueChanged("SetCompression")]
[HideIf("@isSimulate==true || isRaw==true")]
public ECompressOption compression;
[Title("资源包文件名称样式", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("FileStyle"), HideLabel]
[OnValueChanged("SetFileNameStyle")]
[HideIf("isSimulate", true)]
public EFileNameStyle fileNameStyle;
[Title("首包资源文件的拷贝方式", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("FileStyle"), HideLabel]
[OnValueChanged("SetCopyBuildinFileOption")]
[HideIf("isSimulate", true)]
public EBuildinFileCopyOption copyBuildinFileOption;
[Title("首包资源文件的拷贝参数", titleAlignment: TitleAlignments.Centered)]
[HideLabel]
[OnValueChanged("SetCopyBuildinFileParams")]
[ShowIf(
"@copyBuildinFileOption==EBuildinFileCopyOption.ClearAndCopyByTags||copyBuildinFileOption==EBuildinFileCopyOption.OnlyCopyByTags ")]
public string copyBuildinFileParams;
public AbstractBuildPipelineViewer(BuildAssetDataSetting dataSetting)
{
this.dataSetting = dataSetting;
useAssetDependencyDBToggle = true;
clearBuildCacheToggle = false;
compression = ECompressOption.LZ4;
fileNameStyle = EFileNameStyle.BundleName;
copyBuildinFileOption = EBuildinFileCopyOption.ClearAndCopyAll;
}
#region AssetBuild
private void SetCompression()
{
AssetBundleBuilderSetting.SetPackageCompressOption(dataSetting.packageName, dataSetting.selectedBuildPipelines,
compression);
}
private void SetFileNameStyle()
{
AssetBundleBuilderSetting.SetPackageFileNameStyle(dataSetting.packageName, dataSetting.selectedBuildPipelines,
fileNameStyle);
}
private void SetCopyBuildinFileOption()
{
AssetBundleBuilderSetting.SetPackageBuildinFileCopyOption(dataSetting.packageName,
dataSetting.selectedBuildPipelines, copyBuildinFileOption);
//PlayerPrefs.SetInt("CopyBuildinFileOption", (int)copyBuildinFileOption);
}
private void SetCopyBuildinFileParams()
{
AssetBundleBuilderSetting.SetPackageBuildinFileCopyParams(dataSetting.packageName,
dataSetting.selectedBuildPipelines, copyBuildinFileParams);
//PlayerPrefs.SetInt("CopyBuildinFileOption", (int)copyBuildinFileOption);
}
public void SetBuildCacheToggle()
{
AssetBundleBuilderSetting.SetPackageClearBuildCache(dataSetting.packageName, dataSetting.selectedBuildPipelines,
clearBuildCacheToggle);
}
private void SetUseAssetDependencyDB()
{
AssetBundleBuilderSetting.SetPackageUseAssetDependencyDB(dataSetting.packageName, dataSetting.selectedBuildPipelines,
useAssetDependencyDBToggle);
}
#endregion
public virtual void ExecuteBuild()
{
// GetPackageVersion();
}
/// <summary>
/// 创建加密类实例
/// </summary>
protected IEncryptionServices CreateEncryptionInstance()
{
var encyptionClassName =
AssetBundleBuilderSetting.GetPackageEncyptionClassName(dataSetting.packageName,
dataSetting.selectedBuildPipelines);
var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
var classType = encryptionClassTypes.Find(x => x.FullName.Equals(encyptionClassName));
if (classType != null)
return (IEncryptionServices)Activator.CreateInstance(classType);
else
return null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7fdaadaf963047a098c8b4f46fec5619
timeCreated: 1741835014

View File

@@ -0,0 +1,48 @@
using System;
using UnityEditor;
using YooAsset;
using YooAsset.Editor;
namespace Stary.Evo.Editor
{
[Serializable]
public class RawfileBuildpipelineViewer:AbstractBuildPipelineViewer
{
public RawfileBuildpipelineViewer(BuildAssetDataSetting packageName) : base(packageName)
{
isRaw = true;
}
public override void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(dataSetting.packageName, dataSetting.selectedBuildPipelines);
RawFileBuildParameters buildParameters = new RawFileBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = dataSetting.selectedBuildPipelines.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.RawBundle;
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
buildParameters.PackageName = dataSetting.packageName;
buildParameters.PackageVersion =dataSetting.GetBuildPackageVersion();
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.EncryptionServices = CreateEncryptionInstance();
RawFileBuildPipeline pipeline = new RawFileBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
base.ExecuteBuild();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 06dda5f218054dee83d2a37d42bb2b9a
timeCreated: 1741830326

View File

@@ -0,0 +1,62 @@
using System;
using UnityEditor;
using YooAsset;
using YooAsset.Editor;
namespace Stary.Evo.Editor
{
[Serializable]
public class ScriptableBuildPipelineViewer:AbstractBuildPipelineViewer
{
public ScriptableBuildPipelineViewer(BuildAssetDataSetting packageName) : base(packageName)
{
}
public override void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var builtinShaderBundleName = GetBuiltinShaderBundleName();
ScriptableBuildParameters buildParameters = new ScriptableBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = dataSetting.selectedBuildPipelines.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.AssetBundle;
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
buildParameters.PackageName = dataSetting.packageName;
buildParameters.PackageVersion = dataSetting.GetBuildPackageVersion();
buildParameters.EnableSharePackRule = true;
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
buildParameters.EncryptionServices = CreateEncryptionInstance();
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
base.ExecuteBuild();
}
/// <summary>
/// 内置着色器资源包名称
/// 注意:和自动收集的着色器资源包名保持一致!
/// </summary>
private string GetBuiltinShaderBundleName()
{
var uniqueBundleName = AssetBundleCollectorSettingData.Setting.UniqueBundleName;
var packRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
return packRuleResult.GetBundleName(dataSetting.packageName, uniqueBundleName);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cb4c30ccb8294c92a7545fc05377d7bc
timeCreated: 1741830341

View File

@@ -0,0 +1,42 @@
using System;
using UnityEditor;
using YooAsset;
using YooAsset.Editor;
namespace Stary.Evo.Editor
{
[Serializable]
public class SimulateBuildPipelineViewer:AbstractBuildPipelineViewer
{
public SimulateBuildPipelineViewer(BuildAssetDataSetting packageName) : base(packageName)
{
isSimulate = true;
}
public override void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(dataSetting.packageName, dataSetting.selectedBuildPipelines);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(dataSetting.packageName, dataSetting.selectedBuildPipelines);
EditorSimulateBuildParameters buildParameters = new EditorSimulateBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = dataSetting.selectedBuildPipelines.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.VirtualBundle;
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
buildParameters.PackageName = dataSetting.packageName;
buildParameters.PackageVersion = dataSetting.GetBuildPackageVersion();
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.EncryptionServices = CreateEncryptionInstance();
EditorSimulateBuildPipeline pipeline = new EditorSimulateBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 501ea11982da4673b0bf8af90a805329
timeCreated: 1741830160

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7dfc7b6280e2426a81a5ead99db006f7
timeCreated: 1741232911

View File

@@ -0,0 +1,89 @@
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.Editor
{
public class ChangePlayerMode
{
public static PLayerMode PLayerMode
{
get => _pLayerMode;
set => SetPlayerMode(value);
}
private static PLayerMode _pLayerMode;
private const string EditorSimulateMode = "Evo/ChangePlayerMode/EditorSimulateMode(编辑器调试模式)";
private const string OfflinePlayMode = "Evo/ChangePlayerMode/OfflinePlayMode(本地运行模式)";
private const string HostPlayMode = "Evo/ChangePlayerMode/HostPlayMode(服务器运行模式)";
private const string WebPlayMode = "Evo/ChangePlayerMode/WebPlayMode(Web运行模式)";
[MenuItem(EditorSimulateMode)]
private static void SetEditorMode() => SetPlayerMode(PLayerMode.EDITOR_SIMULATEMODE);
[MenuItem(OfflinePlayMode)]
private static void SetOfflineMode() => SetPlayerMode(PLayerMode.OFFLINE_PLAYMODE);
[MenuItem(HostPlayMode)]
private static void SetHostMode() => SetPlayerMode(PLayerMode.HOST_PLAYMODE);
[MenuItem(WebPlayMode)]
private static void SetWebMode() => SetPlayerMode(PLayerMode.WEB_PLAYMODE);
[MenuItem(EditorSimulateMode, true)]
private static bool ValidateModeMenu()
{
string platform = EditorPrefs.GetString("ChangePLayerMode", PLayerMode.EDITOR_SIMULATEMODE.ToString());
Menu.SetChecked(EditorSimulateMode, platform == PLayerMode.EDITOR_SIMULATEMODE.ToString());
Menu.SetChecked(OfflinePlayMode, platform == PLayerMode.OFFLINE_PLAYMODE.ToString());
Menu.SetChecked(HostPlayMode, platform == PLayerMode.HOST_PLAYMODE.ToString());
Menu.SetChecked(WebPlayMode, platform == PLayerMode.WEB_PLAYMODE.ToString());
Debug.LogError("CheckPlatform");
return true;
}
private static void SetPlayerMode(PLayerMode mode)
{
// 清除所有旧模式定义
var currentTarget = EditorUserBuildSettings.selectedBuildTargetGroup;
if (currentTarget == BuildTargetGroup.Unknown) return;
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTarget)
.Split(';')
.Where(d => !Enum.GetNames(typeof(PLayerMode)).Contains(d))
.ToList();
// 添加新模式
defines.Add(mode.ToString());
PlayerSettings.SetScriptingDefineSymbolsForGroup(currentTarget, string.Join(";", defines));
Debug.Log($"当前编译符号: {string.Join(";", defines)}"); // 添加调试日志
_pLayerMode = mode;
EditorPrefs.SetString("ChangePLayerMode", _pLayerMode.ToString());
AssetDatabase.Refresh();
// 添加解决方案文件重新生成逻辑
EditorApplication.delayCall += () =>
{
EditorApplication.ExecuteMenuItem("Assets/Open C# Project");
UnityEditor.Compilation.CompilationPipeline.RequestScriptCompilation();
Debug.Log("已强制重新生成解决方案文件");
};
}
}
public enum PLayerMode
{
//编辑仿真模式,
EDITOR_SIMULATEMODE,
//单机运行模式
OFFLINE_PLAYMODE,
//联机运行模式
HOST_PLAYMODE,
//web运行模式
WEB_PLAYMODE
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 28520dd6a62c460d93fe8bb524b6a159
timeCreated: 1741232924

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a832a8c4833f01744bb484de1af54c37
guid: d2b63bce95e26de40814079b9e215865
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: fc7186a56102e2f4d803fb53e2dcad09
guid: 10cd38fccc1db684d9a576da1f9dc85e
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,40 @@
// using System;
// using System.IO;
//
// namespace Stary.Evo.Editor
// {
// public class ChangeScriptTemplates : UnityEditor.AssetModificationProcessor
// {
// // 要添加的注释的内容
// private static string annotationStr =
// "/**************************************************** \r\n"
// + " 文件:#Filename\r\n"
// + " 作者:#CreateAuthor#\r\n"
// + " 邮箱:\r\n"
// + " 日期:#CreateTime#\r\n"
// + " 功能:\r\n"
// + "*****************************************************/\r\n\n";
//
// public static void OnWillCreateAsset(string path)
// {
// //将.meta后缀屏蔽
// path = path.Replace(".meta", "");
// //只对.cs脚本作操作
// if (path.EndsWith(".cs"))
// {
// //读取该路径下的.cs文件中的所有文本.
// //注意此时Unity已经对脚本完成了模版内容的替换包括#SCRIPTNAME#也已经被替换为文件名了,读取到的是替换后的文本内容.
// annotationStr += File.ReadAllText(path);
// //获取用户名和当前系统时间并替换对应位置内容
// annotationStr = annotationStr.Replace("#CreateAuthor#", Environment.UserName)
// .Replace("#CreateTime#", string.Concat(DateTime.Now.Year, "/", DateTime.Now.Month, "/",
// DateTime.Now.Day, " ", DateTime.Now.Hour, ":", DateTime.Now.Minute, ":", DateTime.Now.Second))
// .Replace("#Filename", Path.GetFileName(path));
// if (!File.ReadAllText(path).Contains("文件") && !File.ReadAllText(path).Contains("作者") && !File.ReadAllText(path).Contains("邮箱") && !File.ReadAllText(path).Contains("日期") && !File.ReadAllText(path).Contains("功能"))
// //重新将文本写入.cs文件
// File.WriteAllText(path, annotationStr);
// }
//
// }
// }
// }

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 3cf38f4aa9f11b54797838ea149b559d
guid: 46fd7b74d162e9042a93085169ef025f
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: dd58efb7f9e1b0c4f9d07e84827f357d
guid: cf3097de0b145f944931508c9e1a0bcd
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,51 @@
/****************************************************
文件CreatScriptableObject.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/7 18:26:10
功能:
*****************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.Editor
{
public class CreatScriptableObject : OdinMenuEditorWindow
{
[MenuItem("Evo/Utility/ScriptObject/查找", false, 3)]
//[MenuItem("Assets/Create Scriptable Object", priority = -1000)]
private static void ShowDialog()
{
GetWindow<CreatScriptableObject>().Show();
}
/// <summary>
/// 获取继承 ScriptableObject 且不是Editor相关的所有自定义类也就是自己编写的类
/// </summary>
// static HashSet<Type> scriptableObjectTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes)
// .Where(t =>
// t.IsClass &&
// typeof(ScriptableObject).IsAssignableFrom(t) &&
// !typeof(EditorWindow).IsAssignableFrom(t) &&
// !typeof(Editor).IsAssignableFrom(t) && t.GetCustomAttribute<ScriptableObjectEditorAttribute>() != null)
// .ToHashSet();
protected override OdinMenuTree BuildMenuTree()
{
OdinMenuTree tree = new OdinMenuTree(false); //不支持多选
tree.Selection.SupportsMultiSelect = false;
tree.AddAllAssetsAtPath("预览ScriptableObject", "Assets/Domain", typeof(ScriptableObject), true, true);
// tree.AddAllAssetsAtPath("预览ScriptableObject", "Assets/~Resources", typeof(ScriptableObject), true, true);
return tree;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: f5c3a514df208eb4cb4a15721b54f849
guid: ef650bd595ac650469971d45500a96ea
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,204 @@
// /****************************************************
// 文件ScriptableObjectCreator.cs
// 作者:张铮
// 邮箱834207172@qq.com
// 日期2022/3/7 18:24:58
// 功能:
// *****************************************************/
//
// using System;
// using System.Collections.Generic;
// using System.IO;
// using System.Linq;
// using EditorFramework;
// using Sirenix.OdinInspector.Editor;
// using Sirenix.Utilities;
// using Sirenix.Utilities.Editor;
// using UnityEditor;
// using UnityEngine;
// using WVDFramework;
//
// public class ScriptableObjectCreator : OdinMenuEditorWindow
// {
// [MenuItem("Utility/ScriptObject/创建",false,2)]
// //[MenuItem("Assets/Create Scriptable Object", priority = -1000)]
// private static void ShowDialog()
// {
// var path = "Assets";
// var obj = Selection.activeObject; //当前鼠标选中的 Object
// if (obj && AssetDatabase.Contains(obj))
// {
// path = AssetDatabase.GetAssetPath(obj);
// if (!Directory.Exists(path)) //主要用来判断所选的是文件还是文件夹
// {
// path = Path.GetDirectoryName(path); //如果是文件则获取对应文件夹的全名称
// }
// }
//
// //设置窗口对应属性
// var window = CreateInstance<ScriptableObjectCreator>();
// window.position = GUIHelper.GetEditorWindowRect().AlignCenter(800, 500); //设置窗口的宽和高
// window.titleContent = new GUIContent(path);
// window.targetFolder = path.Trim('/'); //避免出现 / 造成路径不对
// window.ShowUtility();
// }
//
// /// <summary>
// /// 获取继承 ScriptableObject 且不是Editor相关的所有自定义类也就是自己编写的类
// /// </summary>
// private static HashSet<Type> scriptableObjectTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes)
// .Where(t =>
// t.IsClass &&
// typeof(ScriptableObject).IsAssignableFrom(t) &&
// !typeof(EditorWindow).IsAssignableFrom(t) &&
// !typeof(Editor).IsAssignableFrom(t) && t.GetCustomAttribute<ScriptableObjectEditorAttribute>() != null)
// .ToHashSet();
// /// <summary>
// /// 选中的 ScriptableObject等待创建
// /// </summary>
// private ScriptableObject previewObject;
//
// /// <summary>
// /// 创建 ScriptableObject 时文件存储的目标文件夹
// /// </summary>
// private string targetFolder;
//
// private Vector2 scroll;
//
// private Type SelectedType
// {
// get
// {
// var m = MenuTree.Selection.LastOrDefault(); //因为可以多选所以返回选中的是一个列表这里返回的是列表的最后一个Object
// return m == null ? null : m.Value as Type;
// }
// }
//
// protected override OdinMenuTree BuildMenuTree()
// {
// mFolderField = new FolderField();
// OdinMenuTree tree = new OdinMenuTree(false); //不支持多选
// MenuWidth = 300; //菜单的宽度
// WindowPadding = Vector4.zero;
// tree.Config.DrawSearchToolbar = true; //开启搜索状态
// tree.DefaultMenuStyle = OdinMenuStyle.TreeViewStyle; //菜单设置成树形模式
// //筛选所有非抽象的类 并获取对应的路径
// tree.AddRange(scriptableObjectTypes.Where(x => !x.IsAbstract), GetMenuPathForType).AddThumbnailIcons();
// tree.SortMenuItemsByName();
// tree.Selection.SelectionConfirmed += x =>
// {
// Debug.Log($"双击确认并创建:{x}");
// this.CreateAsset();
// };
// tree.Selection.SelectionChanged += e =>
// {
// //每当选择发生更改时发生进行回调2次一次SelectionCleared 一次是ItemAdded
// if (this.previewObject && !AssetDatabase.Contains(this.previewObject))
// {
// DestroyImmediate(previewObject);
// }
//
// if (e != SelectionChangedType.ItemAdded)
// {
// return;
// }
//
// var t = SelectedType;
// if (t != null && !t.IsAbstract)
// {
// previewObject = CreateInstance(t) as ScriptableObject;
// }
// };
// return tree;
// }
//
// private string GetMenuPathForType(Type t)
// {
// if (t != null && scriptableObjectTypes.Contains(t))
// {
// var name = t.Name.Split('`').First()
// .SplitPascalCase(); //主要是为了去除泛型相关 例如Sirenix.Utilities.GlobalConfig`1[Sirenix.Serialization.GlobalSerializationConfig]
// return GetMenuPathForType(t.BaseType) + "/" + name;
// }
//
// return "";
// }
//
// protected override IEnumerable<object> GetTargets()
// {
// yield return previewObject;
// }
//
// private FolderField mFolderField;
//
// // private void OnEnable()
// // {
// // mFolderField = new FolderField();
// // }
//
// private string filename = default;
//
// protected override void DrawEditor(int index)
// {
// //scroll 内容滑动条的XY坐标
// scroll = GUILayout.BeginScrollView(scroll);
// {
// base.DrawEditor(index);
// }
// GUILayout.EndScrollView();
//
// if (this.previewObject)
// {
// GUILayout.FlexibleSpace(); //插入一个空隙
// SirenixEditorGUI.HorizontalLineSeparator(5); //插入一个水平分割线
// GUILayout.BeginHorizontal();
// {
// GUILayout.Label("选择要创建到的路径");
// var rect = EditorGUILayout.GetControlRect(GUILayoutOptions.Height(20));
// mFolderField.OnGUI(rect);
// }
// GUILayout.EndHorizontal();
// SirenixEditorGUI.HorizontalLineSeparator(5); //插入一个水平分割线
// GUILayout.BeginHorizontal();
// {
// GUILayout.Label("请输入要创建的文件名字");
// filename = GUILayout.TextField(filename);
// GUILayout.Label(".asset", GUILayout.MaxWidth(40));
// }
// GUILayout.EndHorizontal();
//
// SirenixEditorGUI.HorizontalLineSeparator(5); //插入一个水平分割线
// if (GUILayout.Button("Create Asset", GUILayoutOptions.Height(30)))
// {
// if (mFolderField.Path == "Assets")
// {
// if (EditorUtility.DisplayDialog("创建", ".asset文件创建在Assets目录下是否确定创建", "是", "否")) //显示对话框
// {
// CreateAsset();
// }
// }
// else
// {
// CreateAsset();
// }
// }
// }
// }
//
// private void CreateAsset()
// {
// if (previewObject)
// {
// if (filename == default)
// filename = MenuTree.Selection.First().Name.Replace(" ","");
// var dest = mFolderField.Path + filename + ".asset";
// dest = AssetDatabase.GenerateUniqueAssetPath(dest); //创建唯一路径 重名后缀 +1
// Debug.Log($"要创建的为{previewObject}");
// AssetDatabase.CreateAsset(previewObject, dest);
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
// Selection.activeObject = previewObject;
// EditorApplication.delayCall += Close; //如不需要创建后自动关闭可将本行注释
// }
// }
// }

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a08c59ee0e6844441825e5b5427d1e4c
guid: 814d860f258b17945ba74463d9d00144
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

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

View File

@@ -0,0 +1,77 @@
/****************************************************
文件StringToLayer.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/3 17:53:52
功能:
*****************************************************/
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.Editor
{
public class StringToLayer
{
[MenuItem("Evo/Utility/Layer和Tag转换")]
private static void Layer()
{
var sb = new StringBuilder(); //准备模板生成
sb.AppendLine("public class _Const");
sb.AppendLine("{");
for (int i = 0; i < 32; i++) //遍历所有Layer
{
var name = LayerMask.LayerToName(i); //通过Unity的接口拿到Layer名称
name = name
.Replace(" ", "_")
.Replace("&", "_")
.Replace("/", "_")
.Replace(".", "_")
.Replace(",", "_")
.Replace(";", "_")
.Replace("-", "_"); //对常见的特殊字符进行过滤
if (!string.IsNullOrEmpty(name))
sb.AppendFormat("\tpublic const int LAYER_{0} = {1};\n", name.ToUpper(), i);
}
sb.AppendLine("\tpublic const string " + ("Tag_Untagged".ToUpper() + " = "
+ "\"Untagged\";"));
sb.AppendLine("\tpublic const string " + ("Tag_Respawn".ToUpper() + " = "
+ "\"Respawn\";"));
sb.AppendLine("\tpublic const string " + ("Tag_Finish".ToUpper() + " = "
+ "\"Finish\";"));
sb.AppendLine("\tpublic const string " + ("Tag_EditorOnly".ToUpper() + "= " + "\"EditorOnly\";"));
sb.AppendLine("\tpublic const string " + ("Tag_MainCamera".ToUpper() + "= " + "\"MainCamera\";"));
sb.AppendLine("\tpublic const string " + ("Tag_Player".ToUpper() + " = "
+ "\"Player\";"));
sb.AppendLine("\tpublic const string " + ("Tag_GameController".ToUpper()
+ " = " + "\"GameController\";")); //把一部分内置Tag先写死
var asset = UnityEditor.AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset"); //取得自定义Tag
if ((asset != null) && (asset.Length > 0))
{
for (int i = 0; i < asset.Length; i++)
{
//创建序列化对象
var so = new UnityEditor.SerializedObject(asset[i]);
var tags = so.FindProperty("tags"); //读取具体字段
for (int j = 0; j < tags.arraySize; ++j)
{
var item = tags.GetArrayElementAtIndex(j).stringValue;
sb.AppendFormat("\tpublic const string TAG_{0} = \"{1}\";\n",
item.ToUpper(), item);
} //添加到模板
}
}
sb.AppendLine("}");
File.WriteAllText("Assets/HotUpdate/GeneratedConst.cs", sb.ToString()); //写入硬盘
UnityEditor.AssetDatabase.Refresh(); //通知Unity刷新
///可新增BudSetting中场景
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 42faa98f2e9e23546949a21ac1629c83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,47 @@
using System;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
namespace Stary.Evo.Editor
{
public class ChangeFont :IFontChange
{
Font toChange;
static Font toChangeFont;
FontStyle toFontStyle;
static FontStyle toChangeFontStyle;
public void Creat()
{
EditorGUILayout.Space();
toChange = (Font) EditorGUILayout.ObjectField(toChange, typeof(Font), true, GUILayout.MinWidth(100),GUILayout.MinHeight(30));
toChangeFont = toChange;
EditorGUILayout.Space();
toFontStyle = (FontStyle) EditorGUILayout.EnumPopup(toFontStyle, GUILayout.MinWidth(100f),GUILayout.MinHeight(30));
toChangeFontStyle = toFontStyle;
EditorGUILayout.Space();
GUI.color = Color.green;
if (GUILayout.Button("更换",GUILayout.MinWidth(200), GUILayout.MinHeight(50)))
{
Change();
}
}
private void Change()
{
var tArray = Resources.FindObjectsOfTypeAll(typeof(Text));
for (int i = 0; i < tArray.Length; i++)
{
Text t = tArray[i] as Text;
//这个很重要博主发现如果没有这个代码unity是不会察觉到编辑器有改动的自然设置完后直接切换场景改变是不被保存的
//如果不加这个代码,在做完更改后,自己随便手动修改下场景里物体的状态,在保存就好了
Undo.RecordObject(t, t.gameObject.name);
t.font = toChangeFont;
t.fontStyle = toChangeFontStyle;
//相当于让他刷新下 不然unity显示界面还不知道自己的东西被换掉了,还会呆呆的显示之前的东西
EditorUtility.SetDirty(t);
}
Debug.Log("Succed");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c8ea60d514c51142a7ede6495a50981
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
/****************************************************
文件CreatWindowFont.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/6 16:31:29
功能:对更换字体功能进行重构
*****************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.Editor
{
public class CreatWindowFont : EditorWindow
{
private FontMode fontMode;
private IFontChange fontChange = new ChangeFont();
private IFontChange defaultfontChange = new DefaultFontEditor();
[MenuItem("Evo/Utility/字体设置", false, 1)]
static void Create()
{
GetWindow<CreatWindowFont>().Show();
}
void OnGUI()
{
fontMode = (FontMode) GUILayout.Toolbar((int) fontMode, Enum.GetNames(typeof(FontMode)));
switch (fontMode)
{
case FontMode.:
fontChange.Creat();
break;
case FontMode.:
defaultfontChange.Creat();
break;
}
}
}
enum FontMode
{
,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e553dbbd76141cb43a861b229a57d619
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,186 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using System;
using System.IO;
using EditorFramework;
using UnityEngine.SceneManagement;
namespace Stary.Evo.Editor
{
/// <summary>
/// 设置字体面板
/// </summary>
public class DefaultFontEditor : IFontChange
{
private static Font m_font;
public void Creat()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("选择默认字体");
EditorGUILayout.Space();
m_font = (Font) EditorGUILayout.ObjectField(m_font, typeof(Font), true,GUILayout.MinWidth(100f),GUILayout.MinHeight(30));
EditorGUILayout.Space();
GUI.color = Color.green;
if (GUILayout.Button("确定",GUILayout.MinWidth(200), GUILayout.MinHeight(50)))
{
ToolCacheManager.SaveFont(m_font);
}
}
[MenuItem("GameObject/UI/DefaultText")]
static void CreatImage()
{
Text text = CreateComponent<Text>();
if (text!=null)
{
text.font = ToolCacheManager.GetFont();
}
}
private static T CreateComponent<T>() where T : Component
{
string name = typeof(T).Name;
GameObject go = new GameObject(name);
Transform parent = GetUIParent();
go.transform.SetParent(parent, false);
T com = go.AddComponent<T>();
return com;
}
private static Transform GetUIParent()
{
Transform select = Selection.activeTransform;
if (select)
{
if (select.GetComponentInParent<Canvas>())
{
return select;
}
else
{
Canvas canvas = select.GetComponentInChildren<Canvas>();
if (canvas == null)
{
canvas = InstanceCanvas(select);
}
return canvas.transform;
}
}
else
{
Canvas canvas = GetCanvasInScene();
if (canvas == null)
{
canvas = InstanceCanvas();
}
return canvas.transform;
}
}
/// <summary>
/// 参考PrefabStageUtility.HandleUIReparentingIfNeeded
/// </summary>
/// <returns></returns>
static Canvas GetCanvasInScene()
{
Scene scene = SceneManager.GetActiveScene();
foreach (GameObject go in scene.GetRootGameObjects())
{
var canvas = go.GetComponentInChildren<Canvas>();
if (canvas != null)
return canvas;
}
return null;
}
/// <summary>
/// 参考PrefabStageUtility.HandleUIReparentingIfNeeded
/// </summary>
/// <returns></returns>
private static Canvas InstanceCanvas(Transform parent = null)
{
const string kUILayerName = "UI";
GameObject root = EditorUtility.CreateGameObjectWithHideFlags("Canvas", HideFlags.DontSave);
root.layer = LayerMask.NameToLayer(kUILayerName);
Canvas canvas = root.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
root.AddComponent<CanvasScaler>();
root.AddComponent<GraphicRaycaster>();
if (parent)
{
canvas.transform.SetParent(parent, false);
}
return canvas;
}
}
/// <summary>
/// 缓存管理类
/// </summary>
public class ToolCacheManager
{
private static string mFontDataPath = "Assets/Main/Tools/Font/FontData.asset";
private static string FontDataFolderPath
{
get { return Application.dataPath + "/Main/Tools/Font"; }
}
/// <summary>
/// 保存设置的字体
/// </summary>
/// <param name="font"></param>
public static void SaveFont(Font font)
{
CheckFontDataFolderExist();
EditorFrameworkUtils.DeleteFile(FontDataFolderPath, "FontData.asset");
FontData data = ScriptableObject.CreateInstance<FontData>();
data.defaultFont = font;
AssetDatabase.CreateAsset(data, mFontDataPath);
EditorUtility.SetDirty(data);
}
/// <summary>
/// 从FontData.asset获取字体
/// </summary>
/// <returns></returns>
public static Font GetFont()
{
FontData fontData = AssetDatabase.LoadAssetAtPath<FontData>(mFontDataPath);
if (fontData != null)
return fontData.defaultFont;
else
return null;
}
/// <summary>
/// 确保存放FontData.asset文件夹存在
/// </summary>
private static void CheckFontDataFolderExist()
{
if (!Directory.Exists(FontDataFolderPath))
{
Directory.CreateDirectory(FontDataFolderPath);
AssetDatabase.Refresh();
}
}
}
[InitializeOnLoad]
/// <summary>
///
/// </summary>
public class UnityUIEvent
{
static UnityUIEvent()
{
ObjectFactory.componentWasAdded += ComponentWasAdded;
}
private static void ComponentWasAdded(Component obj)
{
Text text= obj.gameObject.GetComponent<Text>();
if (text!=null)
{
text.font = ToolCacheManager.GetFont();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2e800f1227426ad4ea0fd607689bf25e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Stary.Evo.Editor
{
[System.Serializable]
public class FontData : ScriptableObject
{
[SerializeField] public Font defaultFont;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95cd4753d6d6804499cc0a96c91cdecc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
/****************************************************
文件IFontChange.cs
作者zz
邮箱:
日期2022/3/6 16:34:36
功能:
*****************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Stary.Evo.Editor
{
interface IFontChange
{
void Creat();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 601a6ca5b11bb6c489a238de6bfb56d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,444 @@
/****************************************************
文件FixPanelScript.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/3 17:53:52
功能:
*****************************************************/
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text;
namespace Stary.Evo
{
namespace AssetEditor
{
public enum Mode
{
,
,
}
enum RuleKey
{
Txt,
Btn,
Img
}
public class FixPanelScript : EditorWindow
{
static Dictionary<string, string> childrenNames; //对象子物体列表
static Dictionary<string, string> Rules = new Dictionary<string, string>()
{
{ "Txt", "Text" }, { "Btn", "Button" }, { "Img", "Image" }
}; //命名规则
static Transform SelTran; //选择的对象
static List<string> names; //重名的子物体
static List<string> btnNames; //所有按钮
TextAsset txt; //Fix选择的脚本
private RuleKey ruleKey;
string input; //Fix规则
private Mode mode;
static Dictionary<string, string> FixChilderNames; //fix新加的子物体
static List<string> FixBtnNames; //fix新加的按钮
const string FixDef = "//FixStartDefiened";
const string FixFind = "//FixStartFind";
const string FixAddEvent = "//FixStartAddEvent";
const string FixEvent = "//FixStartEvent";
private bool isHelp = false;
[MenuItem("Evo/Utility/获取子对象")]
static void Fix()
{
FixPanelScript window =
GetWindow<FixPanelScript>(true, "获取所有子对象");
window.Show();
}
private void OnEnable()
{
isHelp = false;
}
private void OnGUI()
{
mode = (Mode)GUILayout.Toolbar((int)mode, Enum.GetNames(typeof(Mode)));
switch (mode)
{
case Mode.:
Create();
break;
case Mode.:
FixKeyUpdate();
break;
case Mode.:
FixNameUpdate();
break;
}
}
public void Create()
{
EditorGUILayout.Space(10);
SelTran = EditorGUILayout.ObjectField("父物体", SelTran, typeof(Transform), true) as Transform;
EditorGUILayout.Space(10);
CreateButton("Create", CreateFile);
EditorGUILayout.Space(10);
}
public void FixKeyUpdate()
{
EditorGUILayout.Space(10);
txt = EditorGUILayout.ObjectField("脚本", txt, typeof(TextAsset), true) as TextAsset;
EditorGUILayout.Space(10);
SelTran = EditorGUILayout.ObjectField("父物体", SelTran, typeof(Transform), true) as Transform;
EditorGUILayout.Space(10);
ruleKey = (RuleKey)EditorGUILayout.EnumPopup("选择关键字进行更新", ruleKey);
input = ruleKey.ToString();
EditorGUILayout.Space(10);
CreateButton("FixKeyUpdate", FixScripts);
}
public void FixNameUpdate()
{
EditorGUILayout.Space(10);
txt = EditorGUILayout.ObjectField("脚本", txt, typeof(TextAsset), true) as TextAsset;
EditorGUILayout.Space(10);
SelTran = EditorGUILayout.ObjectField("父物体", SelTran, typeof(Transform), true) as Transform;
EditorGUILayout.Space(10);
input = EditorGUILayout.TextField("输入名字指定更新", input);
EditorGUILayout.Space(10);
CreateButton("FixNameUpdate", FixScripts);
}
public void CreateButton(string name, Action action)
{
GUI.color = Color.green;
if (GUILayout.Button(name, GUILayout.MinWidth(200), GUILayout.MinHeight(50)))
{
isHelp = false;
action?.Invoke();
}
GUI.color = Color.white;
if (isHelp)
{
EditorGUILayout.HelpBox("未筛选到物体", MessageType.Warning);
}
}
void FixScripts()
{
FixChilderNames = new Dictionary<string, string>();
FixBtnNames = new List<string>();
names = new List<string>();
string path = AssetDatabase.GetAssetPath(txt); //获取选定脚本的路径
Debug.Log(path);
if (string.IsNullOrEmpty(input))
{
Debug.LogError("Error!!!");
return;
}
GetChildren(SelTran, string.Empty, input);
StreamReader sr = new StreamReader(path, Encoding.UTF8);
string msg = sr.ReadToEnd();
FixDealScript(ref msg);
sr.Close();
StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8);
sw.Write(msg);
sw.Close();
AssetDatabase.Refresh();
Debug.Log("fix ok------");
}
void FixDealScript(ref string msg)
{
StringBuilder sbDef = new StringBuilder();
Debug.Log(FixChilderNames.Count);
foreach (KeyValuePair<string, string> item in FixChilderNames)
{
Debug.Log(item.Key);
}
var dic = FixChilderNames.GetEnumerator();
while (dic.MoveNext())
{
string[] names = dic.Current.Key.Split('/');
string name = names[names.Length - 1];
string value = dic.Current.Value;
if (!msg.Contains(name))
{
sbDef.AppendFormat("\tprivate {0} {1};", value, name);
sbDef.AppendLine();
}
}
sbDef.AppendLine("\t" + FixDef);
Debug.Log(sbDef.ToString());
StringBuilder sbFind = new StringBuilder();
dic = FixChilderNames.GetEnumerator();
while (dic.MoveNext())
{
string[] names = dic.Current.Key.Split('/');
string name = names[names.Length - 1];
string value = dic.Current.Value;
string path = dic.Current.Key;
path = path.Substring(SelTran.name.Length + 1);
if (!msg.Contains(name))
{
sbFind.AppendFormat("\t\t{0} = transform.Find<{2}>(\"{1}\");", name, path, value);
sbFind.AppendLine();
}
if (value == Rules["Btn"]) FixBtnNames.Add(name);
}
sbFind.AppendLine("\t\t" + FixFind);
StringBuilder sbAddEvent = new StringBuilder();
for (int i = 0; i < FixBtnNames.Count; i++)
{
if (!msg.Contains(FixBtnNames[i]))
{
sbAddEvent.AppendFormat("\t\tEventTriggerListener.Get({0}.gameObject).onClick = BtnClicked;",
FixBtnNames[i]);
sbAddEvent.AppendLine();
}
}
sbAddEvent.AppendLine("\t\t" + FixAddEvent);
StringBuilder sbEvent = new StringBuilder();
for (int i = 0; i < FixBtnNames.Count; i++)
{
if (!msg.Contains(FixBtnNames[i]))
{
sbEvent.AppendFormat("\t\telse if({0}.gameObject==go)", FixBtnNames[i]);
CreatEvent(sbEvent, i);
}
}
sbEvent.AppendLine("\t\t" + FixEvent);
Debug.Log(msg);
msg = msg.Replace(FixDef, sbDef.ToString()).Replace(FixFind, sbFind.ToString())
.Replace(FixAddEvent, sbAddEvent.ToString()).Replace(FixEvent, sbEvent.ToString());
Debug.Log(msg);
}
void CreateFile()
{
childrenNames = new Dictionary<string, string>();
names = new List<string>();
btnNames = new List<string>();
GetChildren(SelTran);
CreateScript(Application.dataPath + "/" + SelTran.name.Replace(" ", "") + ".cs",
DealScript().ToString());
}
void GetChildren(Transform tran, string name = "", string rule = "")
{
if (string.IsNullOrEmpty(name)) name = tran.name;
int childNum = tran.childCount;
if (string.IsNullOrEmpty(rule)) //Create
{
Debug.Log(AddName(tran.name) + "进入1");
string value = AddName(tran.name);
if (!string.IsNullOrEmpty(value))
{
Debug.Log("进入" + tran.name);
childrenNames.Add(name, value); //符合规则,加入列表
}
}
else //fix
{
string valuefix = AddName(tran.name, rule);
if (!string.IsNullOrEmpty(valuefix)) FixChilderNames.Add(name, valuefix);
}
if (childNum == 0)
{
return;
}
else
{
string temp = name;
for (int i = 0; i < childNum; i++)
{
temp = name;
temp = temp + "/" + tran.GetChild(i).name;
GetChildren(tran.GetChild(i), temp, rule);
}
}
}
/// <summary>
///检测关键字是否包含返回字段
/// </summary>
/// <param name="name">新增的物体</param>
/// <param name="rule">关键字段</param>
/// <returns></returns>
string AddName(string name, string rule = "")
{
if (names.Contains(name))
{
Debug.LogError(name + "重名!!!!");
}
foreach (KeyValuePair<string, string> item in Rules)
{
if (name.Contains(item.Key))
{
if (string.IsNullOrEmpty(rule)) //Create
{
return item.Value;
}
else //fix
{
Debug.Log(item + "----------------");
Debug.Log(name + "----------------" + rule);
if (name.Contains(rule) && mode == Mode.) return item.Value;
else if (name.Equals(rule) && mode == Mode.) return item.Value;
else
{
isHelp = true;
}
}
}
}
return string.Empty;
}
StringBuilder DealScript()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("using UnityEngine;");
sb.AppendLine("using UnityEngine.UI;");
sb.AppendLine("using System.Text;");
sb.AppendLine("using WFramework;");
sb.AppendLine();
sb.AppendLine();
sb.AppendFormat("public class {0} : MonoBehaviour ", SelTran.name.Replace(" ", ""));
sb.AppendLine();
sb.AppendLine("{");
var dic = childrenNames.GetEnumerator();
while (dic.MoveNext())
{
string[] names = dic.Current.Key.Split('/');
string name = names[names.Length - 1];
string value = dic.Current.Value;
sb.AppendFormat("\tprivate {0} {1};", value, name);
sb.AppendLine();
}
sb.AppendLine("\t" + FixDef);
sb.AppendLine("\tvoid Awake() {");
sb.AppendLine("\t\tInit();");
sb.AppendLine("\t}");
sb.AppendLine();
sb.AppendLine("\tvoid Init() {");
sb.AppendLine();
dic = childrenNames.GetEnumerator();
Debug.Log(childrenNames.Count);
while (dic.MoveNext())
{
string[] names = dic.Current.Key.Split('/');
string name = names[names.Length - 1];
string value = dic.Current.Value;
string path = dic.Current.Key;
path = path.Substring(SelTran.name.Length + 1);
sb.AppendFormat("\t\t{0} =transform.Find<{2}>(\"{1}\");", name, path, value);
sb.AppendLine();
if (value == Rules["Btn"]) btnNames.Add(name);
}
sb.AppendLine("\t\t" + FixFind);
sb.AppendLine();
for (int i = 0; i < btnNames.Count; i++)
{
sb.AppendFormat("\t\tEventTriggerListener.Get({0}.gameObject).onClick = BtnClicked;", btnNames[i]);
sb.AppendLine();
}
sb.AppendLine("\t\t" + FixAddEvent);
sb.AppendLine();
sb.AppendLine("\t}");
sb.AppendLine();
sb.AppendLine("\tvoid BtnClicked(GameObject go)");
sb.AppendLine("\t{");
for (int i = 0; i < btnNames.Count; i++)
{
if (i == 0)
{
sb.AppendFormat("\t\tif({0}.gameObject==go)", btnNames[i]);
}
else
{
sb.AppendFormat("\t\telse if({0}.gameObject==go)", btnNames[i]);
}
CreatEvent(sb, i);
}
sb.AppendLine("\t\t" + FixEvent);
sb.AppendLine("\t}");
sb.AppendLine();
sb.AppendLine("}");
return sb;
}
/// <summary>
/// 创建方法里的Event
/// </summary>
/// <param name="sb"></param>
/// <param name="index"></param>
private void CreatEvent(StringBuilder sb, int index = 0)
{
sb.AppendLine();
sb.AppendLine("\t\t{");
sb.AppendFormat("\t\t\tDebug.Log({0}+\"Clicked\");", btnNames[index]);
sb.AppendLine();
sb.AppendLine("\t\t}");
}
void CreateScript(string path, string msg)
{
StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8);
sw.Write(msg);
sw.Flush();
sw.Close();
Debug.Log("ok----------");
AssetDatabase.Refresh();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a023dc093dd405418446c92e00b05a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,71 @@
using System;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Stary.Evo.Editor
{
public static class DragAndDropTool
{
public class DragInfo
{
public bool Dragging;
public bool EnterArea;
public bool Complete;
public Object[] ObjectReferences => DragAndDrop.objectReferences;
public string[] Paths => DragAndDrop.paths;
public DragAndDropVisualMode VisualMode => DragAndDrop.visualMode;
public int ActiveControlID => DragAndDrop.activeControlID;
}
private static DragInfo mDragInfo = new DragInfo();
private static bool mDragging;//拖拽进区域为ture
private static bool mEnterArea;//拖拽进content区域为ture
private static bool mComplete;
/// <summary>
/// 拖拽通用方法
/// </summary>
/// <param name="content">检测区域</param>
/// <param name="OnComplete">完成后的时间利用泛型传进详细的DragInfo</param>
/// <param name="mode"></param>
public static void Drag(Rect content,Action<DragInfo> onComplete=null, DragAndDropVisualMode mode = DragAndDropVisualMode.Generic)
{
Event e=Event.current;
if (e.type == EventType.DragUpdated)
{
mComplete = false;
mDragging = true;
mEnterArea = content.Contains(e.mousePosition);
if (mEnterArea)
{
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
e.Use();
}
}
else if (e.type == EventType.DragPerform)
{
mComplete = true;
mDragging = false;
mEnterArea = content.Contains(e.mousePosition);
DragAndDrop.AcceptDrag();
e.Use();
}
else if (e.type == EventType.DragExited)
{
mComplete = true;
mDragging = false;
mEnterArea = content.Contains(e.mousePosition);
}
mDragInfo.Complete = mComplete && e.type == EventType.Used;
mDragInfo.EnterArea = mEnterArea;
mDragInfo.Dragging = mDragging;
if (mDragInfo.EnterArea && mDragInfo.Complete && !mDragInfo.Dragging)
{
onComplete?.Invoke(mDragInfo);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a676d8ce2e354573ae2984b51cff3b4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
/****************************************************
文件EditorWindowLayout.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/3 17:53:52
功能:
*****************************************************/
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.Editor
{
public class EditorWindowLayout : UnoEditorLayout
{
public EditorWindowLayout(EditorWindow win)
{
_win = win;
Margin = new Vector4(2, 2, 2, 2);
IndentSize = 12;
}
private readonly EditorWindow _win;
public Vector4 Margin { get; set; }
public void Begin()
{
var rect = new Rect(Margin.x, Margin.y, _win.position.width - Margin.x - Margin.z, _win.position.height - Margin.y - Margin.w);
Begin(rect);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a7321934936ed334d81018ca35edf12e
timeCreated: 1511574046
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,68 @@
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.Editor
{
public class FolderField : GUIBase
{
public FolderField(string path = "Assets/", string folder = "Assets", string title = "Select Folder",
string defaultName = "")
{
mPath = path;
Title = title;
Folder = folder;
DefaultName = defaultName;
}
protected string mPath;
public string Path => mPath;
public string Title;
public string Folder;
public string DefaultName;
public void SetPath(string path)
{
mPath = path;
}
public override void OnGUI(Rect position)
{
base.OnGUI(position);
var rects = position.VerticalSplit(position.width - 30);
var leftRect = rects[0];
var rightRect = rects[1];
var currentGUIEnabled = GUI.enabled;
GUI.enabled = false;
EditorGUI.TextField(leftRect, mPath); // 左边的 rect width - 30
GUI.enabled = currentGUIEnabled;
if (GUI.Button(rightRect,GUIContents.Folder)) // 右边的 rect 30
{
var path = EditorUtility.OpenFolderPanel(Title, Folder, DefaultName);
if (!string.IsNullOrEmpty(path) && path.IsDirectory())
{
mPath = path.ToAssetsPath()+"/";
}
}
DragAndDropTool.Drag(leftRect, OnComplete);
}
private void OnComplete(DragAndDropTool.DragInfo info)
{
if (info.Paths[0].IsDirectory())
{
mPath = info.Paths[0]+"/";
}
}
protected override void OnDispose()
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 40b6b51b847f2bd41a6547694b94611f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
using System;
using UnityEngine;
namespace Stary.Evo.Editor
{
public abstract class GUIBase :IDisposable
{
public bool mDisposed { get; protected set; }
public Rect mPosition { get; protected set; }
public virtual void OnGUI(Rect position)
{
mPosition = position;
}
public void Dispose()
{
if(mDisposed) return;
OnDispose();
mDisposed = true;
}
protected abstract void OnDispose();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0bfad764209a8ea469e5934f7cfae937
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.Editor
{
public class GUIContents
{
public static GUIContent Folder = EditorGUIUtility.IconContent("Folder Icon");
public static GUIContent FolderEmpty = EditorGUIUtility.IconContent("FolderEmpty Icon");
// 等等
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 314d1168ba299ae488188c679eabf657
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,123 @@
using UnityEngine;
namespace Stary.Evo.Editor
{
public enum AnchorType
{
UpperLeft = 0,
UpperCenter = 1,
UpperRight = 2,
MiddleLeft = 3,
MiddleCenter = 4,
MiddleRight = 5,
LowerLeft = 6,
LowerCenter = 7,
LowerRight = 8
}
public static class RectExtension
{
/// <summary>
///根据外层窗口缩放
/// </summary>
/// <param name="rect"></param>
/// <param name="type">描点位置</param>
/// <param name="pixel">缩放大小</param>
/// <returns></returns>
public static Rect Zoom(this Rect rect, AnchorType type, float pixel)
{
return Zoom(rect, type, new Vector2(pixel, pixel));
}
public static Rect Zoom(this Rect rect, AnchorType type, Vector2 pixelOffset)
{
float tempW = rect.width + pixelOffset.x;
float tempH = rect.height + pixelOffset.y;
switch (type)
{
case AnchorType.UpperLeft:
break;
case AnchorType.UpperCenter:
rect.x -= (tempW - rect.width) / 2;
break;
case AnchorType.UpperRight:
rect.x -= tempW - rect.width;
break;
case AnchorType.MiddleLeft:
rect.y -= (tempH - rect.height) / 2;
break;
case AnchorType.MiddleCenter:
rect.x -= (tempW - rect.width) / 2;
rect.y -= (tempH - rect.height) / 2;
break;
case AnchorType.MiddleRight:
rect.y -= (tempH - rect.height) / 2;
rect.x -= tempW - rect.width;
break;
case AnchorType.LowerLeft:
rect.y -= tempH - rect.height;
break;
case AnchorType.LowerCenter:
rect.y -= tempH - rect.height;
rect.x -= (tempW - rect.width) / 2;
break;
case AnchorType.LowerRight:
rect.y -= tempH - rect.height;
rect.x -= tempW - rect.width;
break;
}
rect.width = tempW;
rect.height = tempH;
return rect;
}
public static Rect MoveDown(this Rect r, float pixels = 1)
{
r.y += pixels;
return r;
}
public static Rect CutRight(this Rect r, float pixels)
{
r.xMax -= pixels;
return r;
}
public static Rect CutLeft(this Rect r, float pixels)
{
r.xMin += pixels;
return r;
}
public static Rect Cut(this Rect r, float pixels)
{
return r.Margin(-pixels);
}
public static Rect Margin(this Rect r, float pixels)
{
r.xMax += pixels;
r.xMin -= pixels;
r.yMax += pixels;
r.yMin -= pixels;
return r;
}
public static Rect[] VerticalSplit(this Rect r, float width, float padding = 0, bool justMid = true)
{
if (justMid)
return new Rect[2]
{
r.CutRight((int) (r.width - width)).CutRight(padding).CutRight(-Mathf.CeilToInt(padding / 2f)),
r.CutLeft(width).CutLeft(padding).CutLeft(-Mathf.FloorToInt(padding / 2f))
};
return new Rect[2]
{
r.CutRight((int) (r.width - width)).Cut(padding).CutRight(-Mathf.CeilToInt(padding / 2f)),
r.CutLeft(width).Cut(padding).CutLeft(-Mathf.FloorToInt(padding / 2f))
};
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38c8aee9816a74cb4ae2151017cfe040
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,73 @@
/****************************************************
文件EditorWindowLayout.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/3 17:53:52
功能:
*****************************************************/
using System;
using System.Text;
namespace Stary.Evo.Editor
{
public class ScriptBuilder
{
private readonly string NEW_LINE = Environment.NewLine;
public ScriptBuilder()
{
builder = new StringBuilder();
}
private StringBuilder builder;
public int Indent { get; set; }
private int currentCharIndex;
public void Write(string val, bool noAutoIndent = false)
{
if (!noAutoIndent)
val = GetIndents() + val;
if (currentCharIndex == builder.Length)
builder.Append(val);
else
builder.Insert(currentCharIndex, val);
currentCharIndex += val.Length;
}
public void WriteLine(string val, bool noAutoIndent = false)
{
Write(val + NEW_LINE);
}
public int WriteCurlyBrackets(bool increaseIndent = false)
{
var openBracket = GetIndents() + "{" + NEW_LINE;
var closeBracket = GetIndents() + "}" + NEW_LINE;
Write(openBracket + closeBracket, true);
currentCharIndex -= closeBracket.Length;
if(increaseIndent)
Indent++;
return closeBracket.Length;
}
public void GetOutOfCurlyBrackets(int lastCurlyBracketSize, bool decreaseIndent = false)
{
currentCharIndex += lastCurlyBracketSize;
if (decreaseIndent)
Indent--;
}
public string GetIndents()
{
var str = "";
for (var i = 0; i < Indent; i++)
str += " ";
return str;
}
public override string ToString()
{
return builder.ToString();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4a700812e31c5d849b411e1d044687ef
timeCreated: 1582186171

View File

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

View File

@@ -0,0 +1,30 @@
using System.IO;
using UnityEngine;
namespace Stary.Evo.Editor
{
public static class StringExtension
{
/// <summary>
/// 是否是一个文件夹
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
public static bool IsDirectory(this string self)
{
var fileInfo = new FileInfo(self);
if ((fileInfo.Attributes & FileAttributes.Directory) != 0)
{
return true;
}
return false;
}
public static string ToAssetsPath(this string self)
{
var assetsFullPath = Path.GetFullPath(Application.dataPath);
return "Assets" + Path.GetFullPath(self).Substring(assetsFullPath.Length).Replace("\\", "/");
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: abbb0ff31d684ebfb0b17b80691110af
timeCreated: 1635478967

View File

@@ -0,0 +1,448 @@
/****************************************************
文件UnoEditorLayout.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/3 17:53:52
功能:
*****************************************************/
using UnityEditor;
using UnityEngine;
using System;
namespace Stary.Evo.Editor
{
public class UnoEditorLayout
{
public float LineSpacing = 2;
public int IndentCount { get; set; }
public float IndentSize = 15;
private float _originX;
private Rect _rootRect;
public Rect RootRect
{
get
{
var rect = new Rect(_rootRect);
rect.x = _originX + IndentSize * IndentCount;
return rect;
}
}
public void Begin(Rect rect)
{
IndentCount = 0;
_rootRect = rect;
_originX = _rootRect.x;
}
/// <summary>
/// 移至新的一行
/// </summary>
/// <param name="height"></param>
/// <returns>返回前一行的Rect</returns>
public Rect NextLine(float height = 0, float lineSpacing = -1)
{
if (height <= 0)
height = EditorGUIUtility.singleLineHeight;
if (lineSpacing < 0)
lineSpacing = LineSpacing;
var rect = new Rect(RootRect);
rect.height = height;
var delta = height + lineSpacing;
_rootRect.y += delta;
_rootRect.height -= delta;
return rect;
}
public Rect SingleLine(float height = 0f)
{
return CreateRow(new[] { LayoutDef.Any() }, height)[0];
}
public Rect[] CreateRow(LayoutDef[] lDefs, float height = 0f, float gap = 4f, Rect? rect = null, Rect[] result = null)
{
if (height <= 0)
height = EditorGUIUtility.singleLineHeight;
return CreateRects(lDefs, false, height, gap, rect, result);
}
public static Rect[] CreateRow(LayoutDef[] lDefs, Rect rect, float height = 0f, float gap = 4f, Rect[] result = null)
{
return CreateRects(lDefs, rect, false, height, gap, result);
}
public Rect[] CreateColum(LayoutDef[] lDefs, float width = 0f, float gap = 4f, Rect? rect = null, Rect[] result = null)
{
return CreateRects(lDefs, true, width, gap, rect, result);
}
public static Rect[] CreateColum(LayoutDef[] lDefs, Rect rect, float width = 0f, float gap = 4f, Rect[] result = null)
{
return CreateRects(lDefs, rect, true, width, gap, result);
}
private Rect[] CreateRects(LayoutDef[] lDefs, bool isVertical, float otherEdgeLength = 0f, float gap = 4, Rect? rect = null, Rect[] result = null)
{
rect = rect ?? RootRect;
return CreateRects(lDefs, rect.Value, isVertical, otherEdgeLength, gap, result);
}
public static Rect[] CreateRects(LayoutDef[] lDefs, Rect r, bool isVertical, float otherEdgeLength = 0f, float gap = 4, Rect[] result = null)
{
if (result != null && result.Length != lDefs.Length)
throw new ArgumentException("the length of result does not match to length of lDefs");
if (otherEdgeLength <= 0)
{
if (isVertical)
otherEdgeLength = r.width;
else
otherEdgeLength = r.height;
}
var totalSpace = isVertical ? r.height : r.width;
var spaceLeft = totalSpace;
var currentPos = isVertical ? r.y : r.x;
var anyCount = lDefs.Length;
result = result ?? new Rect[lDefs.Length];
for (var i = 0; i < lDefs.Length; i++)
{
var ld = lDefs[i];
float val = 0;
if (!ld.IsAny)
{
val = ld.RatioWise ? GetPercentageVal(ld, totalSpace, lDefs.Length, gap) : ld.Value;
val = ClampValueFromVector2(val, ld.MinSize, ld.MaxSize, isVertical);
spaceLeft -= val;
anyCount--;
}
else if (ld.Value > 0)
{
val = ld.Value + gap;
spaceLeft -= val;
anyCount--;
}
if (isVertical)
{
result[i].height = val;
result[i].width = otherEdgeLength;
result[i].x = r.x;
}
else
{
result[i].width = val;
result[i].height = otherEdgeLength;
result[i].y = r.y;
}
spaceLeft -= gap;
}
spaceLeft += gap;
var anySize = spaceLeft / anyCount;
for (var i = 0; i < lDefs.Length; i++)
{
var ld = lDefs[i];
if (!ld.IsAny || !ld.MinSize.HasValue)
continue;
var size = 0f;
var minSize = isVertical ? ld.MinSize.Value.y : ld.MinSize.Value.x;
if (anySize < minSize)
size = minSize;
if (size <= 0)
continue;
anyCount--;
spaceLeft -= size;
lDefs[i].Value = size;
if (isVertical)
result[i].height = size;
else
result[i].width = size;
}
anySize = spaceLeft / anyCount;
for (var i = 0; i < lDefs.Length; i++)
{
var ld = lDefs[i];
if (!ld.IsAny || !ld.MaxSize.HasValue)
continue;
var size = 0f;
var maxSize = isVertical ? ld.MaxSize.Value.y : ld.MaxSize.Value.x;
if (anySize > maxSize)
size = maxSize;
if (size <= 0)
continue;
anyCount--;
spaceLeft -= size;
lDefs[i].Value = size;
if (isVertical)
result[i].height = size;
else
result[i].width = size;
}
anySize = spaceLeft / anyCount;
for (var i = 0; i < lDefs.Length; i++)
{
var ld = lDefs[i];
float val;
if (isVertical)
{
if (ld.IsAny)
{
result[i].height = anySize;
val = anySize;
}
else
val = result[i].height;
result[i].y = currentPos;
}
else
{
if (ld.IsAny)
{
result[i].width = anySize;
val = anySize;
}
else
val = result[i].width;
result[i].x = currentPos;
}
currentPos += val + gap;
//Debug.Log(result[i].x + ", " + result[i].width);
}
return result;
}
public Rect[][] CreateGrid(LayoutDef[] hlDefs, LayoutDef[] vlDefs, float gap = 4, Rect? rect = null)
{
rect = rect ?? RootRect;
return CreateGrid(hlDefs, vlDefs, rect.Value, gap);
}
public static Rect[][] CreateGrid(LayoutDef[] hlDefs, LayoutDef[] vlDefs, Rect rect, float gap = 4)
{
var result = new Rect[vlDefs.Length][];
var row = CreateRects(hlDefs, rect, false, 0, gap);
result[0] = row;
for (var i = 1; i < vlDefs.Length; i++)
{
result[i] = new Rect[row.Length];
for (var j = 0; j < row.Length; j++)
{
result[i][j] = row[j];
}
}
var col = CreateRects(vlDefs, rect, true, 0, gap);
for (var i = 0; i < vlDefs.Length; i++)
{
for (var j = 0; j < result[i].Length; j++)
{
result[i][j].height = col[i].height;
result[i][j].y = col[i].y;
}
}
return result;
}
/// <summary>
///
/// </summary>
/// <param name="hlDefs"></param>
/// <param name="vlDefs"></param>
/// <param name="gap"></param>
/// <param name="rect"></param>
/// <returns>result[i] represents a row</returns>
public Rect[][] CreateGridUnevenColum(LayoutDef[][] hlDefs, LayoutDef[] vlDefs, float gap = 4, Rect? rect = null)
{
rect = rect ?? RootRect;
return CreateGridUnevenColum(hlDefs, vlDefs, rect.Value, gap);
}
/// <summary>
///
/// </summary>
/// <param name="hlDefs"></param>
/// <param name="vlDefs"></param>
/// <param name="gap"></param>
/// <param name="rect"></param>
/// <returns>result[i] represents a row</returns>
public static Rect[][] CreateGridUnevenColum(LayoutDef[][] hlDefs, LayoutDef[] vlDefs, Rect rect, float gap = 4)
{
if (hlDefs.Length != vlDefs.Length)
throw new ArgumentException("the length of hlDefs must match with the length of vlDefs");
var result = new Rect[vlDefs.Length][];
for (var i = 0; i < vlDefs.Length; i++)
{
result[i] = CreateRects(hlDefs[i], rect, false, 0, gap);
}
var col = CreateRects(vlDefs, rect, true, 0, gap);
for (var i = 0; i < vlDefs.Length; i++)
{
var row = result[i];
for (var j = 0; j < row.Length; j++)
{
row[j].height = col[i].height;
row[j].y = col[i].y;
}
}
return result;
}
/// <summary>
///
/// </summary>
/// <param name="hlDefs"></param>
/// <param name="vlDefs"></param>
/// <param name="gap"></param>
/// <param name="rect"></param>
/// <returns>result[i] represents a colum</returns>
public Rect[][] CreateGridUnevenRow(LayoutDef[] hlDefs, LayoutDef[][] vlDefs, float gap = 4, Rect? rect = null)
{
rect = rect ?? RootRect;
return CreateGridUnevenRow(hlDefs, vlDefs, rect.Value, gap);
}
/// <summary>
///
/// </summary>
/// <param name="hlDefs"></param>
/// <param name="vlDefs"></param>
/// <param name="gap"></param>
/// <param name="rect"></param>
/// <returns>result[i] represents a colum</returns>
public static Rect[][] CreateGridUnevenRow(LayoutDef[] hlDefs, LayoutDef[][] vlDefs, Rect rect, float gap = 4)
{
if (hlDefs.Length != vlDefs.Length)
throw new ArgumentException("the length of hlDefs must match with the length of vlDefs");
var result = new Rect[vlDefs.Length][];
for (var i = 0; i < vlDefs.Length; i++)
{
result[i] = CreateRects(vlDefs[i], rect, true, 0, gap);
}
var row = CreateRects(hlDefs, rect, false, 0, gap);
for (var i = 0; i < row.Length; i++)
{
for (var j = 0; j < result[i].Length; j++)
{
result[i][j].width = row[i].width;
result[i][j].x = row[i].x;
}
}
return result;
}
public static Vector2 EvaluateTextSize(GUIContent text, GUIStyle guiStyle = null)
{
if (guiStyle == null)
guiStyle = EditorStyles.label;
return guiStyle.CalcSize(text);
}
public static Vector2 EvaluateTextSize(string text, GUIStyle guiStyle = null)
{
return EvaluateTextSize(new GUIContent(text), guiStyle);
}
private static float ClampValueFromVector2(float val, Vector2? min, Vector2? max, bool byY)
{
if (byY)
{
return Mathf.Clamp(val,
min.HasValue ? min.Value.y : float.MinValue,
max.HasValue ? max.Value.y : float.MaxValue);
}
else
{
return Mathf.Clamp(val,
min.HasValue ? min.Value.x : float.MinValue,
max.HasValue ? max.Value.x : float.MaxValue);
}
}
private static float GetPercentageVal(LayoutDef ld, float totalSpace, int numChildren, float gap)
{
return (totalSpace - (numChildren - 1) * gap) * ld.Value * .01f;
}
}
public struct LayoutDef
{
public static LayoutDef Any()
{
return new LayoutDef();
}
public static LayoutDef Val(float value)
{
return new LayoutDef { Value = value };
}
public static LayoutDef Percentage(float percentage)
{
return new LayoutDef { Value = percentage, RatioWise = true };
}
public static LayoutDef[] EquallyDivide(int num)
{
var arr = new LayoutDef[num];
//default(LayoutDef) == LayoutDef.Any()
return arr;
}
public float Value { get; set; }
public bool RatioWise { get; set; }
public Vector2? MinSize { get; private set; }
public Vector2? MaxSize { get; private set; }
public LayoutDef WithMinSize(Vector2 minSize)
{
MinSize = minSize;
return this;
}
public LayoutDef WithMaxSize(Vector2 maxSize)
{
MaxSize = maxSize;
return this;
}
public LayoutDef WithMinSize(float x, float y)
{
MinSize = new Vector2(x, y);
return this;
}
public LayoutDef WithMaxSize(float x, float y)
{
MaxSize = new Vector2(x, y);
return this;
}
public bool IsAny
{
get { return Value == 0; }
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6fa325b0a38cdb84bb0d9125492a3211
timeCreated: 1597995623

View File

@@ -0,0 +1,292 @@
/****************************************************
文件UtilityEditor.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/3 17:53:52
功能:
*****************************************************/
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
namespace Stary.Evo.Editor
{
public class UtilityEditor
{
[MenuItem("Evo/Utility/优化/检查模型/一键压缩模型的mesh")]
static void mesh()
{
AssetDatabase.StartAssetEditing();
int count = 0;
foreach (var guid in AssetDatabase.FindAssets("t:Model"))
{
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
var textureImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
if (textureImporter == null)
continue;
if (textureImporter.meshCompression != ModelImporterMeshCompression.Off)
{
textureImporter.meshCompression = ModelImporterMeshCompression.Off;
textureImporter.SaveAndReimport();
count++;
}
}
Debug.Log("压缩了:" + count + "个模型");
AssetDatabase.StopAssetEditing();
AssetDatabase.Refresh();
}
[MenuItem("Evo/Utility/优化/检查模型/选择文件夹压缩模型mesh")]
static void mesh()
{
if (Selection.objects.Length != 1)
{
Debug.LogError("选择一个文件夹");
return;
}
string path = AssetDatabase.GetAssetPath(Selection.objects[0]);
if (!Directory.Exists(path))
{
Debug.Log(path);
return;
}
AssetDatabase.StartAssetEditing();
int count = 0;
string[] filePath = GetFilePath(Selection.objects);
foreach (var guid in AssetDatabase.FindAssets("t:Model", filePath))
{
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
var textureImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
if (textureImporter == null)
continue;
if (textureImporter.meshCompression != ModelImporterMeshCompression.Off)
{
Debug.Log(assetPath);
textureImporter.meshCompression = ModelImporterMeshCompression.Off;
textureImporter.SaveAndReimport();
count++;
}
}
Debug.Log("处理了:" + count + "个模型");
AssetDatabase.StopAssetEditing();
AssetDatabase.Refresh();
}
[MenuItem("Evo/Utility/优化/检查模型/去除文件夹内模型的ReadWrite")]
static void ReadWrite()
{
if (Selection.objects.Length != 1)
{
Debug.LogError("选择一个文件夹");
return;
}
string path = AssetDatabase.GetAssetPath(Selection.objects[0]);
if (!Directory.Exists(path))
{
Debug.Log(path);
return;
}
AssetDatabase.StartAssetEditing();
int count = 0;
string[] filePath = GetFilePath(Selection.objects);
foreach (var guid in AssetDatabase.FindAssets("t:Model", filePath))
{
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
var textureImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
if (textureImporter == null)
continue;
if (textureImporter.isReadable)
{
Debug.Log(assetPath);
textureImporter.isReadable = false;
textureImporter.SaveAndReimport();
count++;
}
}
Debug.Log("处理了:" + count + "个模型");
AssetDatabase.StopAssetEditing();
AssetDatabase.Refresh();
}
public static string[] GetFilePath(Object[] targets)
{
var folders = new List<string>();
for (int i = 0; i < targets.Length; i++)
{
string assetPath = AssetDatabase.GetAssetPath(targets[i]);
if (Directory.Exists(assetPath))
folders.Add(assetPath);
}
return folders.ToArray();
}
[MenuItem("Evo/Utility/优化/检查模型/一键压缩模型的动画为Optimal")]
static void ()
{
AssetDatabase.StartAssetEditing();
int count = 0;
foreach (var guid in AssetDatabase.FindAssets("t:Model"))
{
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
var textureImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
if (textureImporter == null)
continue;
if (textureImporter.animationCompression != ModelImporterAnimationCompression.Optimal)
{
Debug.Log(assetPath);
textureImporter.animationCompression = ModelImporterAnimationCompression.Optimal;
textureImporter.SaveAndReimport();
count++;
}
}
Debug.Log("处理了:" + count + "个模型");
AssetDatabase.StopAssetEditing();
AssetDatabase.Refresh();
}
[MenuItem("Evo/Utility/优化/检查图片/去除文件夹内图片的ReadWrite")]
static void ReadWrite()
{
if (Selection.objects.Length != 1)
{
Debug.LogError("选择一个文件夹");
return;
}
string path = AssetDatabase.GetAssetPath(Selection.objects[0]);
if (!Directory.Exists(path))
{
Debug.Log(path);
return;
}
AssetDatabase.StartAssetEditing();
int count = 0;
string[] filePath = GetFilePath(Selection.objects);
foreach (var guid in AssetDatabase.FindAssets("t:Texture", filePath))
{
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
var textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (textureImporter == null)
continue;
if (textureImporter.isReadable)
{
Debug.Log(assetPath);
textureImporter.isReadable = false;
textureImporter.SaveAndReimport();
count++;
}
}
Debug.Log("处理了:" + count + "个图片");
AssetDatabase.StopAssetEditing();
AssetDatabase.Refresh();
}
[MenuItem("Evo/Utility/优化/检查图片/去除文件夹内图片的mipmap")]
static void mipmap()
{
if (Selection.objects.Length != 1)
{
Debug.LogError("选择一个文件夹");
return;
}
string path = AssetDatabase.GetAssetPath(Selection.objects[0]);
if (!Directory.Exists(path))
{
Debug.Log(path);
return;
}
AssetDatabase.StartAssetEditing();
int count = 0;
string[] filePath = GetFilePath(Selection.objects);
foreach (var guid in AssetDatabase.FindAssets("t:Texture", filePath))
{
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
var textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (textureImporter == null)
continue;
if (textureImporter.mipmapEnabled)
{
Debug.Log(assetPath);
textureImporter.mipmapEnabled = false;
textureImporter.SaveAndReimport();
count++;
}
}
Debug.Log("处理了:" + count + "个图片");
AssetDatabase.StopAssetEditing();
AssetDatabase.Refresh();
}
private static void DeleteEmptyDirectory(DirectoryInfo directory)
{
DirectoryInfo[] childDirectory = directory.GetDirectories();
if (childDirectory.Length > 0)
{
for (int i = 0; i < childDirectory.Length; i++)
{
DeleteEmptyDirectory(childDirectory[i]);
}
}
if (directory.GetFileSystemInfos().Length == 0)
{
string path = directory.FullName;
int index = path.IndexOf("Assets");
path = path.Remove(0, index);
directory.Delete();
}
}
/// <summary>
/// 打开文件夹
/// </summary>
/// <param name="path"></param>
public static void OpenDirectory(string path)
{
#if UNITY_EDITOR
if (string.IsNullOrEmpty(path)) return;
path = path.Replace("/", "\\");
if (!Directory.Exists(path))
{
Debug.LogError("No Directory: " + path);
return;
}
System.Diagnostics.Process.Start("explorer.exe", path);
#endif
}
/// <summary>
/// 获取文件夹下所有文件路径
/// </summary>
/// <param name="path"></param>
/// <param name="extension">"*.mp3"</param>
/// <returns></returns>
public static string[] GetFiles(string path, string extension = "*")
{
if (File.Exists(path))
{
return Directory.GetFiles(path, extension, SearchOption.AllDirectories);
}
else
{
return null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 58460c25029e7b84c87ff61ae21746a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,560 @@
using System;
using System.Collections.Generic;
using System.IO;
using HybridCLR.Editor;
using HybridCLR.Editor.Commands;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
using YooAsset.Editor;
namespace Stary.Evo.Editor
{
public class MarkAdressable : MonoBehaviour
{
private static AssetBundleCollectorPackage package;
private static string packageName;
private static string[] configNames = new[] { "DomainConfig" };
public static string DomainRoot
{
get { return Application.dataPath + "/Domain"; }
}
// public static string AtlasRemotedRoot
// {
// get { return Application.dataPath + "/AddressableRes/Sprites"; }
// }
//
// public static string SpriteRemotedAtlas
// {
// get { return Application.dataPath + "/AddressableRes/SpriteAtlas"; }
// }
//[MenuItem("Evo/Hotfix/BuildAll")]
public static void BuildAll()
{
PrebuildCommand.GenerateAll();
Debug.Log("UnityEvo:Build【GenerateAll】完成");
AddHotfixAddressableDll();
Debug.Log("UnityEvo:Build【CopyHotfixAddressableDll】完成");
AddMark();
Debug.Log("UnityEvo:Build【MarkAsset】完成");
}
//[MenuItem("Evo/Hotfix/Addressable")]
public static void AddHotfixAddressableDll()
{
CopyDllHotUpdateAssembly(BuildAssetWindow.GetBuildPackageName(), $"{DomainRoot}/{BuildAssetWindow.GetBuildPackageName()}/AddressableRes");
CopyDllStrippedAOTDllOutputRootDir($"{DomainRoot}/{BuildAssetWindow.GetBuildPackageName()}/AddressableRes");
//EditorUtility.DisplayDialog("自动标记", "自动Hotfix成功", "确定");
}
private static void CopyDllHotUpdateAssembly(string domain, string target)
{
//读取打包dll位置
string hotUpdateDir =
$"{SettingsUtil.HybridCLRSettings.hotUpdateDllCompileOutputRootDir}/{EditorUserBuildSettings.activeBuildTarget}";
foreach (var dll in SettingsUtil.HybridCLRSettings.hotUpdateAssemblyDefinitions)
{
if (dll.name.Contains(domain))
{
string hotfixDllPath = $"{hotUpdateDir}/{dll.name}.dll";
string hotfixDllPathTarget =
$"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll.name}.dll.bytes";
string hotfixDllPathPdb = $"{hotUpdateDir}/{dll.name}.pdb";
string hotfixDllPathPdbTarget =
$"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll.name}.pdb.bytes";
FileUtility.Copy(hotfixDllPath, hotfixDllPathTarget, true);
FileUtility.Copy(hotfixDllPathPdb, hotfixDllPathPdbTarget, true);
}
}
foreach (var dll in SettingsUtil.HybridCLRSettings.hotUpdateAssemblies)
{
if (dll.Contains(domain))
{
string hotfixDllPath = $"{hotUpdateDir}/{dll}.dll";
string hotfixDllPathTarget =
$"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll}.dll.bytes";
string hotfixDllPathPdb = $"{hotUpdateDir}/{dll}.pdb";
string hotfixDllPathPdbTarget =
$"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll}.pdb.bytes";
FileUtility.Copy(hotfixDllPath, hotfixDllPathTarget, true);
FileUtility.Copy(hotfixDllPathPdb, hotfixDllPathPdbTarget, true);
}
}
}
private static void CopyDllStrippedAOTDllOutputRootDir(string target)
{
//读取打包dll位置
string hotUpdateDir =
$"{SettingsUtil.HybridCLRSettings.strippedAOTDllOutputRootDir}/{EditorUserBuildSettings.activeBuildTarget}";
foreach (var dll in SettingsUtil.HybridCLRSettings.patchAOTAssemblies)
{
string hotfixDllPath = $"{hotUpdateDir}/{dll}";
string hotfixDllPathTarget =
$"{target}/Dll/{EditorUserBuildSettings.activeBuildTarget}/{dll}.bytes";
FileUtility.Copy(hotfixDllPath, hotfixDllPathTarget, true);
}
}
//[MenuItem("Evo/Hotfix/标记资源")]
public static void AddMark()
{
//copydll
AddHotfixAddressableDll();
//清空旧数据
YooAsset.Editor.AssetBundleCollectorSettingData.ClearAll();
packageName = "";
package = null;
string configPath =
$"Assets/Domain/{BuildAssetWindow.GetBuildPackageName()}/Conf/HotfixMainResDomain.asset";
HotfixMainResDomain hotfixMainResDomain = AssetDatabase.LoadAssetAtPath<HotfixMainResDomain>(configPath);
packageName = hotfixMainResDomain.hotfixMainResDomainEntity.domain;
Mark();
CreateRes(packageName,
$"{DomainRoot}/{BuildAssetWindow.GetBuildPackageName()}/AddressableRes",
$"{DomainRoot}/{BuildAssetWindow.GetBuildPackageName()}/HotUpdate");
EditorUtility.DisplayDialog("自动标记", "自动标记成功", "确定");
}
// [MenuItem("Evo/Hotfix/一键Res")]
public static void CreateRes(string domain, string resPath, string outputPath)
{
FileGet.CreateClass("Res", domain, outputPath,
(a) => { FileGet.CreateContent(a, resPath, "\t"); });
}
#region
public static Dictionary<string, string> addressDic = new Dictionary<string, string>();
public static Dictionary<string, AssetBundleCollectorGroup> collectorGroupDic =
new Dictionary<string, AssetBundleCollectorGroup>();
public static void Mark()
{
addressDic.Clear();
collectorGroupDic.Clear();
///创建分组
string remotedRoot = $"{DomainRoot}/{packageName}/AddressableRes";
DirectoryInfo[] dirs = new DirectoryInfo(remotedRoot).GetDirectories();
var setting = YooAsset.Editor.AssetBundleCollectorSettingData.Setting;
setting.ShowPackageView = true;
setting.UniqueBundleName = true;
//创建Package文件
package = YooAsset.Editor.AssetBundleCollectorSettingData.CreatePackage(packageName);
//检测Packages是否存在TestPackage
package.PackageName = packageName;
package.EnableAddressable = true;
package.IncludeAssetGUID = true;
package.AutoCollectShaders = true;
package.IgnoreRuleName = "NormalIgnoreRule";
//检测Packages是否存在Group
foreach (var info in dirs)
{
string groupName = info.Name;
if (info.Name != "Atlas")
{
AssetBundleCollectorGroup collectorGroup =
YooAsset.Editor.AssetBundleCollectorSettingData.CreateGroup(package, groupName);
collectorGroup.AssetTags = groupName;
if (!collectorGroupDic.ContainsKey(groupName))
{
collectorGroupDic.Add(groupName, collectorGroup);
}
else
{
Debug.LogError("分组 " + groupName + "已存在,请检查资源目录,避免重复");
}
}
AutoMarkRootAddress(info);
// if (info.Name != "SpriteAtlas" && info.Name != "Atlas")
// AutoMark(info.Name);
}
///自动创建图集
Debug.Log("开始创建图集");
AutoCreateSpriteAtlas(remotedRoot);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
MarkStatus();
YooAsset.Editor.AssetBundleCollectorSettingData.FixFile();
// CreateRes();
Debug.Log("MarkAsset Successful");
}
public static void AutoMarkRootAddress(DirectoryInfo dir)
{
List<string> fileInfos = new List<string>();
FilesUtils.GetFiles(dir.FullName, ref fileInfos);
//检测用户config下是否存在config文件
if (dir.Name == "Config")
{
List<string> fileNewInfos = new List<string>();
foreach (var file in fileInfos)
{
if (Path.GetExtension(file) != ".meta")
{
fileNewInfos.Add(file);
}
}
//不存在的配置对象名称
List<string> configNonentity = new List<string>();
//查找不存在的配置文件
for (int i = 0; i < configNames.Length; i++)
{
bool exists = false;
foreach (var filePath in fileNewInfos)
{
// 使用Path获取文件名
string fileName = Path.GetFileNameWithoutExtension(filePath);
if (fileName == configNames[i])
{
exists = true;
break;
}
}
if (!exists)
{
configNonentity.Add(configNames[i]);
}
}
string remotedRoot = Application.dataPath + "/Main/Config";
List<string> mainConfigInfos = new List<string>();
FilesUtils.GetFiles(remotedRoot, ref mainConfigInfos);
//从main文件里拿取指定配置文件
foreach (var config in configNonentity)
{
foreach (var mainConfigInfo in mainConfigInfos)
{
// 使用Path获取文件名
string fileName = Path.GetFileNameWithoutExtension(mainConfigInfo);
if (Path.GetExtension(mainConfigInfo) != ".meta" && fileName.Equals(config))
{
fileInfos.Add(mainConfigInfo);
Debug.LogWarning($"用户资源目录不存在【{config}】文件从Main目录下复制此操作可能导致配置文件不完成请在用户目录配置");
break;
}
}
}
}
if (fileInfos != null && fileInfos.Count > 0)
{
foreach (var file in fileInfos)
{
if (Path.GetExtension(file) != ".meta" && Path.GetExtension(file) != ".spriteatlas")
{
// string[] dirSplit = file.Split(new string[] { $"AddressableRes\\{dir.Name}\\" },
// StringSplitOptions.RemoveEmptyEntries);
// string address = (dirSplit[dirSplit.Length - 1]).Replace("\\", "/");
// Debug.Log("address" + address);
string groupName = dir.Name;
string assetPath = FilesUtils.AbsoluteToRelativePath("Assets", file); //Asset到文件的路径
var guid = AssetDatabase.AssetPathToGUID(assetPath);
var group = collectorGroupDic[groupName];
if (group != null)
{
AssetBundleCollector collector = new AssetBundleCollector()
{
CollectPath = assetPath,
CollectorGUID = guid,
CollectorType = ECollectorType.MainAssetCollector,
AddressRuleName = nameof(AddressByFolderAndFileName),
AssetTags = groupName,
};
//如果是video目录设置
if (groupName == "Video")
{
collector.PackRuleName = nameof(PackVideoFile);
}
YooAsset.Editor.AssetBundleCollectorSettingData.CreateCollector(group, collector);
Debug.Log("GetAssetAddress:" + GetAssetAddress(file));
AddAddressInfo(file, GetAssetAddress(file));
}
else
{
Debug.LogError("分组 = " + groupName + "不存在");
}
}
}
}
}
#region
public static void AutoCreateSpriteAtlas(string domainRootRes)
{
string AtlasRemotedRoot = domainRootRes + "/SpriteAtlas";
string SpriteRemotedAtlas = domainRootRes + "/Sprites";
DirectoryInfo[] remotedirs = new DirectoryInfo(SpriteRemotedAtlas).GetDirectories();
foreach (var info in remotedirs)
{
AddSpriteAtlas(SpriteRemotedAtlas + "/" + info.Name, SpriteRemotedAtlas,
AtlasRemotedRoot, info);
}
}
/// <summary>
/// 自动创建图集
/// </summary>
/// <param name="path">路径</param>
/// <param name="dir">文件夹</param>
private static void AddSpriteAtlas(string path, string atlasRoot, string spriteAtlas, DirectoryInfo dir)
{
var groupname = "SpriteAtlas";
var dirs = dir.GetDirectories();
if (dirs == null || dirs.Length == 0)
{
string name = path.Replace(atlasRoot + "/", string.Empty).Replace("/", "_");
string filePath = $"{spriteAtlas}/{name}.spriteatlas";
// string[] dirSplit =
// filePath.Split(new string[] { $"AddressableRes/{Path.GetFileName(spriteAtlas)}" },
// StringSplitOptions.RemoveEmptyEntries);
// string address = (dirSplit[dirSplit.Length - 1]).Substring(1).Replace("\\", "/");
// Debug.Log("spriteatlasaddress" + address);
int assetIndex = filePath.IndexOf("Assets");
string guidPath = filePath.Remove(0, assetIndex);
if (!File.Exists(filePath))
{
SpriteAtlas atlas = new SpriteAtlas();
//设置打包参数
SpriteAtlasPackingSettings packSetting = new SpriteAtlasPackingSettings()
{
blockOffset = 1,
enableRotation = true,
enableTightPacking = false,
padding = 2,
};
atlas.SetPackingSettings(packSetting);
//设置打包后Texture图集信息
SpriteAtlasTextureSettings textureSettings = new SpriteAtlasTextureSettings()
{
readable = false,
generateMipMaps = false,
sRGB = true,
filterMode = FilterMode.Bilinear,
};
atlas.SetTextureSettings(textureSettings);
//设置平台图集大小压缩等信息
TextureImporterPlatformSettings platformSettings = new TextureImporterPlatformSettings()
{
maxTextureSize = 4096,
format = TextureImporterFormat.Automatic,
crunchedCompression = true,
textureCompression = TextureImporterCompression.Compressed,
compressionQuality = 50,
};
atlas.SetPlatformSettings(platformSettings);
AssetDatabase.CreateAsset(atlas, guidPath);
int pathIndex = path.IndexOf("Assets");
string spritePath = path.Remove(0, pathIndex);
UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(spritePath, typeof(UnityEngine.Object));
atlas.Add(new[] { obj });
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
var guid = AssetDatabase.AssetPathToGUID(guidPath);
var group = collectorGroupDic[groupname];
if (group != null)
{
AssetBundleCollector collector = new AssetBundleCollector()
{
CollectPath = guidPath,
CollectorGUID = guid,
CollectorType = ECollectorType.MainAssetCollector,
AddressRuleName = nameof(AddressByFolderAndFileName),
AssetTags = groupname,
};
YooAsset.Editor.AssetBundleCollectorSettingData.CreateCollector(group, collector);
AddAddressInfo(path, GetAssetAddress(path));
}
else
{
Debug.LogError("分组 = " + GetAssetAddress(path) + "不存在");
}
AssetDatabase.Refresh();
}
else
{
if (dirs.Length > 0)
{
foreach (var info in dirs)
{
AddSpriteAtlas(path + "/" + info.Name, atlasRoot, spriteAtlas, info);
}
}
}
}
#endregion
private static void AddAddressInfo(string assetPath, string address)
{
if (addressDic.ContainsKey(assetPath))
{
Debug.LogError("命名重复,已经存在:" + assetPath);
}
else
{
addressDic.Add(assetPath, address);
}
}
private static string GetAssetAddress(string assetPath)
{
string fileName = Path.GetFileNameWithoutExtension(assetPath);
FileInfo fileInfo = new FileInfo(assetPath);
return $"{fileInfo.Directory.Name}_{fileName}";
}
#endregion
// /// <summary>
// /// 标记是否有打包报错信息
// /// </summary>
// private static bool _isBuildSuccess = true;
//
// [MenuItem("Evo/BuildTools/BuildAdressable")]
// private static void BuildByStatus()
// {
// InitAssetData();
// _isBuildSuccess = true;
// //BuildTools.ClearConsole();
// Application.logMessageReceived += OnLogMessage;
//
// AssetDatabase.Refresh();
// AssetDatabase.Refresh();
// MarkStatus();
// //SetMD5Info();
// AssetDatabase.Refresh();
// Application.logMessageReceived -= OnLogMessage;
// if (!_isBuildSuccess)
// {
// if (EditorUtility.DisplayDialog("打包失败", "请检测报错信息", "确定"))
// {
// // EditorUtility.RevealInFinder(BuildTools.OutPath);
// // BuildTools.OutPath = string.Empty;
// }
// }
// }
/// <summary>
/// 标记为资源分组
/// </summary>
private static void MarkStatus()
{
List<AssetBundleCollectorGroup> deleteList = new List<AssetBundleCollectorGroup>();
for (int i = 0; i < package.Groups.Count; i++)
{
var group = package.Groups[i];
if (group.GroupName != "Default Local Group" && group.GroupName != "Built In Data")
{
if (group.Collectors.Count <= 0)
{
///删除没有资源的分组
deleteList.Add(group);
}
}
}
for (int i = 0; i < deleteList.Count; i++)
{
package.Groups.Remove(deleteList[i]);
}
}
// private static Dictionary<string, MD5Info> _md5Files = new Dictionary<string, MD5Info>();
//
// private static void SetMD5Info()
// {
// _md5Files.Clear();
//
// string path = Application.dataPath.Replace("Assets",
// $"ServerData/{Application.platform}/Release");
// if (Directory.Exists(path))
// {
// DirectoryInfo dir = new DirectoryInfo(path);
// MD5File(dir);
// }
//
// AssetDatabase.Refresh();
// }
//
// private static void MD5File(DirectoryInfo info)
// {
// FileInfo[] files = info.GetFiles();
// if (files.Length > 0)
// {
// for (int i = 0; i < files.Length; i++)
// {
// var file = files[i];
// if (file == null || file.Extension == ".meta")
// {
// continue;
// }
//
// string filePath = file.FullName.Replace(@"\", "/");
// MD5Info md5 = new MD5Info();
// md5.AssetPath = filePath;
// md5.MD5 = FilesUtils.CalculateMD5(file.FullName);
// _md5Files.Add(md5.AssetPath, md5);
// }
// }
//
// DirectoryInfo[] dirs = info.GetDirectories();
// if (dirs != null && dirs.Length > 0)
// {
// for (int i = 0; i < dirs.Length; i++)
// {
// MD5File(dirs[i]);
// }
// }
// }
// private static void OnLogMessage(string condition, string stackTrace, LogType type)
// {
// if (type == LogType.Error)
// {
// if (condition != "EndLayoutGroup: BeginLayoutGroup must be called first.")
// _isBuildSuccess = false;
// }
// }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c4bdee1290d71f34b9346c345de976a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,25 @@
using Sirenix.OdinInspector.Editor;
using UnityEditor;
namespace Stary.Evo.Editor
{
public class MyMenuEditorWindow : OdinMenuEditorWindow
{
[MenuItem("Evo/Utility/优化/一键优化工具")]
private static void OpenWindow()
{
GetWindow<MyMenuEditorWindow>().Show();
}
protected override OdinMenuTree BuildMenuTree()
{
var tree = new OdinMenuTree();
tree.Selection.SupportsMultiSelect = false;
tree.Add("一键批量更改Raycast Target选项", new OneKeyChangeRaycastTarget());
tree.Add("一键查找重复文件", new OneKeySearchDuplicateFiles());
return tree;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6f9dc9117e7bf144b83022ae0e269d99
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,127 @@
/****************************************************
文件OneKeySearchDuplicateFiles.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/7 18:28:50
功能:
*****************************************************/
using Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
namespace Stary.Evo.Editor
{
[TypeInfoBox("批量选中或者取消对应UI上的Raycast")]
public class OneKeyChangeRaycastTarget : SerializedScriptableObject
{
private bool selectRaycastComplete = false;
private bool cancelRaycastComplete = false;
[PreviewField(50)]
[OnValueChanged("SelectRaycastListValueChangeCallBack")]
[HorizontalGroup("Raycast")]
[PropertySpace(10, 10)]
[BoxGroup("Raycast/Left", false)]
[LabelText("需要选中Raycast拖入进来")]
public List<GameObject> SelectRaycastList = new List<GameObject>();
public void SelectRaycastListValueChangeCallBack()
{
selectRaycastComplete = false;
}
[PreviewField(50)]
[OnValueChanged("CancelRaycastListValueChangeCallBack")]
[PropertySpace(10, 10)]
[BoxGroup("Raycast/Right", false)]
[LabelText("需要取消Raycast拖入进来")]
public List<GameObject> CancelRaycastList = new List<GameObject>();
public void CancelRaycastListValueChangeCallBack()
{
cancelRaycastComplete = false;
}
[HideIf("@selectRaycastComplete==true||SelectRaycastList.Count==0")]
[BoxGroup("Raycast/Left")]
[Button("勾选所有射线检测", ButtonSizes.Large, ButtonStyle.FoldoutButton)]
public void SelectRaycast()
{
for (int i = 0; i < SelectRaycastList.Count; i++)
{
if (SelectRaycastList[i] == null)
{
continue;
}
Graphic[] graphicArray = SelectRaycastList[i].GetComponentsInChildren<Graphic>();
for (int k = 0; k < graphicArray.Length; k++)
{
graphicArray[k].raycastTarget = true;
EditorUtility.SetDirty(graphicArray[k]);
}
GameObject tempObject = SelectRaycastList[i];
bool isPrefabInstance = PrefabUtility.IsPartOfPrefabInstance(tempObject);
bool isPrefabAsset = PrefabUtility.IsPartOfPrefabAsset(tempObject);
if (isPrefabAsset)
{
PrefabUtility.SavePrefabAsset(SelectRaycastList[i]);
}
if (isPrefabInstance)
{
PrefabUtility.ApplyPrefabInstance(SelectRaycastList[i], InteractionMode.UserAction);
}
}
selectRaycastComplete = true;
AssetDatabase.Refresh();
}
[HideIf("@cancelRaycastComplete==true||CancelRaycastList.Count==0")]
[BoxGroup("Raycast/Right")]
[Button("取消所有射线检测", ButtonSizes.Large, ButtonStyle.FoldoutButton)]
public void CancelRaycast()
{
for (int i = 0; i < CancelRaycastList.Count; i++)
{
if (CancelRaycastList[i] == null)
{
continue;
}
Graphic[] graphicArray = CancelRaycastList[i].GetComponentsInChildren<Graphic>();
for (int k = 0; k < graphicArray.Length; k++)
{
graphicArray[k].raycastTarget = false;
EditorUtility.SetDirty(graphicArray[k]);
}
GameObject tempObject = CancelRaycastList[i];
bool isPrefabInstance = PrefabUtility.IsPartOfPrefabInstance(tempObject);
bool isPrefabAsset = PrefabUtility.IsPartOfPrefabAsset(tempObject);
if (isPrefabAsset)
{
PrefabUtility.SavePrefabAsset(CancelRaycastList[i]);
}
if (isPrefabInstance)
{
PrefabUtility.ApplyPrefabInstance(CancelRaycastList[i], InteractionMode.UserAction);
}
}
cancelRaycastComplete = true;
AssetDatabase.Refresh();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0fd00bd6b055f134e8be6fb93a5b5ce4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,186 @@
/****************************************************
文件OneKeySearchDuplicateFiles.cs
作者:张铮
邮箱834207172@qq.com
日期2022/3/7 18:28:50
功能:
*****************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using System.Threading;
namespace Stary.Evo.Editor
{
public class OneKeySearchDuplicateFiles : SerializedScriptableObject
{
private bool IsToggled;
private int maxCount;
private IEnumerator<FileInfo> fileInfoIEnumerator;
[PropertySpace(10)]
[Title("需要搜索的文件夹", "默认为Asset全目录", titleAlignment: TitleAlignments.Split)]
[FolderPath(ParentFolder = "Assets", RequireExistingPath = true, AbsolutePath = true)]
[LabelText("选择你要搜索的文件夹")]
public string targetSearchFolder;
[ShowInInspector] [DictionaryDrawerSettings(KeyLabel = "MD5值", ValueLabel = "文件名称列表")]
private Dictionary<string, List<string>> sameMD5Group = new Dictionary<string, List<string>>();
[ShowInInspector] [DictionaryDrawerSettings(KeyLabel = "文件名称", ValueLabel = "绝对路径列表")]
private Dictionary<string, List<string>> sameNameGroup = new Dictionary<string, List<string>>();
[ShowInInspector]
[TitleGroup("重复文件列表")]
[HorizontalGroup("重复文件列表/重复文件")]
[BoxGroup("重复文件列表/重复文件/MD5值相同", CenterLabel = true)]
[PropertyOrder(1000)]
[InfoBox("发现相同MD5值文件.", InfoMessageType.Error, "CheckSameMD5ResultGroup")]
[ShowIf("$CheckSameMD5ResultGroup")]
[DictionaryDrawerSettings(KeyLabel = "MD5值", ValueLabel = "相同MD5值文件名称")]
private Dictionary<string, List<string>> sameMD5Result5Group = new Dictionary<string, List<string>>();
[BoxGroup("重复文件列表/重复文件/名称值相同", CenterLabel = true)]
[ShowInInspector]
[PropertyOrder(1000)]
[InfoBox("发现相同名称文件.", InfoMessageType.Error, "CheckSameNameResultGroup")]
[ShowIf("$CheckSameNameResultGroup")]
[DictionaryDrawerSettings(KeyLabel = "相同文件名称", ValueLabel = "对应绝对路径列表")]
private Dictionary<string, List<string>> sameNameResultGroup = new Dictionary<string, List<string>>();
public bool CheckSameMD5ResultGroup()
{
return sameMD5Result5Group.Count > 0;
}
private bool CheckSameNameResultGroup()
{
return sameNameResultGroup.Count > 0;
}
[PropertySpace(10, 20)]
[ShowIf("@ IsToggled== false")]
[Button("开始搜索", ButtonSizes.Large)]
public void StartSearch()
{
if (string.IsNullOrEmpty(targetSearchFolder))
{
targetSearchFolder = Application.dataPath;
}
ResetData();
DirectoryInfo directoryInfo = new DirectoryInfo(targetSearchFolder);
var filesGroup = directoryInfo.EnumerateFiles("*", SearchOption.AllDirectories)
.Where(x => x.Extension != ".meta");
maxCount = filesGroup.Count();
fileInfoIEnumerator = filesGroup.GetEnumerator();
IsToggled = true;
EditorApplication.update += Updte;
}
private void ResetData()
{
maxCount = 0;
MaxCount = 0;
sameMD5Group.Clear();
sameNameGroup.Clear();
sameMD5Result5Group.Clear();
sameNameResultGroup.Clear();
fileInfoIEnumerator = null;
}
/// <summary>
/// 过滤掉没有重复文件的数据
/// </summary>
private void FilterDictionary()
{
sameMD5Result5Group = sameMD5Group.Where(x => x.Value.Count > 1).ToDictionary(p => p.Key, p => p.Value);
sameNameResultGroup = sameNameGroup.Where(x => x.Value.Count > 1).ToDictionary(p => p.Key, p => p.Value);
}
[ReadOnly]
[ProgressBar(0, "maxCount", DrawValueLabel = true, ValueLabelAlignment = TextAlignment.Left,
ColorGetter = "GetHealthBarColor", Height = 30)]
[ShowInInspector]
[HideLabel]
[ShowIf("@ IsToggled== true")]
public int MaxCount { get; set; } //绘制进度条
private Color GetHealthBarColor(int value)
{
maxCount = maxCount == 0 ? 1 : maxCount;
return Color.Lerp(Color.red, Color.green, Mathf.Pow((float)value / maxCount, 2));
}
public void Updte()
{
if (IsToggled)
{
if (fileInfoIEnumerator.MoveNext())
{
//获取对应Hash值
string hashValue = GetMD5HashFromFile(fileInfoIEnumerator.Current.FullName);
if (!sameMD5Group.ContainsKey(hashValue))
{
sameMD5Group[hashValue] = new List<string>();
}
sameMD5Group[hashValue].Add("名称为:" + fileInfoIEnumerator.Current.Name);
//获取名称
string fileName = fileInfoIEnumerator.Current.Name;
if (!sameNameGroup.ContainsKey(fileName))
{
sameNameGroup[fileName] = new List<string>();
}
sameNameGroup[fileName].Add("路径为:" + fileInfoIEnumerator.Current.FullName);
++MaxCount;
}
else
{
EditorApplication.update -= Updte;
IsToggled = false;
FilterDictionary();
Debug.Log("<color=green>注销</color>");
}
}
}
/// <summary>
/// 计算文件MD5值
/// </summary>
/// <param name="fileFullName"></param>
/// <returns></returns>
public string GetMD5HashFromFile(string fileFullName)
{
try
{
FileStream file = new FileStream(fileFullName, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(file);
file.Close();
return BitConverter.ToString(retVal).ToLower().Replace("-", "");
}
catch
{
throw;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 951c77f73e8aa2f47b895be4fe74da46
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.Editor
{
public static class FileGet
{
public static void CreateContent(StringBuilder variable, string path, string tab)
{
tab += "\t\t";
DirectoryInfo dir = new DirectoryInfo(path);
DirectoryInfo[] first = dir.GetDirectories();
FileInfo[] fil = dir.GetFiles();
if (first.Length > 0)
{
foreach (FileInfo f in fil)
{
CreateFile(variable, f, tab);
}
foreach (DirectoryInfo f in first)
{
CreateFolder(variable, f, tab);
}
}
else
{
foreach (FileInfo f in fil)
{
CreateFile(variable, f, tab);
}
}
}
/// <summary>
/// 生成脚本文件
/// </summary>
/// <param name="className">类名</param>
/// <param name="content">字符串事件</param>
public static void CreateClass(string className, string package, string outputPath,
Action<StringBuilder> content = null)
{
string tdClassName = className;
StringBuilder variable = new StringBuilder();
//variable.Append("using System;\n");
variable.Append("namespace " + "R" + "\n");
variable.Append("{\n");
variable.Append("\tpublic class " + tdClassName + "\n");
variable.Append("\t{\n");
variable.Append("\t\tpublic class " + package + "\n");
variable.Append("\t\t{\n");
content?.Invoke(variable);
variable.Append("\t\t}\n");
variable.Append("\t}\n");
variable.Append("}");
outputPath = $"{outputPath}/{tdClassName}.cs";
if (File.Exists(outputPath))
{
File.Delete(outputPath);
}
FileHelper.WriteFile(outputPath, variable.ToString());
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
/// <summary>
/// 文件夹生成
/// </summary>
/// <param name="folderName"></param>
private static void CreateFolder(StringBuilder variable, DirectoryInfo folderName, string tab)
{
string classname = FilesUtils.ChineseToPinYin(folderName.Name, false);
variable.Append(tab + " public static class " + classname + "\n");
variable.Append(tab + "{\n");
CreateContent(variable, folderName.FullName, tab);
variable.Append(tab + "}\n");
}
/// <summary>
/// 文件生成
/// </summary>
/// <param name="fileName"></param>
private static void CreateFile(StringBuilder variable, FileInfo fileName, string tab)
{
var fullname =System.IO.Path.GetExtension(fileName.FullName);
if (fullname != ".meta"&&fullname!=".hint" )
{
Debug.Log("FileInfo" + fileName.Name);
string[] fileSplit = fileName.FullName.Split(new string[] { "AddressableRes\\" },
StringSplitOptions.RemoveEmptyEntries);
string[] resSplit = fileSplit[fileSplit.Length - 1].Split('\\');
// fileSplit = fileName.FullName.Split(new string[] { $"AddressableRes\\{resSplit[0]}\\" },
// StringSplitOptions.RemoveEmptyEntries);
// string filepath = fileSplit[fileSplit.Length - 1].Replace("\\", "/");
// // 删除文件后缀
// filepath = Path.Combine(
// Path.GetDirectoryName(filepath),
// Path.GetFileNameWithoutExtension(filepath)
// ).Replace("\\", "/");
// Debug.Log(filepath);
string filepath;
if (MarkAdressable.addressDic.ContainsKey(fileName.FullName))
{
filepath = MarkAdressable.addressDic[fileName.FullName];
}
else
{
Debug.LogError("未找到地址,请检查资源自动化标记逻辑:" + fileName.FullName);
filepath = "";
}
string name = FilesUtils.ChineseToPinYin(fileName.Name.Replace(".", "_"), false)
.Replace(" ", "")
.Replace("-", "_")
.Replace(".", "_"); // 保留点号替换为下划线
variable.Append(tab + "public const string " + name + " = \"" + filepath + "\";\n");
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17d52df7853411b46bc8e8ecf271db8a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Stary.Evo.Editor
{
/// <summary>
/// 文件辅助类
/// </summary>
public static class FileHelper
{
/// <summary>
/// 编码方式
/// </summary>
private static readonly Encoding Encoding = Encoding.UTF8;
/// <summary>
/// 递归取得文件夹下文件
/// </summary>
/// <param name="dir"></param>
/// <param name="list"></param>
public static void GetFiles(string dir, List<string> list)
{
GetFiles(dir, list, new List<string>());
}
/// <summary>
/// 递归取得文件夹下文件
/// </summary>
/// <param name="dir"></param>
/// <param name="list"></param>
/// <param name="fileExtsions"></param>
public static void GetFiles(string dir, List<string> list, List<string> fileExtsions)
{
//添加文件
string[] files = Directory.GetFiles(dir);
if (fileExtsions.Count > 0)
{
foreach (string file in files)
{
string extension = Path.GetExtension(file);
if (extension != null && fileExtsions.Contains(extension))
{
list.Add(file);
}
}
}
else
{
list.AddRange(files);
}
//如果是目录,则递归
DirectoryInfo[] directories = new DirectoryInfo(dir).GetDirectories();
foreach (DirectoryInfo item in directories)
{
GetFiles(item.FullName, list, fileExtsions);
}
}
/// <summary>
/// 写入文件
/// </summary>
/// <param name="filePath">文件名</param>
/// <param name="content">文件内容</param>
public static void WriteFile(string filePath, string content)
{
try
{
var fs = new FileStream(filePath, FileMode.Create);
Encoding encode = Encoding;
//获得字节数组
byte[] data = encode.GetBytes(content);
//开始写入
fs.Write(data, 0, data.Length);
//清空缓冲区、关闭流
fs.Flush();
fs.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 读取文件
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static string ReadFile(string filePath)
{
return ReadFile(filePath, Encoding);
}
/// <summary>
/// 读取文件
/// </summary>
/// <param name="filePath"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static string ReadFile(string filePath, Encoding encoding)
{
using (var sr = new StreamReader(filePath, encoding))
{
return sr.ReadToEnd();
}
}
/// <summary>
/// 读取文件
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static List<string> ReadFileLines(string filePath)
{
var str = new List<string>();
using (var sr = new StreamReader(filePath, Encoding))
{
String input;
while ((input = sr.ReadLine()) != null)
{
str.Add(input);
}
}
return str;
}
/// <summary>
/// 复制文件夹(及文件夹下所有子文件夹和文件)
/// </summary>
/// <param name="sourcePath">待复制的文件夹路径</param>
/// <param name="destinationPath">目标路径</param>
public static void CopyDirectory(String sourcePath, String destinationPath)
{
var info = new DirectoryInfo(sourcePath);
Directory.CreateDirectory(destinationPath);
foreach (FileSystemInfo fsi in info.GetFileSystemInfos())
{
String destName = Path.Combine(destinationPath, fsi.Name);
if (fsi is FileInfo) //如果是文件,复制文件
File.Copy(fsi.FullName, destName);
else //如果是文件夹,新建文件夹,递归
{
Directory.CreateDirectory(destName);
CopyDirectory(fsi.FullName, destName);
}
}
}
/// <summary>
/// 删除文件夹(及文件夹下所有子文件夹和文件)
/// </summary>
/// <param name="directoryPath"></param>
public static void DeleteFolder(string directoryPath)
{
foreach (string d in Directory.GetFileSystemEntries(directoryPath))
{
if (File.Exists(d))
{
var fi = new FileInfo(d);
if (fi.Attributes.ToString().IndexOf("ReadOnly", StringComparison.Ordinal) != -1)
fi.Attributes = FileAttributes.Normal;
File.Delete(d); //删除文件
}
else
DeleteFolder(d); //删除文件夹
}
Directory.Delete(directoryPath); //删除空文件夹
}
/// <summary>
/// 清空文件夹(及文件夹下所有子文件夹和文件)
/// </summary>
/// <param name="directoryPath"></param>
public static void ClearFolder(string directoryPath)
{
foreach (string d in Directory.GetFileSystemEntries(directoryPath))
{
if (File.Exists(d))
{
var fi = new FileInfo(d);
if (fi.Attributes.ToString().IndexOf("ReadOnly", StringComparison.Ordinal) != -1)
fi.Attributes = FileAttributes.Normal;
File.Delete(d); //删除文件
}
else
DeleteFolder(d); //删除文件夹
}
}
/// <summary>
/// 取得文件大小,按适当单位转换
/// </summary>
/// <param name="filepath"></param>
/// <returns></returns>
public static string GetFileSize(string filepath)
{
string result = "0KB";
if (File.Exists(filepath))
{
var size = new FileInfo(filepath).Length;
int filelength = size.ToString().Length;
if (filelength < 4)
result = size + "byte";
else if (filelength < 7)
result = Math.Round(Convert.ToDouble(size / 1024d), 2) + "KB";
else if (filelength < 10)
result = Math.Round(Convert.ToDouble(size / 1024d / 1024), 2) + "MB";
else if (filelength < 13)
result = Math.Round(Convert.ToDouble(size / 1024d / 1024 / 1024), 2) + "GB";
else
result = Math.Round(Convert.ToDouble(size / 1024d / 1024 / 1024 / 1024), 2) + "TB";
return result;
}
return result;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f7bb160f90922fc489ad0c7ccada23cc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,505 @@
/****************************************************
文件EditorFrameworkUtils.cs
作者:张铮
邮箱:
日期2022/3/8 17:50:17
功能:
*****************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.Editor
{
#if UNITY_EDITOR
/// <summary>
/// 文件辅助类
/// </summary>
public static class FilesUtils
{
/// <summary>
/// 编码方式
/// </summary>
private static readonly Encoding Encoding = Encoding.UTF8;
/// <summary>
/// 递归取得文件夹下文件
/// </summary>
/// <param name="dir"></param>
/// <param name="list"></param>
/// <param name="fileExtsions"></param>
public static void GetFiles(string dir, ref List<string> list)
{
//添加文件
string[] files = Directory.GetFiles(dir);
//if (fileExtsions.Count > 0)
//{
foreach (string file in files)
{
string extension = Path.GetExtension(file);
if (extension != null)
{
list.Add(file);
}
}
// }
// else
// {
// list.AddRange(files);
// }
//如果是目录,则递归
DirectoryInfo[] directories = new DirectoryInfo(dir).GetDirectories();
foreach (DirectoryInfo item in directories)
{
GetFiles(item.FullName, ref list);
}
}
/// <summary>
/// 创建文件夹
/// </summary>
public static void CreateFolder()
{
// Directory.CreateDirectory();//
}
/// <summary>
/// 写入文件
/// </summary>
/// <param name="filePath">文件名</param>
/// <param name="content">文件内容</param>
public static void WriteFile(string filePath, string content)
{
try
{
var fs = new FileStream(filePath, FileMode.Create);
Encoding encode = Encoding;
//获得字节数组
byte[] data = encode.GetBytes(content);
//开始写入
fs.Write(data, 0, data.Length);
//清空缓冲区、关闭流
fs.Flush();
fs.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 读取文件
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static string ReadFile(string filePath)
{
return ReadFile(filePath, Encoding);
}
/// <summary>
/// 读取文件
/// </summary>
/// <param name="filePath"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static string ReadFile(string filePath, Encoding encoding)
{
using (var sr = new StreamReader(filePath, encoding))
{
return sr.ReadToEnd();
}
}
/// <summary>
/// 读取文件
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static List<string> ReadFileLines(string filePath)
{
var str = new List<string>();
using (var sr = new StreamReader(filePath, Encoding))
{
String input;
while ((input = sr.ReadLine()) != null)
{
str.Add(input);
}
}
return str;
}
/// <summary>
/// 文件复制
/// </summary>
/// <param name="filePath"></param>
/// <param name="targetPath"></param>
public static void CopyFile(string filePath, string targetPath)
{
FileInfo file = new FileInfo(filePath);
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
if (file != null)
{
string tempPath = Path.Combine(targetPath, file.Name);
file.CopyTo(tempPath, true); //如果文件存在则覆盖
}
}
/// <summary>
/// 复制文件夹(及文件夹下所有子文件夹和文件)
/// </summary>
/// <param name="sourcePath">待复制的文件夹路径</param>
/// <param name="destinationPath">目标路径</param>
public static void CopyDirectory(String sourcePath, String destinationPath)
{
var info = new DirectoryInfo(sourcePath);
Directory.CreateDirectory(destinationPath);
foreach (FileSystemInfo fsi in info.GetFileSystemInfos())
{
String destName = Path.Combine(destinationPath, fsi.Name);
if (fsi is FileInfo) //如果是文件,复制文件
File.Copy(fsi.FullName, destName);
else //如果是文件夹,新建文件夹,递归
{
Directory.CreateDirectory(destName);
CopyDirectory(fsi.FullName, destName);
}
}
}
/// <summary>
/// 删除文件夹(及文件夹下所有子文件夹和文件)
/// </summary>
/// <param name="directoryPath"></param>
public static void DeleteFolder(string directoryPath)
{
foreach (string d in Directory.GetFileSystemEntries(directoryPath))
{
if (File.Exists(d))
{
var fi = new FileInfo(d);
if (fi.Attributes.ToString().IndexOf("ReadOnly", StringComparison.Ordinal) != -1)
fi.Attributes = FileAttributes.Normal;
File.Delete(d); //删除文件
}
else
DeleteFolder(d); //删除文件夹
}
Directory.Delete(directoryPath); //删除空文件夹
}
/// <summary>
/// 清空文件夹(及文件夹下所有子文件夹和文件)
/// </summary>
/// <param name="directoryPath"></param>
public static void ClearFolder(string directoryPath)
{
foreach (string d in Directory.GetFileSystemEntries(directoryPath))
{
if (File.Exists(d))
{
var fi = new FileInfo(d);
if (fi.Attributes.ToString().IndexOf("ReadOnly", StringComparison.Ordinal) != -1)
fi.Attributes = FileAttributes.Normal;
File.Delete(d); //删除文件
}
else
DeleteFolder(d); //删除文件夹
}
}
/// <summary>
/// 取得文件大小,按适当单位转换
/// </summary>
/// <param name="filepath"></param>
/// <returns></returns>
public static string GetFileSize(string filepath)
{
string result = "0KB";
if (File.Exists(filepath))
{
var size = new FileInfo(filepath).Length;
int filelength = size.ToString().Length;
if (filelength < 4)
result = size + "byte";
else if (filelength < 7)
result = Math.Round(Convert.ToDouble(size / 1024d), 2) + "KB";
else if (filelength < 10)
result = Math.Round(Convert.ToDouble(size / 1024d / 1024), 2) + "MB";
else if (filelength < 13)
result = Math.Round(Convert.ToDouble(size / 1024d / 1024 / 1024), 2) + "GB";
else
result = Math.Round(Convert.ToDouble(size / 1024d / 1024 / 1024 / 1024), 2) + "TB";
return result;
}
return result;
}
/// <summary>
/// 删除文件.
/// </summary>
/// <param name="path">删除完整文件夹路径.</param>
/// <param name="name">删除文件的名称.</param>
public static void DeleteFile(string path, string name)
{
File.Delete(path + name);
}
/// <summary>
/// 删除文件夹下所有子文件夹与文件
/// </summary>
public static void DeleteAllChild(string path, FileAttributes filter)
{
if (!Directory.Exists(path))
return;
DirectoryInfo dir = new DirectoryInfo(path);
FileInfo[] files = dir.GetFiles("*");
for (int i = 0; i < files.Length; ++i)
{
if ((files[i].Attributes & filter) > 0)
continue;
if (File.Exists(files[i].FullName))
File.Delete(files[i].FullName);
}
DirectoryInfo[] dirs = dir.GetDirectories("*");
for (int i = 0; i < dirs.Length; ++i)
{
if ((dirs[i].Attributes & filter) > 0)
continue;
if (Directory.Exists(dirs[i].FullName))
Directory.Delete(dirs[i].FullName, true);
}
}
/// <summary>
/// 绝对路径转相对路径
/// </summary>
public static string AbsoluteToRelativePath(string root_path, string absolute_path)
{
absolute_path = absolute_path.Replace('\\', '/');
int last_idx = absolute_path.LastIndexOf(root_path);
if (last_idx < 0)
return absolute_path;
int start = last_idx;
if (absolute_path[start] == '/')
start += 1;
int length = absolute_path.Length - start;
return absolute_path.Substring(start, length);
}
/// <summary>
/// 获得取除路径扩展名的路径
/// </summary>
public static string GetPathWithoutExtension(this string full_name)
{
int last_idx = full_name.LastIndexOfAny(".".ToCharArray());
if (last_idx < 0)
return full_name;
return full_name.Substring(0, last_idx);
}
/// <summary>
/// 将字符串转为大写或小写
/// </summary>
/// <param name="tmp"></param>
/// <param name="isUpper"></param>
/// <returns></returns>
public static string GetUpperOrLower(this string tmp, bool isUpper = true)
{
if (isUpper)
return tmp.ToLower();
else
return tmp.ToUpper();
}
/// <summary>
/// 判断是否有中文,有转为全拼
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public static string ChineseToPinYin(string text, bool isfile = true)
{
if (HasChinese(text))
{
return ConvertPinYin(text, isfile).GetUpperOrLower().Replace(" ", "");
}
else
{
if (isfile)
text = String.Concat("_", text);
return text.GetUpperOrLower();
}
}
/// <summary>
/// 判断字符串中是否有中文
/// </summary>
private static bool HasChinese(string s)
{
return Regex.IsMatch(s, "[\u4e00-\u9fbb]");
}
/// <summary>
/// 汉字转全拼
/// </summary>
private static string ConvertPinYin(string text, bool isfile = true)
{
if (string.IsNullOrEmpty(text))
return text;
try
{
var sb = new StringBuilder();
bool isfirstchinese = false;
if (HasChinese(text.ToList()[0].ToString()))
{
isfirstchinese = true;
Debug.Log(text.ToList()[0].ToString() + ":" + isfirstchinese);
}
for (int i = 0; i < text.ToList().Count; i++)
{
if (text.ToList()[i] <= 127)
sb.Append(text.ToList()[i]);
else
sb.Append($"_{NPinyin.Pinyin.GetPinyin(text.ToList()[i])}_");
}
var name = sb.ToString().Replace("__", "_");
if (!isfile) //裁剪首尾字符“_”
{
name = name.Trim('_');
}
else
{
name = name.TrimEnd('_');
if (!isfirstchinese)
name = String.Concat("_", name);
}
return name;
}
catch (Exception e)
{
Debug.LogError($"拼音转换失败:{text} {e.Message}");
}
return text;
}
/// <summary>
/// 删除指定字符后的字符串
/// </summary>
/// <param name="fileName">字符串</param>
/// <param name="lastIndex">符号例如:“ .”</param>
/// <returns></returns>
public static string DeleteLastIndex(string fileName, string lastIndex)
{
int index = fileName.LastIndexOf(lastIndex);
if (index >= 0)
{
fileName = fileName.Substring(0, index);
}
return fileName;
}
/// <summary>
/// 带颜色的日志输出
/// </summary>
public static void LogColor(string s, string path = null, Color color = default)
{
if (string.IsNullOrEmpty(path))
Debug.Log($"<color=#{ColorUtility.ToHtmlStringRGB(color)}>{s}</color>");
else
{
string assetPath = s.Replace("\\", "/").Replace(Application.dataPath, "Assets");
Debug.Log($"<color=#{ColorUtility.ToHtmlStringRGB(color)}>{assetPath}</color>",
AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath));
}
}
/// <summary>
/// 过滤:去掉首尾空格和换行符【\n】
/// </summary>
private static string FilterTo(string self)
{
self = self.TrimStart();
self = self.TrimEnd();
self = self.Replace("\n", "");
return self;
}
/// <summary>
/// 获取Assets下带.meta文件的资源的路径
/// </summary>
/// <param name="objectName">文件夹、资源</param>
private static string[] GetPathsOfAssetsObject(string objectName)
{
string[] guids = AssetDatabase.FindAssets(objectName);
string[] paths = new string[guids.Length];
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
if (path.Contains("Assets"))
paths[i] = path;
}
return paths;
}
/// <remarks>计算MD5</remarks>
public static string CalculateMD5(string file)
{
string result = "";
FileStream fs = new FileStream(file, FileMode.Open);
try
{
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(fs);
fs.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
result = sb.ToString();
}
catch (Exception e)
{
UnityEngine.Debug.Log("md5file() fail, error:" + e.Message);
}
finally
{
fs.Close();
}
return result;
}
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1c60a5396e9caa14db0afc2d11072688
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace NPinyin
{
public static class Pinyin
{
/// <summary>
/// 取中文文本的拼音首字母
/// </summary>
/// <param name="text">编码为UTF8的文本</param>
/// <returns>返回中文对应的拼音首字母</returns>
public static string GetInitials(string text)
{
text = text.Trim();
StringBuilder chars = new StringBuilder();
for (var i = 0; i < text.Length; ++i)
{
string py = GetPinyin(text[i]);
if (py != "") chars.Append(py[0]);
}
return chars.ToString().ToUpper();
}
/// <summary>
/// 取中文文本的拼音首字母
/// </summary>
/// <param name="text">文本</param>
/// <param name="encoding">源文本的编码</param>
/// <returns>返回encoding编码类型中文对应的拼音首字母</returns>
public static string GetInitials(string text, Encoding encoding)
{
string temp = ConvertEncoding(text, encoding, Encoding.UTF8);
return ConvertEncoding(GetInitials(temp), Encoding.UTF8, encoding);
}
/// <summary>
/// 取中文文本的拼音
/// </summary>
/// <param name="text">编码为UTF8的文本</param>
/// <returns>返回中文文本的拼音</returns>
public static string GetPinyin(string text)
{
StringBuilder sbPinyin = new StringBuilder();
for (var i = 0; i < text.Length; ++i)
{
string py = GetPinyin(text[i]);
if (py != "") sbPinyin.Append(py);
sbPinyin.Append(" ");
}
return sbPinyin.ToString().Trim();
}
/// <summary>
/// 取中文文本的拼音
/// </summary>
/// <param name="text">编码为UTF8的文本</param>
/// <param name="encoding">源文本的编码</param>
/// <returns>返回encoding编码类型的中文文本的拼音</returns>
public static string GetPinyin(string text, Encoding encoding)
{
string temp = ConvertEncoding(text.Trim(), encoding, Encoding.UTF8);
return ConvertEncoding(GetPinyin(temp), Encoding.UTF8, encoding);
}
/// <summary>
/// 取和拼音相同的汉字列表
/// </summary>
/// <param name="pinyin">编码为UTF8的拼音</param>
/// <returns>取拼音相同的汉字列表如拼音“ai”将会返回“唉爱……”等</returns>
public static string GetChineseText(string pinyin)
{
string key = pinyin.Trim().ToLower();
foreach (string str in PyCode.codes)
{
if (str.StartsWith(key + " ") || str.StartsWith(key + ":"))
return str.Substring(7);
}
return "";
}
/// <summary>
/// 取和拼音相同的汉字列表编码同参数encoding
/// </summary>
/// <param name="pinyin">编码为encoding的拼音</param>
/// <param name="encoding">编码</param>
/// <returns>返回编码为encoding的拼音为pinyin的汉字列表如拼音“ai”将会返回“唉爱……”等</returns>
public static string GetChineseText(string pinyin, Encoding encoding)
{
string text = ConvertEncoding(pinyin, encoding, Encoding.UTF8);
return ConvertEncoding(GetChineseText(text), Encoding.UTF8, encoding);
}
/// <summary>
/// 返回单个字符的汉字拼音
/// </summary>
/// <param name="ch">编码为UTF8的中文字符</param>
/// <returns>ch对应的拼音</returns>
public static string GetPinyin(char ch)
{
short hash = GetHashIndex(ch);
for (var i = 0; i < PyHash.hashes[hash].Length; ++i)
{
short index = PyHash.hashes[hash][i];
var pos = PyCode.codes[index].IndexOf(ch, 7);
if (pos != -1)
return PyCode.codes[index].Substring(0, 6).Trim();
}
return ch.ToString();
}
/// <summary>
/// 返回单个字符的汉字拼音
/// </summary>
/// <param name="ch">编码为encoding的中文字符</param>
/// <returns>编码为encoding的ch对应的拼音</returns>
public static string GetPinyin(char ch, Encoding encoding)
{
ch = ConvertEncoding(ch.ToString(), encoding, Encoding.UTF8)[0];
return ConvertEncoding(GetPinyin(ch), Encoding.UTF8, encoding);
}
/// <summary>
/// 转换编码
/// </summary>
/// <param name="text">文本</param>
/// <param name="srcEncoding">源编码</param>
/// <param name="dstEncoding">目标编码</param>
/// <returns>目标编码文本</returns>
public static string ConvertEncoding(string text, Encoding srcEncoding, Encoding dstEncoding)
{
byte[] srcBytes = srcEncoding.GetBytes(text);
byte[] dstBytes = Encoding.Convert(srcEncoding, dstEncoding, srcBytes);
return dstEncoding.GetString(dstBytes);
}
/// <summary>
/// 取文本索引值
/// </summary>
/// <param name="ch">字符</param>
/// <returns>文本索引值</returns>
private static short GetHashIndex(char ch)
{
return (short)((uint)ch % PyCode.codes.Length);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea36e52653d7c124a8ab2f814bf52457
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,410 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace NPinyin
{
internal class PyCode
{
internal static string[] codes = new string[]{
"a :阿啊吖嗄腌锕",
"ai :爱埃碍矮挨唉哎哀皑癌蔼艾隘捱嗳嗌嫒瑷暧砹锿霭",
"an :安按暗岸案俺氨胺鞍谙埯揞犴庵桉铵鹌黯",
"ang :昂肮盎",
"ao :凹奥敖熬翱袄傲懊澳坳拗嗷岙廒遨媪骜獒聱螯鏊鳌鏖",
"ba :把八吧巴拔霸罢爸坝芭捌扒叭笆疤跋靶耙茇菝岜灞钯粑鲅魃",
"bai :百白败摆柏佰拜稗捭掰",
"ban :办半板班般版拌搬斑扳伴颁扮瓣绊阪坂钣瘢癍舨",
"bang :帮棒邦榜梆膀绑磅蚌镑傍谤蒡浜",
"bao :报保包剥薄胞暴宝饱抱爆堡苞褒雹豹鲍葆孢煲鸨褓趵龅",
"bei :北被倍备背辈贝杯卑悲碑钡狈惫焙孛陂邶埤萆蓓呗悖碚鹎褙鐾鞴",
"ben :本奔苯笨畚坌贲锛",
"beng :泵崩绷甭蹦迸嘣甏",
"bi :比必避闭辟笔壁臂毕彼逼币鼻蔽鄙碧蓖毙毖庇痹敝弊陛匕俾荜荸薜吡哔狴庳愎滗濞弼妣婢嬖璧畀铋秕裨筚箅篦舭襞跸髀",
"bian :变边便编遍辩扁辨鞭贬卞辫匾弁苄忭汴缏飚煸砭碥窆褊蝙笾鳊",
"biao :表标彪膘婊骠杓飑飙镖镳瘭裱鳔髟",
"bie :别鳖憋瘪蹩",
"bin :宾彬斌濒滨摈傧豳缤玢槟殡膑镔髌鬓",
"bing :并病兵柄冰丙饼秉炳禀邴摒",
"bo :波播伯拨博勃驳玻泊菠钵搏铂箔帛舶脖膊渤亳啵饽檗擘礴钹鹁簸跛踣",
"bu :不部步布补捕卜哺埠簿怖卟逋瓿晡钚钸醭",
"ca :擦嚓礤",
"cai :采才材菜财裁彩猜睬踩蔡",
"can :参残蚕灿餐惭惨孱骖璨粲黪",
"cang :藏仓苍舱沧",
"cao :草槽操糙曹嘈漕螬艚",
"ce :测策侧册厕恻",
"cen :岑涔",
"ceng :层蹭",
"cha :查差插察茶叉茬碴搽岔诧猹馇汊姹杈楂槎檫锸镲衩",
"chai :柴拆豺侪钗瘥虿",
"chan :产铲阐搀掺蝉馋谗缠颤冁谄蒇廛忏潺澶羼婵骣觇禅镡蟾躔",
"chang :长常场厂唱肠昌倡偿畅猖尝敞伥鬯苌菖徜怅惝阊娼嫦昶氅鲳",
"chao :朝超潮巢抄钞嘲吵炒怊晁耖",
"che :车彻撤扯掣澈坼砗",
"chen :陈沉称衬尘臣晨郴辰忱趁伧谌谶抻嗔宸琛榇碜龀",
"cheng :成程称城承乘呈撑诚橙惩澄逞骋秤丞埕噌枨柽塍瞠铖铛裎蛏酲",
"chi :持尺齿吃赤池迟翅斥耻痴匙弛驰侈炽傺坻墀茌叱哧啻嗤彳饬媸敕眵鸱瘛褫蚩螭笞篪豉踟魑",
"chong :虫充冲崇宠茺忡憧铳舂艟",
"chou :抽仇臭酬畴踌稠愁筹绸瞅丑俦帱惆瘳雠",
"chu :出处除初础触楚锄储橱厨躇雏滁矗搐亍刍怵憷绌杵楮樗褚蜍蹰黜",
"chuai :揣搋啜膪踹",
"chuan :传船穿串川椽喘舛遄巛氚钏舡",
"chuang:床创窗闯疮幢怆",
"chui :吹垂锤炊捶陲棰槌",
"chun :春纯醇椿唇淳蠢莼鹑蝽",
"chuo :戳绰辍踔龊",
"ci :此次刺磁雌词茨疵辞慈瓷赐茈呲祠鹚糍",
"cong :从丛聪葱囱匆苁淙骢琮璁",
"cou :凑楱辏腠",
"cu :粗促醋簇蔟徂猝殂酢蹙蹴",
"cuan :篡蹿窜汆撺爨镩",
"cui :催脆淬粹摧崔瘁翠萃啐悴璀榱毳隹",
"cun :存村寸忖皴",
"cuo :错措撮磋搓挫厝嵯脞锉矬痤鹾蹉",
"da :大打达答搭瘩耷哒嗒怛妲疸褡笪靼鞑",
"dai :代带待袋戴呆歹傣殆贷逮怠埭甙呔岱迨骀绐玳黛",
"dan :单但弹担蛋淡胆氮丹旦耽郸掸惮诞儋萏啖殚赕眈疸瘅聃箪",
"dang :党当档挡荡谠凼菪宕砀裆",
"dao :到道导刀倒稻岛捣盗蹈祷悼叨忉氘纛",
"de :的得德锝",
"deng :等灯登邓蹬瞪凳噔嶝戥磴镫簦",
"di :地第低敌底帝抵滴弟递堤迪笛狄涤翟嫡蒂缔氐籴诋谛邸荻嘀娣绨柢棣觌砥碲睇镝羝骶",
"dia :嗲",
"dian :电点垫典店颠淀掂滇碘靛佃甸惦奠殿阽坫巅玷钿癜癫簟踮",
"diao :调掉吊碉叼雕凋刁钓铞铫貂鲷",
"die :迭跌爹碟蝶谍叠垤堞揲喋牒瓞耋蹀鲽",
"ding :定顶钉丁订盯叮鼎锭仃啶玎腚碇町疔耵酊",
"diu :丢铥",
"dong :动东冬懂洞冻董栋侗恫垌咚岽峒氡胨胴硐鸫",
"dou :斗豆兜抖陡逗痘蔸窦蚪篼",
"du :度都毒独读渡杜堵镀顿督犊睹赌肚妒芏嘟渎椟牍蠹笃髑黩",
"duan :断端段短锻缎椴煅簖",
"dui :对队堆兑怼憝碓",
"dun :盾吨顿蹲敦墩囤钝遁沌炖砘礅盹镦趸",
"duo :多夺朵掇哆垛躲跺舵剁惰堕咄哚沲缍柁铎裰踱",
"e :而二尔儿恶额恩俄耳饵蛾饿峨鹅讹娥厄扼遏鄂噩谔垩苊莪萼呃愕屙婀轭腭锇锷鹗颚鳄",
"ei :诶",
"en :恩蒽摁",
"er :而二尔儿耳饵洱贰佴迩珥铒鸸鲕",
"fa :发法阀乏伐罚筏珐垡砝",
"fan :反翻范犯饭繁泛番凡烦返藩帆樊矾钒贩蕃蘩幡梵燔畈蹯",
"fang :方放防访房纺仿妨芳肪坊邡枋钫舫鲂",
"fei :非肥飞费废肺沸菲匪啡诽吠芾狒悱淝妃绯榧腓斐扉镄痱蜚篚翡霏鲱",
"fen :分粉奋份粪纷芬愤酚吩氛坟焚汾忿偾瀵棼鲼鼢",
"feng :风封蜂丰缝峰锋疯奉枫烽逢冯讽凤俸酆葑唪沣砜",
"fou :否缶",
"fu :复服副府夫负富附福伏符幅腐浮辅付腹妇孵覆扶辐傅佛缚父弗甫肤氟敷拂俘涪袱抚俯釜斧脯腑赴赋阜讣咐匐凫郛芙苻茯莩菔拊呋幞怫滏艴孚驸绂绋桴赙祓砩黻黼罘稃馥蚨蜉蝠蝮麸趺跗鲋鳆",
"ga :噶嘎尬尕尜旮钆",
"gai :改该盖概钙溉丐陔垓戤赅",
"gan :干杆感敢赶甘肝秆柑竿赣坩苷尴擀泔淦澉绀橄旰矸疳酐",
"gang :刚钢缸纲岗港杠冈肛戆罡筻",
"gao :高搞告稿膏篙皋羔糕镐睾诰郜藁缟槔槁杲锆",
"ge :个各革格割歌隔哥铬阁戈葛搁鸽胳疙蛤鬲仡哿圪塥嗝搿膈硌镉袼虼舸骼",
"gen :根跟亘茛哏艮",
"geng :更耕颈庚羹埂耿梗哽赓绠鲠",
"gong :工公共供功攻巩贡汞宫恭龚躬弓拱珙肱蚣觥",
"gou :够构沟狗钩勾购苟垢佝诟岣遘媾缑枸觏彀笱篝鞲",
"gu :鼓固古骨故顾股谷估雇孤姑辜菇咕箍沽蛊嘏诂菰崮汩梏轱牯牿臌毂瞽罟钴锢鸪痼蛄酤觚鲴鹘",
"gua :挂刮瓜剐寡褂卦诖呱栝胍鸹",
"guai :怪乖拐",
"guan :关管观官灌贯惯冠馆罐棺倌莞掼涫盥鹳矜鳏",
"guang :光广逛咣犷桄胱",
"gui :规贵归硅鬼轨龟桂瑰圭闺诡癸柜跪刽匦刿庋宄妫桧炅晷皈簋鲑鳜",
"gun :滚辊棍衮绲磙鲧",
"guo :国过果锅郭裹馘埚掴呙帼崞猓椁虢聒蜾蝈",
"ha :哈铪",
"hai :还海害孩骸氦亥骇嗨胲醢",
"han :含焊旱喊汉寒汗函韩酣憨邯涵罕翰撼捍憾悍邗菡撖阚瀚晗焓顸颔蚶鼾",
"hang :航夯杭沆绗珩颃",
"hao :好号毫耗豪郝浩壕嚎蒿薅嗥嚆濠灏昊皓颢蚝",
"he :和合河何核赫荷褐喝贺呵禾盒菏貉阂涸鹤诃劾壑嗬阖纥曷盍颌蚵翮",
"hei :黑嘿",
"hen :很狠痕恨",
"heng :横衡恒哼亨蘅桁",
"hong :红洪轰烘哄虹鸿宏弘黉訇讧荭蕻薨闳泓",
"hou :后候厚侯喉猴吼堠後逅瘊篌糇鲎骺",
"hu :护互湖呼户弧乎胡糊虎忽瑚壶葫蝴狐唬沪冱唿囫岵猢怙惚浒滹琥槲轷觳烀煳戽扈祜瓠鹄鹕鹱笏醐斛",
"hua :化花话划滑华画哗猾骅桦砉铧",
"huai :坏怀淮槐徊踝",
"huan :环换欢缓患幻焕桓唤痪豢涣宦郇奂萑擐圜獾洹浣漶寰逭缳锾鲩鬟",
"huang :黄簧荒皇慌蝗磺凰惶煌晃幌恍谎隍徨湟潢遑璜肓癀蟥篁鳇",
"hui :会回灰挥辉汇毁慧恢绘惠徽蛔悔卉晦贿秽烩讳诲诙茴荟蕙咴哕喙隳洄浍彗缋珲晖恚虺蟪麾",
"hun :混浑荤昏婚魂诨馄阍溷",
"huo :活或火货获伙霍豁惑祸劐藿攉嚯夥钬锪镬耠蠖",
"ji :级及机极几积给基记己计集即际季激济技击继急剂既纪寄挤鸡迹绩吉脊辑籍疾肌棘畸圾稽箕饥讥姬缉汲嫉蓟冀伎祭悸寂忌妓藉丌亟乩剞佶偈诘墼芨芰荠蒺蕺掎叽咭哜唧岌嵴洎屐骥畿玑楫殛戟戢赍觊犄齑矶羁嵇稷瘠虮笈笄暨跻跽霁鲚鲫髻麂",
"jia :加家架价甲夹假钾贾稼驾嘉枷佳荚颊嫁伽郏葭岬浃迦珈戛胛恝铗镓痂瘕袷蛱笳袈跏",
"jian :间件见建坚减检践尖简碱剪艰渐肩键健柬鉴剑歼监兼奸箭茧舰俭笺煎缄硷拣捡荐槛贱饯溅涧僭谏谫菅蒹搛湔蹇謇缣枧楗戋戬牮犍毽腱睑锏鹣裥笕翦趼踺鲣鞯",
"jiang :将降讲江浆蒋奖疆僵姜桨匠酱茳洚绛缰犟礓耩糨豇",
"jiao :较教交角叫脚胶浇焦搅酵郊铰窖椒礁骄娇嚼矫侥狡饺缴绞剿轿佼僬艽茭挢噍峤徼姣敫皎鹪蛟醮跤鲛",
"jie :结阶解接节界截介借届街揭洁杰竭皆秸劫桔捷睫姐戒藉芥疥诫讦拮喈嗟婕孑桀碣疖颉蚧羯鲒骱",
"jin :进金近紧斤今尽仅劲浸禁津筋锦晋巾襟谨靳烬卺荩堇噤馑廑妗缙瑾槿赆觐衿",
"jing :经精京径井静竟晶净境镜景警茎敬惊睛竞荆兢鲸粳痉靖刭儆阱菁獍憬泾迳弪婧肼胫腈旌",
"jiong :炯窘迥扃",
"jiu :就九旧究久救酒纠揪玖韭灸厩臼舅咎疚僦啾阄柩桕鸠鹫赳鬏",
"ju :具据局举句聚距巨居锯剧矩拒鞠拘狙疽驹菊咀沮踞俱惧炬倨讵苣苴莒掬遽屦琚椐榘榉橘犋飓钜锔窭裾趄醵踽龃雎鞫",
"juan :卷捐鹃娟倦眷绢鄄狷涓桊蠲锩镌隽",
"jue :决觉绝掘撅攫抉倔爵诀厥劂谲矍蕨噘噱崛獗孓珏桷橛爝镢蹶觖",
"jun :军均菌君钧峻俊竣浚郡骏捃皲筠麇",
"ka :卡喀咖咯佧咔胩",
"kai :开凯揩楷慨剀垲蒈忾恺铠锎锴",
"kan :看刊坎堪勘砍侃莰戡龛瞰",
"kang :抗康炕慷糠扛亢伉闶钪",
"kao :考靠拷烤尻栲犒铐",
"ke :可克科刻客壳颗棵柯坷苛磕咳渴课嗑岢恪溘骒缂珂轲氪瞌钶锞稞疴窠颏蝌髁",
"ken :肯啃垦恳裉",
"keng :坑吭铿",
"kong :孔空控恐倥崆箜",
"kou :口扣抠寇芤蔻叩眍筘",
"ku :苦库枯酷哭窟裤刳堀喾绔骷",
"kua :跨夸垮挎胯侉",
"kuai :快块筷侩蒯郐哙狯脍",
"kuan :宽款髋",
"kuang :况矿狂框匡筐眶旷诓诳邝圹夼哐纩贶",
"kui :奎溃馈亏盔岿窥葵魁傀愧馗匮夔隗蒉揆喹喟悝愦逵暌睽聩蝰篑跬",
"kun :困昆坤捆悃阃琨锟醌鲲髡",
"kuo :扩括阔廓蛞",
"la :拉啦蜡腊蓝垃喇辣剌邋旯砬瘌",
"lai :来赖莱崃徕涞濑赉睐铼癞籁",
"lan :兰烂蓝览栏婪拦篮阑澜谰揽懒缆滥岚漤榄斓罱镧褴",
"lang :浪朗郎狼琅榔廊莨蒗啷阆锒稂螂",
"lao :老劳牢涝捞佬姥酪烙唠崂栳铑铹痨耢醪",
"le :了乐勒肋仂叻泐鳓",
"lei :类雷累垒泪镭蕾磊儡擂肋羸诔嘞嫘缧檑耒酹",
"leng :冷棱楞塄愣",
"li :理里利力立离例历粒厘礼李隶黎璃励犁梨丽厉篱狸漓鲤莉荔吏栗砾傈俐痢沥哩俪俚郦坜苈莅蓠藜呖唳喱猁溧澧逦娌嫠骊缡枥栎轹戾砺詈罹锂鹂疠疬蛎蜊蠡笠篥粝醴跞雳鲡鳢黧",
"lia :俩",
"lian :连联练炼脸链莲镰廉怜涟帘敛恋蔹奁潋濂琏楝殓臁裢裣蠊鲢",
"liang :量两粮良亮梁凉辆粱晾谅墚椋踉靓魉",
"liao :料疗辽僚撩聊燎寥潦撂镣廖蓼尥嘹獠寮缭钌鹩",
"lie :列裂烈劣猎冽埒捩咧洌趔躐鬣",
"lin :林磷临邻淋麟琳霖鳞凛赁吝蔺啉嶙廪懔遴檩辚膦瞵粼躏",
"ling :领另零令灵岭铃龄凌陵拎玲菱伶羚酃苓呤囹泠绫柃棂瓴聆蛉翎鲮",
"liu :流六留刘硫柳馏瘤溜琉榴浏遛骝绺旒熘锍镏鹨鎏",
"long :龙垄笼隆聋咙窿拢陇垅茏泷珑栊胧砻癃",
"lou :漏楼娄搂篓陋偻蒌喽嵝镂瘘耧蝼髅",
"lu :路率露绿炉律虑滤陆氯鲁铝录旅卢吕芦颅庐掳卤虏麓碌赂鹿潞禄戮驴侣履屡缕垆撸噜闾泸渌漉逯璐栌榈橹轳辂辘氇胪膂镥稆鸬鹭褛簏舻鲈",
"luan :卵乱峦挛孪滦脔娈栾鸾銮",
"lue :略掠锊",
"lun :论轮伦抡仑沦纶囵",
"luo :落罗螺洛络逻萝锣箩骡裸骆倮蠃荦捋摞猡泺漯珞椤脶镙瘰雒",
"m :呒",
"ma :马麻吗妈骂嘛码玛蚂唛犸嬷杩蟆",
"mai :麦脉卖买埋迈劢荬霾",
"man :满慢曼漫蔓瞒馒蛮谩墁幔缦熳镘颟螨鳗鞔",
"mang :忙芒盲茫氓莽邙漭硭蟒",
"mao :毛矛冒貌贸帽猫茅锚铆卯茂袤茆峁泖瑁昴牦耄旄懋瞀蟊髦",
"me :么麽",
"mei :没每美煤霉酶梅妹眉玫枚媒镁昧寐媚莓嵋猸浼湄楣镅鹛袂魅",
"men :们门闷扪焖懑钔",
"meng :孟猛蒙盟梦萌锰檬勐甍瞢懵朦礞虻蜢蠓艋艨",
"mi :米密迷蜜秘眯醚靡糜谜弥觅泌幂芈谧蘼咪嘧猕汨宓弭脒祢敉糸縻麋",
"mian :面棉免绵眠冕勉娩缅沔渑湎腼眄",
"miao :苗秒描庙妙瞄藐渺喵邈缈缪杪淼眇鹋",
"mie :灭蔑咩蠛篾",
"min :民敏抿皿悯闽苠岷闵泯缗玟珉愍黾鳘",
"ming :命明名鸣螟铭冥茗溟暝瞑酩",
"miu :谬",
"mo :磨末模膜摸墨摩莫抹默摹蘑魔沫漠寞陌谟茉蓦馍嫫殁镆秣瘼耱貊貘",
"mou :某谋牟侔哞眸蛑蝥鍪",
"mu :亩目木母墓幕牧姆穆拇牡暮募慕睦仫坶苜沐毪钼",
"n :嗯",
"na :那南哪拿纳钠呐娜捺肭镎衲",
"nai :耐奶乃氖奈鼐艿萘柰",
"nan :南难男喃囝囡楠腩蝻赧",
"nang :囊攮囔馕曩",
"nao :脑闹挠恼淖孬垴呶猱瑙硇铙蛲",
"ne :呢讷",
"nei :内馁",
"nen :嫩恁",
"neng :能",
"ni :你泥尼逆拟尿妮霓倪匿腻溺伲坭猊怩昵旎慝睨铌鲵",
"nian :年念粘蔫拈碾撵捻酿廿埝辇黏鲇鲶",
"niang :娘",
"niao :尿鸟茑嬲脲袅",
"nie :镍啮涅捏聂孽镊乜陧蘖嗫颞臬蹑",
"nin :您",
"ning :宁凝拧柠狞泞佞苎咛甯聍",
"niu :牛扭钮纽狃忸妞",
"nong :农弄浓脓侬哝",
"nou :耨",
"nu :女奴努怒弩胬孥驽恧钕衄",
"nuan :暖",
"nue :虐",
"nuo :诺挪懦糯傩搦喏锘",
"o :欧偶哦鸥殴藕呕沤讴噢怄瓯耦",
"ou :欧偶鸥殴藕呕沤讴怄瓯耦",
"pa :怕派爬帕啪趴琶葩杷筢",
"pai :派排拍牌哌徘湃俳蒎",
"pan :判盘叛潘攀磐盼畔胖爿泮袢襻蟠蹒",
"pang :旁乓庞耪胖彷滂逄螃",
"pao :跑炮刨抛泡咆袍匏狍庖脬疱",
"pei :配培陪胚呸裴赔佩沛辔帔旆锫醅霈",
"pen :喷盆湓",
"peng :碰棚蓬朋捧膨砰抨烹澎彭硼篷鹏堋嘭怦蟛",
"pi :批皮坯脾疲砒霹披劈琵毗啤匹痞僻屁譬丕仳陴邳郫圮鼙芘擗噼庀淠媲纰枇甓睥罴铍癖疋蚍蜱貔",
"pian :片偏篇骗谝骈犏胼翩蹁",
"piao :票漂飘瓢剽嘌嫖缥殍瞟螵",
"pie :撇瞥丿苤氕",
"pin :品贫频拼苹聘拚姘嫔榀牝颦",
"ping :平评瓶凭苹乒坪萍屏俜娉枰鲆",
"po :破迫坡泼颇婆魄粕叵鄱珀攴钋钷皤笸",
"pou :剖裒掊",
"pu :普谱扑埔铺葡朴蒲仆莆菩圃浦曝瀑匍噗溥濮璞氆镤镨蹼",
"qi :起其气期七器齐奇汽企漆欺旗畦启弃歧栖戚妻凄柒沏棋崎脐祈祁骑岂乞契砌迄泣讫亓俟圻芑芪萁萋葺蕲嘁屺岐汔淇骐绮琪琦杞桤槭耆欹祺憩碛颀蛴蜞綦綮蹊鳍麒",
"qia :恰掐洽葜髂",
"qian :前千钱浅签迁铅潜牵钳谴扦钎仟谦乾黔遣堑嵌欠歉倩佥阡芊芡茜荨掮岍悭慊骞搴褰缱椠肷愆钤虔箬箝",
"qiang :强枪抢墙腔呛羌蔷戕嫱樯戗炝锖锵镪襁蜣羟跄",
"qiao :桥瞧巧敲乔蕉橇锹悄侨鞘撬翘峭俏窍劁诮谯荞愀憔樵硗跷鞒",
"qie :切且茄怯窃郄惬妾挈锲箧",
"qin :亲侵勤秦钦琴芹擒禽寝沁芩揿吣嗪噙溱檎锓覃螓衾",
"qing :情清青轻倾请庆氢晴卿擎氰顷苘圊檠磬蜻罄箐謦鲭黥",
"qiong :穷琼邛茕穹蛩筇跫銎",
"qiu :求球秋丘邱囚酋泅俅巯犰湫逑遒楸赇虬蚯蝤裘糗鳅鼽",
"qu :去区取曲渠屈趋驱趣蛆躯娶龋诎劬蕖蘧岖衢阒璩觑氍朐祛磲鸲癯蛐蠼麴瞿黢",
"quan :全权圈劝泉醛颧痊拳犬券诠荃悛绻辁畎铨蜷筌鬈",
"que :确却缺炔瘸鹊榷雀阕阙悫",
"qun :群裙逡",
"ran :然燃染冉苒蚺髯",
"rang :让壤嚷瓤攘禳穰",
"rao :绕扰饶荛娆桡",
"re :热惹",
"ren :人认任仁刃忍壬韧妊纫仞荏葚饪轫稔衽",
"reng :仍扔",
"ri :日",
"rong :容溶荣熔融绒戎茸蓉冗嵘狨榕肜蝾",
"rou :肉揉柔糅蹂鞣",
"ru :如入儒乳茹蠕孺辱汝褥蓐薷嚅洳溽濡缛铷襦颥",
"ruan :软阮朊",
"rui :瑞锐蕊芮蕤枘睿蚋",
"run :润闰",
"ruo :弱若偌",
"sa :撒萨洒卅仨挲脎飒",
"sai :塞赛腮鳃噻",
"san :三散叁伞馓毵糁",
"sang :桑丧嗓搡磉颡",
"sao :扫搔骚嫂埽缫缲臊瘙鳋",
"se :色瑟涩啬铯穑",
"sen :森",
"seng :僧",
"sha :沙杀砂啥纱莎刹傻煞杉唼歃铩痧裟霎鲨",
"shai :筛晒",
"shan :山闪善珊扇陕苫杉删煽衫擅赡膳汕缮剡讪鄯埏芟潸姗嬗骟膻钐疝蟮舢跚鳝",
"shang :上商伤尚墒赏晌裳垧绱殇熵觞",
"shao :少烧稍绍哨梢捎芍勺韶邵劭苕潲蛸筲艄",
"she :社设射摄舌涉舍蛇奢赊赦慑厍佘猞滠歙畲麝",
"shen :深身神伸甚渗沈肾审申慎砷呻娠绅婶诜谂莘哂渖椹胂矧蜃",
"sheng :生胜声省升盛绳剩圣牲甥嵊晟眚笙",
"shi :是时十使事实式识世试石什示市史师始施士势湿适食失视室氏蚀诗释拾饰驶狮尸虱矢屎柿拭誓逝嗜噬仕侍恃谥埘莳蓍弑轼贳炻铈螫舐筮酾豕鲥鲺",
"shou :手受收首守授寿兽售瘦狩绶艏",
"shu :数书树属术输述熟束鼠疏殊舒蔬薯叔署枢梳抒淑赎孰暑曙蜀黍戍竖墅庶漱恕丨倏塾菽摅沭澍姝纾毹腧殳秫",
"shua :刷耍唰",
"shuai :衰帅摔甩蟀",
"shuan :栓拴闩涮",
"shuang:双霜爽孀",
"shui :水谁睡税",
"shun :顺吮瞬舜",
"shuo :说硕朔烁蒴搠妁槊铄",
"si :四思死斯丝似司饲私撕嘶肆寺嗣伺巳厮兕厶咝汜泗澌姒驷缌祀锶鸶耜蛳笥",
"song :松送宋颂耸怂讼诵凇菘崧嵩忪悚淞竦",
"sou :搜艘擞嗽叟薮嗖嗾馊溲飕瞍锼螋",
"su :素速苏塑缩俗诉宿肃酥粟僳溯夙谡蔌嗉愫涑簌觫稣",
"suan :算酸蒜狻",
"sui :随穗碎虽岁隋绥髓遂隧祟谇荽濉邃燧眭睢",
"sun :损孙笋荪狲飧榫隼",
"suo :所缩锁索蓑梭唆琐唢嗦嗍娑桫睃羧",
"ta :他它她塔踏塌獭挞蹋闼溻遢榻沓铊趿鳎",
"tai :台太态胎抬泰苔酞汰邰薹肽炱钛跆鲐",
"tan :谈碳探炭坦贪滩坍摊瘫坛檀痰潭谭毯袒叹郯澹昙忐钽锬",
"tang :堂糖唐塘汤搪棠膛倘躺淌趟烫傥帑溏瑭樘铴镗耥螗螳羰醣",
"tao :套讨逃陶萄桃掏涛滔绦淘鼗啕洮韬焘饕",
"te :特忒忑铽",
"teng :腾疼藤誊滕",
"ti :提题体替梯惕剔踢锑蹄啼嚏涕剃屉倜悌逖缇鹈裼醍",
"tian :天田添填甜恬舔腆掭忝阗殄畋",
"tiao :条跳挑迢眺佻祧窕蜩笤粜龆鲦髫",
"tie :铁贴帖萜餮",
"ting :听停庭挺廷厅烃汀亭艇莛葶婷梃铤蜓霆",
"tong :同通统铜痛筒童桶桐酮瞳彤捅佟仝茼嗵恸潼砼",
"tou :头投透偷钭骰",
"tu :图土突途徒凸涂吐兔屠秃堍荼菟钍酴",
"tuan :团湍抟彖疃",
"tui :推退腿颓蜕褪煺",
"tun :吞屯臀氽饨暾豚",
"tuo :脱拖托妥椭鸵陀驮驼拓唾乇佗坨庹沱柝橐砣箨酡跎鼍",
"wa :瓦挖哇蛙洼娃袜佤娲腽",
"wai :外歪",
"wan :完万晚弯碗顽湾挽玩豌丸烷皖惋宛婉腕剜芄菀纨绾琬脘畹蜿",
"wang :往王望网忘妄亡旺汪枉罔尢惘辋魍",
"wei :为位委围维唯卫微伟未威危尾谓喂味胃魏伪违韦畏纬巍桅惟潍苇萎蔚渭尉慰偎诿隈葳薇囗帏帷崴嵬猥猬闱沩洧涠逶娓玮韪軎炜煨痿艉鲔",
"wen :问温文稳纹闻蚊瘟吻紊刎阌汶璺雯",
"weng :嗡翁瓮蓊蕹",
"wo :我握窝蜗涡沃挝卧斡倭莴喔幄渥肟硪龌",
"wu :无五物武务误伍舞污悟雾午屋乌吴诬钨巫呜芜梧吾毋捂侮坞戊晤勿兀仵阢邬圬芴唔庑怃忤浯寤迕妩婺骛杌牾焐鹉鹜痦蜈鋈鼯",
"xi :系席西习细吸析喜洗铣稀戏隙希息袭锡烯牺悉惜溪昔熙硒矽晰嘻膝夕熄汐犀檄媳僖兮隰郗菥葸蓰奚唏徙饩阋浠淅屣嬉玺樨曦觋欷熹禊禧皙穸蜥螅蟋舄舾羲粞翕醯鼷",
"xia :下夏吓狭霞瞎虾匣辖暇峡侠厦呷狎遐瑕柙硖罅黠",
"xian :线现先县限显鲜献险陷宪纤掀弦腺锨仙咸贤衔舷闲涎嫌馅羡冼苋莶藓岘猃暹娴氙燹祆鹇痫蚬筅籼酰跣跹霰",
"xiang :想向相象响项箱乡香像详橡享湘厢镶襄翔祥巷芗葙饷庠骧缃蟓鲞飨",
"xiao :小消削效笑校销硝萧肖孝霄哮嚣宵淆晓啸哓崤潇逍骁绡枭枵筱箫魈",
"xie :些写斜谢协械卸屑鞋歇邪胁蟹泄泻楔蝎挟携谐懈偕亵勰燮薤撷獬廨渫瀣邂绁缬榭榍躞",
"xin :新心信锌芯辛欣薪忻衅囟馨昕歆鑫",
"xing :行性形型星兴醒姓幸腥猩惺刑邢杏陉荇荥擤饧悻硎",
"xiong :雄胸兄凶熊匈汹芎",
"xiu :修锈休袖秀朽羞嗅绣咻岫馐庥溴鸺貅髹",
"xu :续许须需序虚絮畜叙蓄绪徐墟戌嘘酗旭恤婿诩勖圩蓿洫溆顼栩煦盱胥糈醑",
"xuan :选旋宣悬玄轩喧癣眩绚儇谖萱揎泫渲漩璇楦暄炫煊碹铉镟痃",
"xue :学血雪穴靴薛谑泶踅鳕",
"xun :训旬迅讯寻循巡勋熏询驯殉汛逊巽埙荀蕈薰峋徇獯恂洵浔曛醺鲟",
"ya :压亚呀牙芽雅蚜鸭押鸦丫崖衙涯哑讶伢垭揠岈迓娅琊桠氩砑睚痖",
"yan :验研严眼言盐演岩沿烟延掩宴炎颜燕衍焉咽阉淹蜒阎奄艳堰厌砚雁唁彦焰谚厣赝俨偃兖谳郾鄢菸崦恹闫阏湮滟妍嫣琰檐晏胭焱罨筵酽魇餍鼹",
"yang :样养氧扬洋阳羊秧央杨仰殃鸯佯疡痒漾徉怏泱炀烊恙蛘鞅",
"yao :要药摇腰咬邀耀疟妖瑶尧遥窑谣姚舀夭爻吆崾徭幺珧杳轺曜肴鹞窈繇鳐",
"ye :也业页叶液夜野爷冶椰噎耶掖曳腋靥谒邺揶晔烨铘",
"yi :一以义意已移医议依易乙艺益异宜仪亿遗伊役衣疑亦谊翼译抑忆疫壹揖铱颐夷胰沂姨彝椅蚁倚矣邑屹臆逸肄裔毅溢诣翌绎刈劓佚佾诒圯埸懿苡荑薏弈奕挹弋呓咦咿噫峄嶷猗饴怿怡悒漪迤驿缢殪轶贻旖熠眙钇镒镱痍瘗癔翊蜴舣羿翳酏黟",
"yin :因引阴印音银隐饮荫茵殷姻吟淫寅尹胤鄞垠堙茚吲喑狺夤洇氤铟瘾窨蚓霪龈",
"ying :应影硬营英映迎樱婴鹰缨莹萤荧蝇赢盈颖嬴郢茔莺萦蓥撄嘤膺滢潆瀛瑛璎楹媵鹦瘿颍罂",
"yo :哟唷",
"yong :用勇永拥涌蛹庸佣臃痈雍踊咏泳恿俑壅墉喁慵邕镛甬鳙饔",
"you :有由又油右友优幼游尤诱犹幽悠忧邮铀酉佑釉卣攸侑莠莜莸呦囿宥柚猷牖铕疣蚰蚴蝣鱿黝鼬",
"yu :于与育鱼雨玉余遇预域语愈渔予羽愚御欲宇迂淤盂榆虞舆俞逾愉渝隅娱屿禹芋郁吁喻峪狱誉浴寓裕豫驭禺毓伛俣谀谕萸蓣揄圄圉嵛狳饫馀庾阈鬻妪妤纡瑜昱觎腴欤於煜熨燠聿钰鹆鹬瘐瘀窬窳蜮蝓竽臾舁雩龉",
"yuan :员原圆源元远愿院缘援园怨鸳渊冤垣袁辕猿苑垸塬芫掾沅媛瑗橼爰眢鸢螈箢鼋",
"yue :月越约跃曰阅钥岳粤悦龠瀹樾刖钺",
"yun :运云匀允孕耘郧陨蕴酝晕韵郓芸狁恽愠纭韫殒昀氲熨",
"za :杂咱匝砸咋咂",
"zai :在再载栽灾哉宰崽甾",
"zan :赞咱暂攒拶瓒昝簪糌趱錾",
"zang :脏葬赃奘驵臧",
"zao :造早遭燥凿糟枣皂藻澡蚤躁噪灶唣",
"ze :则择责泽仄赜啧帻迮昃笮箦舴",
"zei :贼",
"zen :怎谮",
"zeng :增曾憎赠缯甑罾锃",
"zha :扎炸闸铡轧渣喳札眨栅榨乍诈揸吒咤哳砟痄蚱齄",
"zhai :寨摘窄斋宅债砦瘵",
"zhan :战展站占瞻毡詹沾盏斩辗崭蘸栈湛绽谵搌旃",
"zhang :张章掌仗障胀涨账樟彰漳杖丈帐瘴仉鄣幛嶂獐嫜璋蟑",
"zhao :照找招召赵爪罩沼兆昭肇诏棹钊笊",
"zhe :这着者折哲浙遮蛰辙锗蔗谪摺柘辄磔鹧褶蜇赭",
"zhen :真针阵镇振震珍诊斟甄砧臻贞侦枕疹圳蓁浈缜桢榛轸赈胗朕祯畛稹鸩箴",
"zheng :争正政整证征蒸症郑挣睁狰怔拯帧诤峥徵钲铮筝",
"zhi :之制治只质指直支织止至置志值知执职植纸致枝殖脂智肢秩址滞汁芝吱蜘侄趾旨挚掷帜峙稚炙痔窒卮陟郅埴芷摭帙忮彘咫骘栉枳栀桎轵轾贽胝膣祉祗黹雉鸷痣蛭絷酯跖踬踯豸觯",
"zhong :中种重众钟终忠肿仲盅衷冢锺螽舯踵",
"zhou :轴周洲州皱骤舟诌粥肘帚咒宙昼荮啁妯纣绉胄碡籀酎",
"zhu :主注著住助猪铸株筑柱驻逐祝竹贮珠朱诸蛛诛烛煮拄瞩嘱蛀伫侏邾茱洙渚潴杼槠橥炷铢疰瘃竺箸舳翥躅麈",
"zhua :抓",
"zhuai :拽",
"zhuan :转专砖撰赚篆啭馔颛",
"zhuang:装状壮庄撞桩妆僮",
"zhui :追锥椎赘坠缀惴骓缒",
"zhun :准谆肫窀",
"zhuo :捉桌拙卓琢茁酌啄灼浊倬诼擢浞涿濯焯禚斫镯",
"zi :子自资字紫仔籽姿兹咨滋淄孜滓渍谘嵫姊孳缁梓辎赀恣眦锱秭耔笫粢趑觜訾龇鲻髭",
"zong :总纵宗综棕鬃踪偬枞腙粽",
"zou :走邹奏揍诹陬鄹驺鲰",
"zu :组族足阻祖租卒诅俎菹镞",
"zuan :钻纂攥缵躜",
"zui :最罪嘴醉蕞",
"zun :尊遵撙樽鳟",
"zuo :作做左座坐昨佐柞阼唑嘬怍胙祚"};
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f62374cec666c6548b4b870066c57c86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More