完善框架

This commit is contained in:
陈思海 2025-01-24 16:21:00 +08:00
parent eb38f67131
commit 9f3fe49d6a
253 changed files with 13144 additions and 3268 deletions

View File

@ -159,7 +159,7 @@ namespace BuildCli
}
}
[MenuItem("Build/Build Test")]
[MenuItem("开发工具/Build/Build Test")]
public static void BuildAAA()
{
string outPath = System.IO.Path.Combine(Application.dataPath, "../../bundles/");
@ -179,7 +179,7 @@ namespace BuildCli
BuildTest(outPath, version);
BuildUpdateData(version);
}
static void BuildUpdateData(string version)
{
string outPath = System.IO.Path.Combine(Application.dataPath, "../../bundles/");
@ -232,6 +232,7 @@ namespace BuildCli
{
Directory.CreateDirectory(targetPath);
}
DeleteFilesInDirectory(targetPath);
CopyFiles(bundlePath, targetPath);
@ -370,4 +371,4 @@ namespace BuildCli
}
}
}
}
}

View File

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

View File

@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Presets;
using UnityEngine;
namespace BuildCli
{
public class BuildManager
{
public Preset SelectedBuildPreset;
public Preset[] PlayerSettingsPresetsInProject;
public void OpenBuildWindow()
{
#if UNITY_6000_0_OR_NEWER
EditorApplication.ExecuteMenuItem("File/Build Profiles");
#else
var buildPlayerWindow = EditorWindow.GetWindow<BuildPlayerWindow>("Build Settings");
buildPlayerWindow.Show();
#endif
}
public static void ApplyPreset(Preset preset)
{
var projectSettings = Resources.FindObjectsOfTypeAll<PlayerSettings>();
foreach (var settings in projectSettings)
{
preset.ApplyTo(settings);
}
}
public List<string> GenerateBuildSettingsList()
{
PlayerSettingsPresetsInProject = AssetDatabase.FindAssets("t:Preset")
.Select(AssetDatabase.GUIDToAssetPath)
.Where(path => path.Contains("PlayerSettings"))
.Select(AssetDatabase.LoadAssetAtPath<Preset>)
.ToArray();
var buildPresetsList = new List<string>(PlayerSettingsPresetsInProject.Select(preset => preset.name));
return buildPresetsList;
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: dea5e7b095c6d3b4ea334c381fcd16fb
guid: 3ad015755f8508d48ba8bca98199bf77
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using UnityEditor;
namespace BuildCli
{
[InitializeOnLoad]
public static class CustomUnityToolbar
{
private static readonly List<Action> LeftToolbarGUI = new();
private static readonly List<Action> RightToolbarGUI = new();
static CustomUnityToolbar()
{
CustomUnityToolbarCallback.OnToolbarGUILeft = () => { DrawToolbar(LeftToolbarGUI); };
CustomUnityToolbarCallback.OnToolbarGUIRight = () => { DrawToolbar(RightToolbarGUI); };
}
private static void DrawToolbar(List<Action> toolbarActions)
{
EditorGUILayout.BeginHorizontal();
foreach (var action in toolbarActions) action();
EditorGUILayout.EndHorizontal();
}
}
}

View File

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

View File

@ -0,0 +1,58 @@
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace BuildCli
{
public static class CustomUnityToolbarCallback
{
private static readonly Type MToolbarType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.Toolbar");
private static ScriptableObject _mCurrentToolbar;
private static Action _onToolbarGUI;
public static Action OnToolbarGUILeft;
public static Action OnToolbarGUIRight;
static CustomUnityToolbarCallback()
{
EditorApplication.delayCall -= OnUpdate;
EditorApplication.delayCall += OnUpdate;
}
private static void OnUpdate()
{
if (_mCurrentToolbar != null) return;
var toolbars = Resources.FindObjectsOfTypeAll(MToolbarType);
_mCurrentToolbar = toolbars.Length > 0 ? (ScriptableObject) toolbars[0] : null;
if (_mCurrentToolbar == null) return;
var root = _mCurrentToolbar.GetType()
.GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance);
var mRoot = root?.GetValue(_mCurrentToolbar) as VisualElement;
if (mRoot == null) return;
var playButton = mRoot.Q("Play");
var extendedPlayModeToolbar = new PlayModeToolbar();
mRoot.Q("ToolbarZoneRightAlign").Add(extendedPlayModeToolbar);
RegisterCallback("ToolbarZoneLeftAlign", OnToolbarGUILeft);
RegisterCallback("ToolbarZoneRightAlign", OnToolbarGUIRight);
}
private static void RegisterCallback(string root, Action action)
{
var toolbarZone =
_mCurrentToolbar?.GetType().GetProperty(root)?.GetValue(_mCurrentToolbar) as VisualElement;
if (toolbarZone == null) return;
var container = new IMGUIContainer();
container.onGUIHandler = () => { action?.Invoke(); };
container.style.flexGrow = 1;
container.style.flexDirection = FlexDirection.Row;
toolbarZone.Add(container);
}
}
}

View File

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

View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2024 Disillusion
Copyright (c) 2023-2024 TippingGame tippinggame@163.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8da90e55807a3d24bac1ac41360d16bd
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using YooAsset;
namespace BuildCli
{
public class PlayModeManager
{
private string[] _playmodeSettings;
private Dictionary<string, EPlayMode> _resourceModeSettings = new Dictionary<string, EPlayMode>
{
{ "编辑器模式", EPlayMode.EditorSimulateMode },
{ "单机模式", EPlayMode.OfflinePlayMode },
{ "热更模式", EPlayMode.HostPlayMode },
};
private static string PrefsKey => Application.dataPath.GetHashCode() + "GamePlayMode";
public static void EditorStartScene() => EditorSceneManager.playModeStartScene = null;
public void PlayScene()
{
if (!EditorApplication.isPlaying)
{
EditorApplication.isPlaying = true;
}
else
EditorApplication.isPlaying = false;
}
public List<string> GenerateResourceModeList()
{
return _resourceModeSettings.Keys.ToList();
}
public void SetPlayMode(string value)
{
if (_resourceModeSettings.TryGetValue(value, out EPlayMode playMode))
{
EditorPrefs.SetInt(PrefsKey, (int)playMode);
}
}
public int GetSelectPlayMode()
{
var selectIndex = EditorPrefs.GetInt(PrefsKey, -1);
if (selectIndex == -1)
{
selectIndex = (int)EPlayMode.EditorSimulateMode;
EditorPrefs.SetInt(PrefsKey, selectIndex);
}
return selectIndex;
}
public string GetSelectPlayModeValue()
{
var selectIndex = EditorPrefs.GetInt(PrefsKey, -1);
if (selectIndex == -1)
{
selectIndex = (int)EPlayMode.EditorSimulateMode;
EditorPrefs.SetInt(PrefsKey, selectIndex);
}
EPlayMode mode = (EPlayMode)selectIndex;
return mode.ToString();
}
public List<string> GeneratePlayModeSettingsList()
{
_playmodeSettings = new[]
{
"Default (Reload Domain, Reload Scene)", "Disable Reload Domain", "Disable Reload Scene", "Disable All"
};
var playModeSettingsList = new List<string>(_playmodeSettings);
return playModeSettingsList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b51aeed2989245259b93bddc8922b086
timeCreated: 1676311145

View File

@ -0,0 +1,133 @@
.plus-button {
background-color: rgb(56, 56, 56);
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border-color: rgba(56, 56, 56, 0);
border-width: 11px;
}
.plus-button:hover {
background-color: rgb(75, 75, 75);
-unity-background-image-tint-color: rgb(255, 255, 255);
-unity-background-scale-mode: scale-to-fit;
}
.plus-button:active {
background-color: rgb(0, 0, 0);
-unity-background-image-tint-color: rgb(89, 158, 94);
}
.unity-base-field {
width: 31px;
height: 100%;
background-image: none;
background-color: rgba(0, 0, 0, 0);
-unity-background-scale-mode: scale-to-fit;
justify-content: center;
margin-left: 0px;
margin-right: 1px;
margin-top: 0px;
margin-bottom: 0px;
border-top-width: 0px;
}
.unity-base-field:hover .unity-base-popup-field__input {
background-color: rgb(75, 75, 75);
-unity-background-image-tint-color: rgb(255, 255, 255);
}
.unity-base-field__input {
padding-bottom: 0px;
border-width: 0px;
border-top-width: 0px;
justify-content: center;
align-items: center;
height: 100%;
-unity-background-scale-mode: scale-to-fit;
}
.unity-base-popup-field__input {
border-radius: 0px;
-unity-background-scale-mode: scale-to-fit;
border-top-width: 0px;
min-width: 31px;
background-color: rgb(56, 56, 56);
background-image: none;
justify-content: center;
align-items: center;
height: 100%;
}
.scene-select-dropdown .unity-base-popup-field__input {
background-image: url('project://database/Packages/com.disillusion.play-mode-plus/Editor/Resources/com.disillusion.play-mode-plus/CustomDropdownArrow.png?fileID=2800000&guid=d56d19b3e6d0fc0419cda6972838d5ba&type=3#CustomDropdownArrow');
-unity-background-scale-mode: scale-to-fit;
width: 14px;
height: 21px;
margin-left: 0px;
margin-right: 0px;
margin-top: 0px;
margin-bottom: 0px;
justify-content: center;
padding-left: 0px;
padding-right: 0px;
padding-top: 0px;
padding-bottom: 0px;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border-color: rgba(56, 56, 56, 0);
border-width: 11px;
}
.play-mode-settings-dropdown .unity-base-popup-field__input {
background-image: url('project://database/Packages/com.disillusion.play-mode-plus/Editor/Resources/com.disillusion.play-mode-plus/CustomSceneCogButton.png?fileID=2800000&guid=b620a07f1fa7bf54b874f9661d2c6140&type=3#CustomSceneCogButton');
-unity-background-scale-mode: scale-to-fit;
border-color: rgba(56, 56, 56, 0);
border-width: 11px;
border-radius: 5px;
}
.build-settings-select-dropdown .unity-base-popup-field__input {
background-image: url('project://database/Packages/com.disillusion.play-mode-plus/Editor/Resources/com.disillusion.play-mode-plus/CustomDropdownArrow.png?fileID=2800000&guid=d56d19b3e6d0fc0419cda6972838d5ba&type=3#CustomDropdownArrow');
-unity-background-scale-mode: scale-to-fit;
width: auto;
height: 21px;
justify-content: center;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
border-color: rgba(56, 56, 56, 0);
border-width: 11px;
}
.dropdown-override {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
border-color: rgba(56, 56, 56, 0);
border-width: 8px;
width: 6px;
margin-left: 9px;
margin-right: 12px;
padding: 0px;
}
.unity-base-popup-field__input:hover {
background-color: rgb(75, 75, 75);
-unity-background-image-tint-color: rgb(255, 255, 255);
}
.unity-base-popup-field__arrow {
display: none;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
border-color: rgba(56, 56, 56, 0);
border-width: 11px;
}
.unity-base-popup-field__text {
display: none;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
border-color: rgba(56, 56, 56, 0);
border-width: 11px;
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 88ed63fd5c4857c43a3dbb9672116bb3
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@ -0,0 +1,122 @@
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using YooAsset;
namespace BuildCli
{
public class PlayModeToolbar : VisualElement
{
private readonly PlayModeManager _playModeManager = new();
private readonly BuildManager _buildManager = new();
private readonly Button _buildButton;
private readonly DropdownField _selectSceneDropdown;
private readonly DropdownField _selectPlayModeSettingsDropdown;
private readonly DropdownField _selectPlayerSettingsPresetsDropdown;
public PlayModeToolbar()
{
#if UNITY_6000_0_OR_NEWER
var visualTree = Resources.Load<VisualTreeAsset>("com.disillusion.play-mode-plus/PlayModePlusToolbar6000");
#else
var visualTree = Resources.Load<VisualTreeAsset>("com.disillusion.play-mode-plus/PlayModePlusToolbar");
#endif
visualTree.CloneTree(this);
style.flexGrow = 1;
_buildButton = this.Q<Button>("build-button");
_buildButton.clicked -= OnBuildClicked;
_buildButton.clicked += OnBuildClicked;
#region Select Scene Dropdown
_selectSceneDropdown = this.Q<DropdownField>("select-scene-dropdown");
_selectSceneDropdown.RegisterCallback<FocusEvent>(evt =>
_selectSceneDropdown.choices = _playModeManager.GenerateResourceModeList());
_selectSceneDropdown.RegisterCallback<ChangeEvent<string>>(evt => { _playModeManager.SetPlayMode(evt.newValue); });
#endregion
#region Play Mode Settings Dropdown
_selectPlayModeSettingsDropdown = this.Q<DropdownField>("play-mode-settings-dropdown");
_selectPlayModeSettingsDropdown.RegisterCallback<FocusEvent>(evt =>
_selectSceneDropdown.choices = _playModeManager.GenerateResourceModeList());
_selectPlayModeSettingsDropdown.RegisterCallback<ChangeEvent<string>>(evt =>
{
var editorSettings = new SerializedObject(
AssetDatabase.LoadAssetAtPath("ProjectSettings/EditorSettings.asset", typeof(Object)));
var enterPlayModeOptionsEnabled =
editorSettings.FindProperty("m_EnterPlayModeOptionsEnabled");
var enterPlayModeOptions = editorSettings.FindProperty("m_EnterPlayModeOptions");
switch (_selectPlayModeSettingsDropdown.value)
{
case "Default (Reload Domain, Reload Scene":
enterPlayModeOptionsEnabled.boolValue = false;
enterPlayModeOptions.intValue = (int)EnterPlayModeOptions.None;
break;
case "Disable Reload Domain":
enterPlayModeOptionsEnabled.boolValue = true;
enterPlayModeOptions.intValue = (int)EnterPlayModeOptions.DisableDomainReload;
break;
case "Disable Reload Scene":
enterPlayModeOptionsEnabled.boolValue = true;
enterPlayModeOptions.intValue = (int)EnterPlayModeOptions.DisableSceneReload;
break;
case "Disable All":
enterPlayModeOptionsEnabled.boolValue = true;
enterPlayModeOptions.intValue |= (int)EnterPlayModeOptions.DisableDomainReload;
enterPlayModeOptions.intValue |= (int)EnterPlayModeOptions.DisableSceneReload;
break;
default:
enterPlayModeOptionsEnabled.boolValue = false;
enterPlayModeOptions.intValue = (int)EnterPlayModeOptions.None;
break;
}
editorSettings.ApplyModifiedProperties();
EditorUtility.SetDirty(editorSettings.targetObject);
AssetDatabase.SaveAssets();
});
#endregion
#region Build Settings Dropdown
_selectPlayerSettingsPresetsDropdown = this.Q<DropdownField>("build-settings-dropdown");
_selectPlayerSettingsPresetsDropdown.RegisterCallback<FocusEvent>(evt =>
_selectPlayerSettingsPresetsDropdown.choices = _buildManager.GenerateBuildSettingsList());
_selectPlayerSettingsPresetsDropdown.RegisterCallback<ChangeEvent<string>>(evt =>
{
_buildManager.SelectedBuildPreset =
_buildManager.PlayerSettingsPresetsInProject.FirstOrDefault(presets =>
presets.name == evt.newValue);
BuildManager.ApplyPreset(_buildManager.SelectedBuildPreset);
});
#endregion
// Set the play mode scene for Default play button
PlayModeManager.EditorStartScene();
// Populate Dropdowns
_selectSceneDropdown.choices = _playModeManager.GenerateResourceModeList();
_selectPlayModeSettingsDropdown.choices = _playModeManager.GeneratePlayModeSettingsList();
_selectPlayerSettingsPresetsDropdown.choices = _buildManager.GenerateBuildSettingsList();
// Set Select Scene Dropdown value to Last Scene which was opened
_selectSceneDropdown.index = _playModeManager.GetSelectPlayMode();
}
private void OnBuildClicked() => _buildManager.OpenBuildWindow();
}
}

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

View File

@ -0,0 +1,183 @@
fileFormatVersion: 2
guid: e663f57b9e7db7544b771960de59b03f
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Windows Store Apps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: tvOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

View File

@ -0,0 +1,183 @@
fileFormatVersion: 2
guid: d56d19b3e6d0fc0419cda6972838d5ba
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Windows Store Apps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: tvOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

View File

@ -0,0 +1,183 @@
fileFormatVersion: 2
guid: 9f501d46ce416b04ab9b2795a65e9dbc
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Windows Store Apps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: tvOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

View File

@ -0,0 +1,183 @@
fileFormatVersion: 2
guid: 403347ecfd3420b4fbd207759127cfe3
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Windows Store Apps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: tvOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

View File

@ -0,0 +1,183 @@
fileFormatVersion: 2
guid: b620a07f1fa7bf54b874f9661d2c6140
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Windows Store Apps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: tvOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<Style src="project://database/Assets/Editor/PlayModePlus/PlayModePlus.uss?fileID=7433441132597879392&amp;guid=88ed63fd5c4857c43a3dbb9672116bb3&amp;type=3#PlayModePlus" />
<ui:VisualElement name="VisualElement" style="overflow: visible; flex-direction: row; align-items: center;">
<ui:DropdownField index="-1" name="select-scene-dropdown" tooltip="Select PlayMode Scene" class="scene-select-dropdown dropdown-override" style="top: 0; align-items: flex-start; -unity-slice-scale: 1px; background-position-y: center 0; background-position-x: center 0; justify-content: center; align-self: auto; align-content: flex-start; border-top-width: 0;" />
<ui:DropdownField index="-1" name="play-mode-settings-dropdown" tooltip="PlayMode Settings" class="play-mode-settings-dropdown" style="height: 22px; top: 0;" />
<ui:Button display-tooltip-when-elided="true" tooltip="Build" name="build-button" class="unity-toolbar-toogle plus-button" style="width: 31px; height: 21px; margin-left: 4px; margin-right: 1px; margin-top: 0; margin-bottom: 1px; padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; background-image: url(&quot;project://database/Assets/Editor/PlayModePlus/Resources/com.disillusion.play-mode-plus/CustomBuildButtonOutlined.png?fileID=2800000&amp;guid=e663f57b9e7db7544b771960de59b03f&amp;type=3#CustomBuildButtonOutlined&quot;); -unity-background-scale-mode: scale-to-fit; top: 0;" />
<ui:DropdownField index="-1" name="build-settings-dropdown" tooltip="Select Build Settings Preset" class="build-settings-select-dropdown dropdown-override" style="top: 0; align-items: flex-start; justify-content: center; align-content: flex-start; align-self: auto; border-top-width: 0;" />
</ui:VisualElement>
</ui:UXML>

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 272ada475cb34cb4eabd26fb225d13f5
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@ -0,0 +1,9 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<Style src="project://database/Assets/Editor/PlayModePlus/PlayModePlus.uss?fileID=7433441132597879392&amp;guid=88ed63fd5c4857c43a3dbb9672116bb3&amp;type=3#PlayModePlus" />
<ui:VisualElement name="VisualElement" style="overflow: visible; flex-direction: row; align-items: center;">
<ui:DropdownField index="-1" name="select-scene-dropdown" tooltip="Select PlayMode Scene" class="scene-select-dropdown dropdown-override" style="top: 0; align-items: flex-start; -unity-slice-scale: 1px; background-position-y: center 0; background-position-x: center 0; justify-content: center; align-self: auto; align-content: flex-start;" />
<ui:DropdownField index="-1" name="play-mode-settings-dropdown" tooltip="PlayMode Settings" class="play-mode-settings-dropdown" style="height: 22px; top: 0;" />
<ui:Button display-tooltip-when-elided="true" tooltip="Build" name="build-button" class="unity-toolbar-toogle plus-button" style="width: 31px; height: 21px; margin-left: 4px; margin-right: 1px; margin-top: 0; margin-bottom: 1px; padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; background-image: url(&quot;project://database/Assets/Editor/PlayModePlus/Resources/com.disillusion.play-mode-plus/CustomBuildButtonOutlined.png?fileID=2800000&amp;guid=e663f57b9e7db7544b771960de59b03f&amp;type=3#CustomBuildButtonOutlined&quot;); -unity-background-scale-mode: scale-to-fit; top: 0;" />
<ui:DropdownField index="-1" name="build-settings-dropdown" tooltip="Select Build Settings Preset" class="build-settings-select-dropdown dropdown-override" style="top: 0; align-items: flex-start; justify-content: center; align-content: flex-start; align-self: auto;" />
</ui:VisualElement>
</ui:UXML>

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 20cdb8c96ae40c34b90f6be123593c91
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

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

View File

@ -0,0 +1,549 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
using Object = UnityEngine.Object;
namespace GameFramework.Editor
{
/// <summary>
/// 图集导入管线。
/// </summary>
public class SpritePostprocessor : AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
foreach (var s in importedAssets)
{
EditorSpriteSaveInfo.OnImportSprite(s);
}
foreach (var s in deletedAssets)
{
EditorSpriteSaveInfo.OnDeleteSprite(s);
}
foreach (var s in movedFromAssetPaths)
{
EditorSpriteSaveInfo.OnDeleteSprite(s);
}
foreach (var s in movedAssets)
{
EditorSpriteSaveInfo.OnImportSprite(s);
}
}
}
public static class EditorSpriteSaveInfo
{
private const string NormalAtlasDir = "Assets/AssetArt/Atlas";
private const string UISpritePath = "Assets/AssetRaw/UIRaw";
private const string UIAtlasPath = "Assets/AssetRaw/UIRaw/Atlas";
private static readonly List<string> _dirtyAtlasList = new List<string>();
private static readonly Dictionary<string, List<string>> _allASprites = new Dictionary<string, List<string>>();
private static readonly Dictionary<string, string> _uiAtlasMap = new Dictionary<string, string>();
private static bool _isInit = false;
private static bool m_dirty = false;
public static void Init()
{
if (_isInit)
{
return;
}
EditorApplication.update += CheckDirty;
//读取所有图集信息
string[] findAssets = AssetDatabase.FindAssets("t:SpriteAtlas", new[] { NormalAtlasDir });
foreach (var findAsset in findAssets)
{
var path = AssetDatabase.GUIDToAssetPath(findAsset);
SpriteAtlas sa = AssetDatabase.LoadAssetAtPath(path, typeof(SpriteAtlas)) as SpriteAtlas;
if (sa == null)
{
Debug.LogError($"加载图集数据{path}失败");
continue;
}
string atlasName = Path.GetFileNameWithoutExtension(path);
var objects = sa.GetPackables();
foreach (var o in objects)
{
if (!_allASprites.TryGetValue(atlasName, out var list))
{
list = new List<string>();
_allASprites.Add(atlasName, list);
}
list.Add(AssetDatabase.GetAssetPath(o));
}
}
_isInit = true;
}
public static void CheckDirty()
{
if (m_dirty)
{
m_dirty = false;
AssetDatabase.Refresh();
float lastProgress = -1;
for (int i = 0; i < _dirtyAtlasList.Count; i++)
{
string atlasName = _dirtyAtlasList[i];
Debug.Log("更新图集 : " + atlasName);
var curProgress = (float)i / _dirtyAtlasList.Count;
if (curProgress > lastProgress + 0.01f)
{
lastProgress = curProgress;
var progressText = $"当前进度:{i}/{_dirtyAtlasList.Count} {atlasName}";
bool cancel = EditorUtility.DisplayCancelableProgressBar("刷新图集" + atlasName, progressText, curProgress);
if (cancel)
{
break;
}
}
bool isUI = atlasName.StartsWith("UIRaw");
SaveAtlas(atlasName, isUI);
}
EditorUtility.ClearProgressBar();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
_dirtyAtlasList.Clear();
}
}
public static void OnImportSprite(string assetPath)
{
if (!assetPath.StartsWith(UISpritePath))
{
return;
}
TextureImporter ti = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (ti != null)
{
var modify = false;
if (assetPath.StartsWith(UISpritePath))
{
if (ti.textureType != TextureImporterType.Sprite)
{
ti.textureType = TextureImporterType.Sprite;
modify = true;
}
if (!string.IsNullOrEmpty(ti.spritePackingTag))
{
ti.spritePackingTag = string.Empty;
modify = true;
}
var setting = new TextureImporterSettings();
ti.ReadTextureSettings(setting);
if (setting.spriteGenerateFallbackPhysicsShape)
{
setting.spriteGenerateFallbackPhysicsShape = false;
ti.SetTextureSettings(setting);
modify = true;
}
if (IsKeepRawImage(assetPath))
{
//调整android格式
var andPlatformSettings = ti.GetPlatformTextureSettings("Android");
if (!andPlatformSettings.overridden)
{
andPlatformSettings.overridden = true;
modify = true;
}
if (andPlatformSettings.format != TextureImporterFormat.ASTC_6x6)
{
andPlatformSettings.format = TextureImporterFormat.ASTC_6x6;
andPlatformSettings.compressionQuality = 50;
ti.SetPlatformTextureSettings(andPlatformSettings);
modify = true;
}
//调整ios格式
var iosPlatformSettings = ti.GetPlatformTextureSettings("iPhone");
if (!iosPlatformSettings.overridden)
{
iosPlatformSettings.overridden = true;
modify = true;
}
if (iosPlatformSettings.format != TextureImporterFormat.ASTC_5x5)
{
iosPlatformSettings.format = TextureImporterFormat.ASTC_5x5;
iosPlatformSettings.compressionQuality = 50;
ti.SetPlatformTextureSettings(iosPlatformSettings);
modify = true;
}
//调整WebGL格式
var webglSettings = ti.GetPlatformTextureSettings("WebGL");
if (!webglSettings.overridden)
{
webglSettings.overridden = true;
modify = true;
}
if (webglSettings.format != TextureImporterFormat.ASTC_6x6)
{
webglSettings.format = TextureImporterFormat.ASTC_6x6;
webglSettings.compressionQuality = 50;
ti.SetPlatformTextureSettings(webglSettings);
modify = true;
}
}
}
if (modify)
{
ti.SaveAndReimport();
}
if (ti.textureType == TextureImporterType.Sprite)
{
OnProcessSprite(assetPath);
}
}
}
/// <summary>
/// 是否保持散图(不打图集)
/// </summary>
/// <param name="dirPath"></param>
/// <returns></returns>
public static bool IsKeepRawImage(string dirPath)
{
return dirPath.Contains("UIRaw/Raw/") || dirPath.Contains("UIRaw_Raw_");
}
public static string GetSpritePath(string assetPath)
{
string path = assetPath.Substring(0, assetPath.LastIndexOf(".", StringComparison.Ordinal));
path = path.Replace("Assets/AssetRaw/", "");
return path;
}
/// <summary>
/// 根据文件路径,返回图集名称
/// </summary>
/// <param name="fullName"></param>
/// <returns></returns>
public static string GetPackageTag(string fullName)
{
fullName = fullName.Replace("\\", "/");
int idx = fullName.LastIndexOf("UIRaw", StringComparison.Ordinal);
if (idx == -1)
{
return "";
}
if (IsKeepRawImage(fullName))
{
return "";
}
var atlasPath = fullName.Substring(idx);
string str = atlasPath;
str = str.Substring(0, str.LastIndexOf("/", StringComparison.Ordinal)).Replace("/", "_");
return str;
}
public static void OnProcessSprite(string assetPath)
{
if (!assetPath.StartsWith("Assets"))
{
return;
}
if (assetPath.StartsWith("Assets/UIRaw_Delete"))
{
return;
}
Init();
var spriteName = Path.GetFileNameWithoutExtension(assetPath);
var spritePath = GetSpritePath(assetPath);
if (!_uiAtlasMap.TryGetValue(spriteName, out string oldAssetPath) || spritePath == oldAssetPath)
{
_uiAtlasMap[spriteName] = spritePath;
m_dirty = true;
}
else
{
Debug.LogError($"有重名的图片:{spriteName}\n旧图集{oldAssetPath}\n新图集{spritePath} ");
_uiAtlasMap[spriteName] = spritePath;
m_dirty = true;
}
string atlasName = GetPackageTag(assetPath);
if (string.IsNullOrEmpty(atlasName))
{
bool keepRaw = IsKeepRawImage(assetPath);
if (!keepRaw)
{
Debug.LogError($"empty packingTag of asset :{assetPath} !!!");
}
return;
}
else
{
List<string> ret;
if (!_allASprites.TryGetValue(atlasName, out ret))
{
ret = new List<string>();
_allASprites.Add(atlasName, ret);
}
if (!ret.Contains(assetPath))
{
ret.Add(assetPath);
m_dirty = true;
if (!_dirtyAtlasList.Contains(atlasName))
{
_dirtyAtlasList.Add(atlasName);
}
}
}
}
public static void OnDeleteSprite(string assetPath)
{
if (assetPath.StartsWith("Assets/UIRaw_Delete"))
{
return;
}
if (!assetPath.StartsWith(UISpritePath))
{
return;
}
Init();
string atlasName = GetPackageTag(assetPath);
if (!_allASprites.TryGetValue(atlasName, out var ret))
{
return;
}
//改成文件名的匹配
if (!ret.Exists(s => Path.GetFileName(s) == Path.GetFileName(assetPath)))
{
return;
}
if (assetPath.StartsWith(UISpritePath))
{
var spriteName = Path.GetFileNameWithoutExtension(assetPath);
if (_uiAtlasMap.ContainsKey(spriteName))
{
_uiAtlasMap.Remove(spriteName);
m_dirty = true;
}
}
ret.Remove(assetPath);
m_dirty = true;
if (!_dirtyAtlasList.Contains(atlasName))
{
_dirtyAtlasList.Add(atlasName);
}
}
#region
public static void SaveAtlas(string atlasName, bool isUI)
{
List<Object> spriteList = new List<Object>();
if (_allASprites.TryGetValue(atlasName, out var list))
{
list.Sort(StringComparer.Ordinal);
foreach (var s in list)
{
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(s);
if (sprite != null)
{
spriteList.Add(sprite);
}
}
}
var path = $"{NormalAtlasDir}/{atlasName}.spriteatlas";
if (spriteList.Count == 0)
{
if (File.Exists(path))
{
AssetDatabase.DeleteAsset(path);
}
return;
}
var atlas = new SpriteAtlas();
// var atlas = new SpriteAtlasAsset();
var setting = new SpriteAtlasPackingSettings
{
blockOffset = 1,
padding = 2,
enableRotation = true
};
bool isOpaque = atlasName.Contains("Opaque");
var textureSetting = new SpriteAtlasTextureSettings
{
generateMipMaps = false,
sRGB = true,
filterMode = FilterMode.Bilinear
};
atlas.SetTextureSettings(textureSetting);
var iphonePlatformSetting = atlas.GetPlatformSettings("iPhone");
if (!iphonePlatformSetting.overridden)
{
iphonePlatformSetting.overridden = true;
iphonePlatformSetting.format = TextureImporterFormat.ASTC_5x5;
iphonePlatformSetting.compressionQuality = 100;
atlas.SetPlatformSettings(iphonePlatformSetting);
}
var androidPlatformSetting = atlas.GetPlatformSettings("Android");
if (!androidPlatformSetting.overridden)
{
androidPlatformSetting.overridden = true;
androidPlatformSetting.format = TextureImporterFormat.ASTC_6x6;
androidPlatformSetting.compressionQuality = 100;
atlas.SetPlatformSettings(androidPlatformSetting);
}
var webglSettings = atlas.GetPlatformSettings("WebGL");
if (!webglSettings.overridden)
{
webglSettings.overridden = true;
webglSettings.format = TextureImporterFormat.ASTC_6x6;
webglSettings.compressionQuality = 50;
atlas.SetPlatformSettings(webglSettings);
}
atlas.SetPackingSettings(setting);
atlas.Add(spriteList.ToArray());
AssetDatabase.CreateAsset(atlas, path);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
#endregion
#region
private static readonly Dictionary<string, List<string>> m_tempAllASprites = new Dictionary<string, List<string>>();
[MenuItem("开发工具/Atlas/重新生成UI图集", false, 90)]
static void ForceGenAtlas()
{
Init();
List<string> needSaveAtlas = new List<string>();
m_tempAllASprites.Clear();
_allASprites.Clear();
var findAssets = AssetDatabase.FindAssets("t:sprite", new[] { UIAtlasPath });
foreach (var findAsset in findAssets)
{
var path = AssetDatabase.GUIDToAssetPath(findAsset);
var atlasName = GetPackageTag(path);
if (!m_tempAllASprites.TryGetValue(atlasName, out var spriteList))
{
spriteList = new List<string>();
m_tempAllASprites[atlasName] = spriteList;
}
if (!spriteList.Contains(path))
{
spriteList.Add(path);
}
}
//有变化的才刷
var iter = m_tempAllASprites.GetEnumerator();
while (iter.MoveNext())
{
bool needSave = false;
var atlasName = iter.Current.Key;
var newSpritesList = iter.Current.Value;
if (_allASprites.TryGetValue(atlasName, out var existSprites))
{
if (existSprites.Count != newSpritesList.Count)
{
needSave = true;
existSprites.Clear();
existSprites.AddRange(newSpritesList);
}
else
{
for (int i = 0; i < newSpritesList.Count; i++)
{
if (!existSprites.Contains(newSpritesList[i]))
{
needSave = true;
break;
}
}
if (needSave)
{
existSprites.Clear();
existSprites.AddRange(newSpritesList);
}
}
}
else
{
needSave = true;
_allASprites.Add(atlasName, new List<string>(newSpritesList));
}
if (needSave && !needSaveAtlas.Contains(atlasName))
{
needSaveAtlas.Add(atlasName);
}
}
iter.Dispose();
foreach (var atlas in needSaveAtlas)
{
Debug.LogFormat("Gen atlas:{0}", atlas);
SaveAtlas(atlas, true);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
SpriteAtlasUtility.PackAllAtlases(EditorUserBuildSettings.activeBuildTarget);
Debug.Log("Gen end");
}
#endregion
}
}

View File

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

View File

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

View File

@ -0,0 +1,56 @@
using UnityEditor;
using UnityEngine;
namespace BuildCli
{
public class GameEditorPrefs
{
// 获取 EditorPrefs 中的字符串
public static string GetString(string key, string value = default)
{
return EditorPrefs.GetString(Application.dataPath.GetHashCode() + key, value);
}
// 设置 EditorPrefs 中的字符串
public static void SetString(string key, string value)
{
EditorPrefs.SetString(Application.dataPath.GetHashCode() + key, value);
}
// 获取 EditorPrefs 中的布尔值
public static bool GetBool(string key, bool defaultValue = default)
{
return EditorPrefs.GetBool(Application.dataPath.GetHashCode() + key, defaultValue);
}
// 设置 EditorPrefs 中的布尔值
public static void SetBool(string key, bool value)
{
EditorPrefs.SetBool(Application.dataPath.GetHashCode() + key, value);
}
// 获取 EditorPrefs 中的整数值
public static int GetInt(string key, int defaultValue = default)
{
return EditorPrefs.GetInt(Application.dataPath.GetHashCode() + key, defaultValue);
}
// 设置 EditorPrefs 中的整数值
public static void SetInt(string key, int value)
{
EditorPrefs.SetInt(Application.dataPath.GetHashCode() + key, value);
}
// 获取 EditorPrefs 中的浮点值
public static float GetFloat(string key, float defaultValue = default)
{
return EditorPrefs.GetFloat(Application.dataPath.GetHashCode() + key, defaultValue);
}
// 设置 EditorPrefs 中的浮点值
public static void SetFloat(string key, float value)
{
EditorPrefs.SetFloat(Application.dataPath.GetHashCode() + key, value);
}
}
}

View File

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

View File

@ -0,0 +1,70 @@
using UnityEngine;
using UnityEditor;
using System;
namespace BuildCli
{
public class CaptureWindow : EditorWindow
{
private string saveFileName = string.Empty;
private string saveDirPathKey = "CaptureSaveDirPathKey";
[UnityEditor.MenuItem("开发工具/截图工具", false, 102)]
private static void Capture()
{
if (HasOpenInstances<CaptureWindow>())
{
EditorWindow.GetWindow<CaptureWindow>("截图工具").Close();
}
else
{
EditorWindow.GetWindow<CaptureWindow>("截图工具");
}
}
private void OnGUI()
{
string buildPath = GameEditorPrefs.GetString(saveDirPathKey, Application.dataPath);
EditorGUILayout.LabelField("输出目录 : ");
EditorGUILayout.LabelField(buildPath);
if (GUILayout.Button("选择目录"))
{
string path = EditorUtility.OpenFolderPanel("选择目录", buildPath, Application.dataPath);
if (!string.IsNullOrEmpty(path))
{
GameEditorPrefs.SetString(saveDirPathKey, path);
}
}
if (GUILayout.Button("打开目录"))
{
string openPath = GameEditorPrefs.GetString(saveDirPathKey, Application.dataPath);
System.Diagnostics.Process.Start(openPath);
}
// insert blank line
GUILayout.Label("");
if (GUILayout.Button("截图"))
{
var resolution = GetMainGameViewSize();
int x = (int)resolution.x;
int y = (int)resolution.y;
Debug.Log(buildPath);
var outputPath = buildPath + "/" + DateTime.Now.ToString($"{x}x{y}_yyyy_MM_dd_HH_mm_ss") + ".png";
ScreenCapture.CaptureScreenshot(outputPath);
Debug.Log("保存路径:" + outputPath);
}
}
public static Vector2 GetMainGameViewSize()
{
System.Type T = System.Type.GetType("UnityEditor.GameView,UnityEditor");
System.Reflection.MethodInfo GetSizeOfMainGameView = T.GetMethod("GetSizeOfMainGameView",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
System.Object Res = GetSizeOfMainGameView.Invoke(null, null);
return (Vector2)Res;
}
}
}

View File

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

View File

@ -308,6 +308,52 @@ MonoBehaviour:
componentType:
m_CheckCanReleaseInterval: 30
m_AutoReleaseInterval: 60
--- !u!1 &354344801
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 354344802}
- component: {fileID: 354344803}
m_Layer: 0
m_Name: UI
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &354344802
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 354344801}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1455375114}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &354344803
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 354344801}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 028204b1d2277bd4782816ee91aeed81, type: 3}
m_Name:
m_EditorClassIdentifier:
componentType: AlicizaX.UI.Runtime.UIManager
uiRoot: {fileID: 4612363183729467837, guid: 9368ff38b2090b2468f8358242026e4b, type: 3}
--- !u!1 &539295520
GameObject:
m_ObjectHideFlags: 0
@ -446,6 +492,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
componentType: AlicizaX.Procedure.Runtime.ProcedureManager
m_AvailableProcedureTypeNames:
- Unity.Startup.Procedure.ProcedureClearCache
- Unity.Startup.Procedure.ProcedureCreateDownloader
- Unity.Startup.Procedure.ProcedureDownloadWebFiles
- Unity.Startup.Procedure.ProcedureGameLauncherState
@ -752,7 +799,6 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 2081231531}
- {fileID: 2121063206}
- {fileID: 2066725839}
- {fileID: 804333830}
@ -766,6 +812,8 @@ Transform:
- {fileID: 2030429591}
- {fileID: 965054550}
- {fileID: 559090127}
- {fileID: 2081231531}
- {fileID: 354344802}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1455375115

View File

@ -19,7 +19,6 @@ namespace GameLogic
public static void Entrance(object[] objects)
{
Log.Info("HotFix Logic Entry!");
Log.Info("热更222!");
LoadConfig();
TestLog().Forget();
}
@ -64,4 +63,4 @@ namespace GameLogic
return ByteBuf.Wrap(bytes);
}
}
}
}

View File

@ -0,0 +1,29 @@
using AlicizaX.Resource.Runtime;
using AlicizaX.Fsm.Runtime;
using AlicizaX.Procedure.Runtime;
using AlicizaX.Runtime;
using UnityEngine;
using YooAsset;
namespace Unity.Startup.Procedure
{
internal sealed class ProcedureClearCache : ProcedureBase
{
private IFsm<IProcedureManager> owner;
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
Log.Info("开始清理包裹无用缓存!");
owner = procedureOwner;
ClearUnusedBundleFilesOperation operation = GameApp.Resource.ClearUnusedCacheFilesAsync();
operation.Completed += ClearCacheCompleted;
}
private void ClearCacheCompleted(AsyncOperationBase obj)
{
Log.Debug($"清理包裹缓存完成");
ChangeState<ProcedureLoadAssembly>(owner);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b0ff1b60245f47dbad916144240bbcc2
timeCreated: 1737685923

View File

@ -13,7 +13,7 @@ namespace Unity.Startup.Procedure
{
base.OnEnter(procedureOwner);
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(ResourceComponent.BuildInPackageName, EPatchStates.CreateDownloader));
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(EPatchStates.CreateDownloader));
CreateDownloader(procedureOwner);
}
@ -29,7 +29,7 @@ namespace Unity.Startup.Procedure
procedureOwner.SetData<VarObject>("Downloader", downloaderVarObject);
if (downloader.TotalDownloadCount == 0)
{
Debug.Log("没有发现需要下载的资源");
Log.Info("没有发现需要下载的资源");
ChangeState<ProcedurePatchDone>(procedureOwner);
}
else
@ -45,7 +45,7 @@ namespace Unity.Startup.Procedure
string totalSizeMb = sizeMb.ToString("f1");
Debug.Log($"总共需要下载文件大小为:{totalSizeMb}");
//这里进行确认 如果要下载在进行跳转到Download
GameApp.Event.Fire(this, AssetFoundUpdateFilesEventArgs.Create(downloader.GetPackageName(), totalDownloadCount, totalDownloadBytes));
@ -53,4 +53,4 @@ namespace Unity.Startup.Procedure
}
}
}
}
}

View File

@ -15,7 +15,7 @@ namespace Unity.Startup.Procedure
{
base.OnEnter(procedureOwner);
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(ResourceComponent.BuildInPackageName, EPatchStates.DownloadWebFiles));
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(EPatchStates.DownloadWebFiles));
BeginDownload(procedureOwner).Forget();
}
@ -32,7 +32,7 @@ namespace Unity.Startup.Procedure
ChangeState<ProcedureCreateDownloader>(procedureOwner);
}
downloader.OnDownloadErrorCallback = DownloaderOnDownloadErrorCallback;
downloader.OnDownloadErrorCallback = DownloaderOnDownloadErrorCallback;
downloader.OnDownloadProgressCallback = OnDownloadProgressCallback;
downloader.BeginDownload();
await downloader;
@ -52,4 +52,4 @@ namespace Unity.Startup.Procedure
GameApp.Event.Fire(this, AssetDownloadProgressUpdateEventArgs.Create(packageName, totalDownloadCount, currentDownloadCount, totalDownloadBytes, currentDownloadBytes));
}
}
}
}

View File

@ -11,9 +11,9 @@ namespace Unity.Startup.Procedure
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(ResourceComponent.BuildInPackageName, EPatchStates.PatchDone));
LauncherUIHandler.ShowLogText("补丁流程更新完毕!");
ChangeState<ProcedureLoadAssembly>(procedureOwner);
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(EPatchStates.PatchDone));
Log.Info("补丁流程更新完毕!");
ChangeState<ProcedureClearCache>(procedureOwner);
}
}
}
}

View File

@ -14,7 +14,7 @@ namespace Unity.Startup.Procedure
base.OnEnter(procedureOwner);
if (GameApp.Resource.GamePlayMode == EPlayMode.EditorSimulateMode)
{
await GameApp.Resource.InitPackageAsync(ResourceComponent.BuildInPackageName, string.Empty, string.Empty, true);
await GameApp.Resource.InitPackageAsync();
ChangeState<ProcedureUpdateStaticVersion>(procedureOwner);
return;
}
@ -22,7 +22,7 @@ namespace Unity.Startup.Procedure
if (GameApp.Resource.GamePlayMode == EPlayMode.OfflinePlayMode)
{
Log.Info("当前为离线模式,直接启动 ProcedureUpdateStaticVersion");
await GameApp.Resource.InitPackageAsync(ResourceComponent.BuildInPackageName, string.Empty, string.Empty, true);
await GameApp.Resource.InitPackageAsync();
ChangeState<ProcedureUpdateStaticVersion>(procedureOwner);
return;
}
@ -35,11 +35,10 @@ namespace Unity.Startup.Procedure
string bundleUrl = GlobalConfig.PatchData.BundleUrl;
Log.Info("下载资源的路径:" + bundleUrl);
await GameApp.Resource.InitPackageAsync(ResourceComponent.BuildInPackageName, bundleUrl, bundleUrl, true);
procedureOwner.RemoveData(ResourceComponent.BuildInPackageName);
await GameApp.Resource.InitPackageAsync(string.Empty, bundleUrl, bundleUrl, true);
await UniTask.DelayFrame();
ChangeState<ProcedureUpdateStaticVersion>(procedureOwner);
}
}
}
}

View File

@ -24,7 +24,7 @@ namespace Unity.Startup.Procedure
return;
}
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(ResourceComponent.BuildInPackageName, EPatchStates.UpdateManifest));
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(EPatchStates.UpdateManifest));
UpdateManifest(procedureOwner).Forget();
}
@ -56,11 +56,11 @@ namespace Unity.Startup.Procedure
{
//更新失败
Debug.LogError(buildInOperation.Error);
GameApp.Event.Fire(this, AssetPatchManifestUpdateFailedEventArgs.Create(ResourceComponent.BuildInPackageName, buildInOperation.Error));
GameApp.Event.Fire(this, AssetPatchManifestUpdateFailedEventArgs.Create(buildInOperation.Error));
//询问是否重试
//ChangeState<ProcedureUpdateManifest>(procedureOwner);
}
}
}
}
}

View File

@ -15,14 +15,14 @@ namespace Unity.Startup.Procedure
{
base.OnEnter(procedureOwner);
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(ResourceComponent.BuildInPackageName, EPatchStates.UpdateStaticVersion));
GameApp.Event.Fire(this, AssetPatchStatesChangeEventArgs.Create(EPatchStates.UpdateStaticVersion));
GetStaticVersion(procedureOwner).Forget();
}
private async UniTaskVoid GetStaticVersion(IFsm<IProcedureManager> procedureOwner)
{
var buildInOperation = GameApp.Resource.RequestPackageVersionAsync();
await buildInOperation.ToUniTask();
if (buildInOperation.Status == EOperationStatus.Succeed)
@ -38,9 +38,9 @@ namespace Unity.Startup.Procedure
{
//更新失败
Log.Error(buildInOperation.Error);
GameApp.Event.Fire(this, AssetStaticVersionUpdateFailedEventArgs.Create(ResourceComponent.BuildInPackageName, buildInOperation.Error));
GameApp.Event.Fire(this, AssetStaticVersionUpdateFailedEventArgs.Create(buildInOperation.Error));
ChangeState<ProcedureUpdateStaticVersion>(procedureOwner);
}
}
}
}
}

View File

@ -6,12 +6,20 @@ using UnityEngine;
namespace AlicizaX.Resource.Editor
{
[CustomEditor(typeof(ResourceComponent))]
internal sealed class ResourceComponentInspector: ComponentTypeComponentInspector
internal sealed class ResourceComponentInspector : ComponentTypeComponentInspector
{
private SerializedProperty m_GamePlayMode;
private GUIContent m_GamePlayModeGUIContent = new GUIContent("资源运行模式");
private SerializedProperty m_Milliseconds;
private SerializedProperty m_defaultPackageName;
private SerializedProperty m_AssetAutoReleaseInterval;
private SerializedProperty m_AssetCapacity;
private SerializedProperty m_AssetExpireTime;
private SerializedProperty m_AssetPriority;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
@ -20,22 +28,71 @@ namespace AlicizaX.Resource.Editor
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_GamePlayMode, m_GamePlayModeGUIContent);
long milliseconds = (long)EditorGUILayout.Slider("每帧执行消耗的最大时间切片(ms)", m_Milliseconds.longValue, 30, 100000);
if (milliseconds != m_Milliseconds.longValue)
{
m_Milliseconds.longValue = milliseconds;
}
string packageName = EditorGUILayout.TextField("Package Name", m_defaultPackageName.stringValue);
if (packageName != m_defaultPackageName.stringValue)
{
m_defaultPackageName.stringValue = packageName;
}
float assetAutoReleaseInterval = EditorGUILayout.Slider("对象池自动释放间隔(s)", m_AssetAutoReleaseInterval.floatValue, 60, 3600);
if (assetAutoReleaseInterval != m_AssetAutoReleaseInterval.floatValue)
{
m_AssetAutoReleaseInterval.floatValue = assetAutoReleaseInterval;
}
int assetCapacity = EditorGUILayout.IntSlider("对象池容量", m_AssetCapacity.intValue, 32, 1024);
if (assetCapacity != m_AssetCapacity.intValue)
{
m_AssetCapacity.intValue = assetCapacity;
}
float assetExpireTime = EditorGUILayout.Slider("对象池过期秒数", m_AssetExpireTime.floatValue, 60, 1024);
if (assetExpireTime != m_AssetExpireTime.floatValue)
{
m_AssetExpireTime.floatValue = assetExpireTime;
}
int assetPriority = EditorGUILayout.IntSlider("对象池优先级", m_AssetPriority.intValue, 0, 10);
if (assetPriority != m_AssetPriority.intValue)
{
m_AssetPriority.intValue = assetPriority;
}
}
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void RefreshTypeNames()
{
RefreshComponentTypeNames(typeof(IResourceManager));
}
protected override void Enable()
{
m_GamePlayMode = serializedObject.FindProperty("m_GamePlayMode");
m_Milliseconds = serializedObject.FindProperty("m_Milliseconds");
m_defaultPackageName = serializedObject.FindProperty("m_defaultPackageName");
m_AssetAutoReleaseInterval = serializedObject.FindProperty("m_AssetAutoReleaseInterval");
m_AssetCapacity = serializedObject.FindProperty("m_AssetCapacity");
m_AssetExpireTime = serializedObject.FindProperty("m_AssetExpireTime");
m_AssetPriority = serializedObject.FindProperty("m_AssetPriority");
}
}
}
}

View File

@ -32,7 +32,7 @@ namespace AlicizaX.Resource.Runtime
/// 初始化操作。
/// </summary>
/// <param name="packageName">资源包名称。</param>
UniTask<bool> InitPackageAsync(string packageName, string hostServerURL, string fallbackHostServerURL, bool isDefaultPackage = false);
UniTask<bool> InitPackageAsync(string packageName, string hostServerURL, string fallbackHostServerURL, bool isDefaultPackage = true);
/// <summary>
/// 默认资源包名称。
@ -236,4 +236,4 @@ namespace AlicizaX.Resource.Runtime
#endregion
}
}
}

View File

@ -18,18 +18,18 @@ namespace AlicizaX.Resource.Runtime
[Tooltip("当目标平台为Web平台时将会强制设置为" + nameof(EPlayMode.WebPlayMode))] [SerializeField]
private EPlayMode m_GamePlayMode;
[Range(30, 100000)] [SerializeField] private long m_Milliseconds = 30;
[SerializeField] private long m_Milliseconds = 30;
[SerializeField] private string m_defaultPackageName = "DefaultPackage";
[Range(60, 3600)] [SerializeField] private float m_AssetAutoReleaseInterval = 60;
[SerializeField] private float m_AssetAutoReleaseInterval = 60;
[Range(32, 1024)] [SerializeField] private int m_AssetCapacity = 64;
[SerializeField] private int m_AssetCapacity = 64;
[Range(60, 1024)] [SerializeField] private float m_AssetExpireTime = 60;
[SerializeField] private float m_AssetExpireTime = 60;
[SerializeField] [Range(0, 10)] private int m_AssetPriority = 0;
[SerializeField] private int m_AssetPriority = 0;
/// <summary>
/// 资源的运行模式
@ -40,8 +40,6 @@ namespace AlicizaX.Resource.Runtime
set { m_GamePlayMode = value; }
}
public const string BuildInPackageName = "DefaultPackage";
public const int DefaultPriority = 0;
private IResourceManager m_ResourceManager;
@ -68,15 +66,13 @@ namespace AlicizaX.Resource.Runtime
m_ResourceManager = SysModuleCenter.GetModule<IResourceManager>();
}
private static string PrefsKey => Application.dataPath.GetHashCode() + "GamePlayMode";
protected void Start()
{
if (m_GamePlayMode == EPlayMode.EditorSimulateMode)
{
#if !UNITY_EDITOR
m_GamePlayMode = EPlayMode.OfflinePlayMode;
#if UNITY_EDITOR
m_GamePlayMode = (EPlayMode)UnityEditor.EditorPrefs.GetInt(PrefsKey, 0);
#endif
}
// m_ResourceManager.SetReadOnlyPath(Application.streamingAssetsPath);
// if (config.ReadWritePathType == ReadWritePathType.TemporaryCache)
// {
@ -86,10 +82,7 @@ namespace AlicizaX.Resource.Runtime
// {
// m_ResourceManager.SetReadWritePath(Application.persistentDataPath);
// }
if (string.IsNullOrEmpty(m_defaultPackageName))
{
m_defaultPackageName = BuildInPackageName;
}
m_ResourceManager.DefaultPackageName = m_defaultPackageName;
m_ResourceManager.PlayMode = m_GamePlayMode;
m_ResourceManager.VerifyLevel = EFileVerifyLevel.Middle;
@ -109,7 +102,7 @@ namespace AlicizaX.Resource.Runtime
/// 初始化操作。
/// </summary>
/// <returns></returns>
public async UniTask<bool> InitPackageAsync(string packageName, string host, string fallbackHostServer, bool isDefaultPackage = false)
public async UniTask<bool> InitPackageAsync(string packageName = "", string host = "", string fallbackHostServer = "", bool isDefaultPackage = true)
{
if (m_ResourceManager == null)
{
@ -117,6 +110,11 @@ namespace AlicizaX.Resource.Runtime
return false;
}
if (string.IsNullOrEmpty(packageName))
{
packageName = m_defaultPackageName;
}
return await m_ResourceManager.InitPackageAsync(packageName, host, fallbackHostServer, isDefaultPackage);
}
@ -454,4 +452,4 @@ namespace AlicizaX.Resource.Runtime
#endregion
}
}
}

View File

@ -171,7 +171,7 @@ namespace AlicizaX.Resource.Runtime
}
}
public UniTask<bool> InitPackageAsync(string packageName, string hostServerURL, string fallbackHostServerURL, bool isDefaultPackage = false)
public UniTask<bool> InitPackageAsync(string packageName, string hostServerURL, string fallbackHostServerURL, bool isDefaultPackage = true)
{
if (PackageMap.ContainsKey(packageName))
{
@ -258,7 +258,7 @@ namespace AlicizaX.Resource.Runtime
}
#endregion
#region
/// <summary>
@ -952,7 +952,7 @@ namespace AlicizaX.Resource.Runtime
return package.LoadAssetAsync<T>(location);
}
#endregion
#region
@ -1019,4 +1019,4 @@ namespace AlicizaX.Resource.Runtime
get => 2;
}
}
}
}

View File

@ -11,7 +11,6 @@ namespace AlicizaX.Resource.Runtime
{
public override void Clear()
{
PackageName = null;
Error = null;
}
@ -25,11 +24,6 @@ namespace AlicizaX.Resource.Runtime
get { return EventId; }
}
/// <summary>
/// 包名称
/// </summary>
public string PackageName { get; private set; }
/// <summary>
/// 错误信息
/// </summary>
@ -41,12 +35,11 @@ namespace AlicizaX.Resource.Runtime
/// <param name="packageName">包名称</param>
/// <param name="error">错误信息</param>
/// <returns></returns>
public static AssetPatchManifestUpdateFailedEventArgs Create(string packageName, string error)
public static AssetPatchManifestUpdateFailedEventArgs Create(string error)
{
var assetPatchManifestUpdateFailed = ReferencePool.Acquire<AssetPatchManifestUpdateFailedEventArgs>();
assetPatchManifestUpdateFailed.PackageName = packageName;
assetPatchManifestUpdateFailed.Error = error;
return assetPatchManifestUpdateFailed;
}
}
}
}

View File

@ -11,7 +11,6 @@ namespace AlicizaX.Resource.Runtime
{
public override void Clear()
{
PackageName = null;
CurrentStates = EPatchStates.CreateDownloader;
}
@ -22,10 +21,6 @@ namespace AlicizaX.Resource.Runtime
get { return EventId; }
}
/// <summary>
/// 包名称
/// </summary>
public string PackageName { get; private set; }
/// <summary>
/// 当前步骤
@ -38,12 +33,11 @@ namespace AlicizaX.Resource.Runtime
/// <param name="packageName">包名称</param>
/// <param name="currentStates">当前步骤</param>
/// <returns></returns>
public static AssetPatchStatesChangeEventArgs Create(string packageName, EPatchStates currentStates)
public static AssetPatchStatesChangeEventArgs Create(EPatchStates currentStates)
{
var assetPatchStatesChange = ReferencePool.Acquire<AssetPatchStatesChangeEventArgs>();
assetPatchStatesChange.PackageName = packageName;
assetPatchStatesChange.CurrentStates = currentStates;
return assetPatchStatesChange;
}
}
}
}

View File

@ -11,7 +11,6 @@ namespace AlicizaX.Resource.Runtime
{
public override void Clear()
{
PackageName = null;
Error = null;
}
@ -25,10 +24,6 @@ namespace AlicizaX.Resource.Runtime
get { return EventId; }
}
/// <summary>
/// 包名称
/// </summary>
public string PackageName { get; set; }
/// <summary>
/// 错误信息
@ -41,12 +36,11 @@ namespace AlicizaX.Resource.Runtime
/// <param name="packageName">包名称</param>
/// <param name="error"></param>
/// <returns></returns>
public static AssetStaticVersionUpdateFailedEventArgs Create(string packageName, string error)
public static AssetStaticVersionUpdateFailedEventArgs Create(string error)
{
var assetStaticVersionUpdateFailed = ReferencePool.Acquire<AssetStaticVersionUpdateFailedEventArgs>();
assetStaticVersionUpdateFailed.PackageName = packageName;
assetStaticVersionUpdateFailed.Error = error;
return assetStaticVersionUpdateFailed;
}
}
}
}

View File

@ -4,55 +4,73 @@ using AlicizaX.Runtime;
namespace AlicizaX.Timer.Runtime
{
public delegate void TimerHandler(object[] args);
/// <summary>
/// 定时器接口
/// </summary>
[UnityEngine.Scripting.Preserve]
public interface ITimerManager : IModule, IModuleUpdate
{
List<TimerInfo> GetTimerInfos();
/// <summary>
/// 添加计时器。
/// </summary>
/// <param name="callback">计时器回调。</param>
/// <param name="time">计时器间隔。</param>
/// <param name="isLoop">是否循环。</param>
/// <param name="isUnscaled">是否不收时间缩放影响。</param>
/// <param name="args">传参。(避免闭包)</param>
/// <returns>计时器Id。</returns>
public int AddTimer(TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false, params object[] args);
/// <summary>
/// 添加一个定时调用的任务
/// 暂停计时器。
/// </summary>
/// <param name="interval">间隔时间(以秒为单位)</param>
/// <param name="repeat">重复次数0 表示无限重复)</param>
/// <param name="callback">要执行的回调函数</param>
/// <param name="callbackParam">回调函数的参数(可选)</param>
void Add(float interval, int repeat, Action<object> callback, object callbackParam = null);
/// <param name="timerId">计时器Id。</param>
public void Stop(int timerId);
/// <summary>
/// 添加一个只执行一次的任务
/// 恢复计时器。
/// </summary>
/// <param name="interval">间隔时间(以秒为单位)</param>
/// <param name="callback">要执行的回调函数</param>
/// <param name="callbackParam">回调函数的参数(可选)</param>
void AddOnce(float interval, Action<object> callback, object callbackParam = null);
/// <param name="timerId">计时器Id。</param>
public void Resume(int timerId);
/// <summary>
/// 添加一个每帧更新执行的任务
/// 计时器是否在运行中。
/// </summary>
/// <param name="callback">要执行的回调函数</param>
void AddUpdate(Action<object> callback);
/// <param name="timerId">计时器Id。</param>
/// <returns>否在运行中。</returns>
public bool IsRunning(int timerId);
/// <summary>
/// 添加一个每帧更新执行的任务
/// 获得计时器剩余时间。
/// </summary>
/// <param name="callback">要执行的回调函数</param>
/// <param name="callbackParam">回调函数的参数</param>
void AddUpdate(Action<object> callback, object callbackParam);
public float GetLeftTime(int timerId);
/// <summary>
/// 检查指定的任务是否存在
/// 重置计时器,恢复到开始状态。
/// </summary>
/// <param name="callback">要检查的回调函数</param>
/// <returns>存在返回 true不存在返回 false</returns>
bool Exists(Action<object> callback);
public void Restart(int timerId);
/// <summary>
/// 移除指定的任务
/// 重置计时器。
/// </summary>
/// <param name="callback">要移除的回调函数</param>
void Remove(Action<object> callback);
public void Reset(int timerId, TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false);
/// <summary>
/// 重置计时器。
/// </summary>
public void Reset(int timerId, float time, bool isLoop, bool isUnscaled);
/// <summary>
/// 移除计时器。
/// </summary>
/// <param name="timerId">计时器Id。</param>
public void RemoveTimer(int timerId);
/// <summary>
/// 移除所有计时器。
/// </summary>
public void RemoveAllTimer();
}
}
}

View File

@ -27,71 +27,147 @@ namespace AlicizaX.Timer.Runtime
return;
}
}
/// <summary>
/// 添加一个定时调用的任务
/// <summary>
/// 添加计时器。
/// </summary>
/// <param name="interval">间隔时间(以秒为单位)</param>
/// <param name="repeat">重复次数0 表示无限重复)</param>
/// <param name="callback">要执行的回调函数</param>
/// <param name="callbackParam">回调函数的参数(可选)</param>
public void Add(float interval, int repeat, Action<object> callback, object callbackParam = null)
/// <param name="callback">计时器回调。</param>
/// <param name="time">计时器间隔。</param>
/// <param name="isLoop">是否循环。</param>
/// <param name="isUnscaled">是否不收时间缩放影响。</param>
/// <param name="args">传参。(避免闭包)</param>
/// <returns>计时器Id。</returns>
public int AddTimer(TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false, params object[] args)
{
_timerManager.Add(interval, repeat, callback, callbackParam);
if (_timerManager == null)
{
throw new GameFrameworkException("TimerMgr is invalid.");
}
return _timerManager.AddTimer(callback, time, isLoop, isUnscaled, args);
}
/// <summary>
/// 添加一个只执行一次的任务
/// 暂停计时器。
/// </summary>
/// <param name="interval">间隔时间(以秒为单位)</param>
/// <param name="callback">要执行的回调函数</param>
/// <param name="callbackParam">回调函数的参数(可选)</param>
public void AddOnce(float interval, Action<object> callback, object callbackParam = null)
/// <param name="timerId">计时器Id。</param>
public void Stop(int timerId)
{
_timerManager.AddOnce(interval, callback, callbackParam);
if (_timerManager == null)
{
throw new GameFrameworkException("TimerMgr is invalid.");
}
_timerManager.Stop(timerId);
}
/// <summary>
/// 添加一个每帧更新执行的任务
/// 恢复计时器。
/// </summary>
/// <param name="callback">要执行的回调函数</param>
public void AddUpdate(Action<object> callback)
/// <param name="timerId">计时器Id。</param>
public void Resume(int timerId)
{
_timerManager.AddUpdate(callback);
if (_timerManager == null)
{
throw new GameFrameworkException("TimerMgr is invalid.");
}
_timerManager.Resume(timerId);
}
/// <summary>
/// 添加一个每帧更新执行的任务
/// 计时器是否在运行中。
/// </summary>
/// <param name="callback">要执行的回调函数</param>
/// <param name="callbackParam">回调函数的参数</param>
public void AddUpdate(Action<object> callback, object callbackParam)
/// <param name="timerId">计时器Id。</param>
/// <returns>否在运行中。</returns>
public bool IsRunning(int timerId)
{
_timerManager.AddUpdate(callback, callbackParam);
if (_timerManager == null)
{
throw new GameFrameworkException("TimerMgr is invalid.");
}
return _timerManager.IsRunning(timerId);
}
/// <summary>
/// 检查指定的任务是否存在
/// 获得计时器剩余时间。
/// </summary>
/// <param name="callback">要检查的回调函数</param>
/// <returns>存在返回 true不存在返回 false</returns>
public bool Exists(Action<object> callback)
public float GetLeftTime(int timerId)
{
return _timerManager.Exists(callback);
if (_timerManager == null)
{
throw new GameFrameworkException("TimerMgr is invalid.");
}
return _timerManager.GetLeftTime(timerId);
}
/// <summary>
/// 移除指定的任务
/// 重置计时器,恢复到开始状态。
/// </summary>
/// <param name="callback">要移除的回调函数</param>
public void Remove(Action<object> callback)
public void Restart(int timerId)
{
_timerManager.Remove(callback);
if (_timerManager == null)
{
throw new GameFrameworkException("TimerMgr is invalid.");
}
_timerManager.Restart(timerId);
}
public List<TimerInfo> GetTimerInfos()
/// <summary>
/// 重置计时器。
/// </summary>
public void Reset(int timerId, TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false)
{
return _timerManager.GetTimerInfos();
if (_timerManager == null)
{
throw new GameFrameworkException("TimerMgr is invalid.");
}
_timerManager.Reset(timerId, callback, time, isLoop, isUnscaled);
}
/// <summary>
/// 重置计时器。
/// </summary>
public void Reset(int timerId, float time, bool isLoop, bool isUnscaled)
{
if (_timerManager == null)
{
throw new GameFrameworkException("TimerMgr is invalid.");
}
_timerManager.Reset(timerId, time, isLoop, isUnscaled);
}
/// <summary>
/// 移除计时器。
/// </summary>
/// <param name="timerId">计时器Id。</param>
public void RemoveTimer(int timerId)
{
if (_timerManager == null)
{
Log.Error("TimerMgr is invalid.");
throw new GameFrameworkException("TimerMgr is invalid.");
}
_timerManager.RemoveTimer(timerId);
}
/// <summary>
/// 移除所有计时器。
/// </summary>
public void RemoveAllTimer()
{
if (_timerManager == null)
{
Log.Error("TimerMgr is invalid.");
throw new GameFrameworkException("TimerMgr is invalid.");
}
_timerManager.RemoveAllTimer();
}
}
}
}

View File

@ -5,326 +5,464 @@ using UnityEngine;
namespace AlicizaX.Timer.Runtime
{
public struct TimerInfo
[Serializable]
public class Timer
{
public float Interval;
public int Repeat;
public float Elapsed;
public int timerId = 0;
public float curTime = 0;
public float time = 0;
public TimerHandler Handler;
public bool isLoop = false;
public bool isNeedRemove = false;
public bool isRunning = false;
public bool isUnscaled = false; //是否使用非缩放的时间
public object[] Args = null; //回调参数
}
/// <summary>
/// 定时器管理器
/// </summary>
[UnityEngine.Scripting.Preserve]
internal sealed class TimerManager : ITimerManager
internal sealed class TimerManager : ITimerManager
{
class TimerItem
private int _curTimerId = 0;
private readonly List<Timer> _timerList = new List<Timer>();
private readonly List<Timer> _unscaledTimerList = new List<Timer>();
private readonly List<int> _cacheRemoveTimers = new List<int>();
private readonly List<int> _cacheRemoveUnscaledTimers = new List<int>();
/// <summary>
/// 添加计时器。
/// </summary>
/// <param name="callback">计时器回调。</param>
/// <param name="time">计时器间隔。</param>
/// <param name="isLoop">是否循环。</param>
/// <param name="isUnscaled">是否不收时间缩放影响。</param>
/// <param name="args">传参。(避免闭包)</param>
/// <returns>计时器Id。</returns>
public int AddTimer(TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false, params object[] args)
{
public float Interval;
public int Repeat;
public Action<object> Callback;
public object Param;
public float Elapsed;
public bool Deleted;
public void Set(float interval, int repeat, Action<object> callback, object param)
Timer timer = new Timer
{
this.Interval = interval;
this.Repeat = repeat;
this.Callback = callback;
this.Param = param;
timerId = ++_curTimerId,
curTime = time,
time = time,
Handler = callback,
isLoop = isLoop,
isUnscaled = isUnscaled,
Args = args,
isNeedRemove = false,
isRunning = true
};
InsertTimer(timer);
return timer.timerId;
}
private void InsertTimer(Timer timer)
{
bool isInsert = false;
if (timer.isUnscaled)
{
for (int i = 0, len = _unscaledTimerList.Count; i < len; i++)
{
if (_unscaledTimerList[i].curTime > timer.curTime)
{
_unscaledTimerList.Insert(i, timer);
isInsert = true;
break;
}
}
if (!isInsert)
{
_unscaledTimerList.Add(timer);
}
}
else
{
for (int i = 0, len = _timerList.Count; i < len; i++)
{
if (_timerList[i].curTime > timer.curTime)
{
_timerList.Insert(i, timer);
isInsert = true;
break;
}
}
if (!isInsert)
{
_timerList.Add(timer);
}
}
}
private readonly Dictionary<Action<object>, TimerItem> _items = new Dictionary<Action<object>, TimerItem>();
private readonly Dictionary<Action<object>, TimerItem> _toAdd = new Dictionary<Action<object>, TimerItem>();
private readonly List<TimerItem> _toRemove = new List<TimerItem>();
private readonly List<TimerItem> _pool = new List<TimerItem>(100);
private static readonly object Locker = new object();
/// <summary>
/// 暂停计时器。
/// </summary>
/// <param name="timerId">计时器Id。</param>
public void Stop(int timerId)
{
Timer timer = GetTimer(timerId);
if (timer != null) timer.isRunning = false;
}
/// <summary>
/// 是否触发回调异常
/// 恢复计时器。
/// </summary>
public static bool CatchCallbackExceptions = false;
/// <param name="timerId">计时器Id。</param>
public void Resume(int timerId)
{
Timer timer = GetTimer(timerId);
if (timer != null) timer.isRunning = true;
}
/// <summary>
/// 计时器是否在运行中。
/// </summary>
/// <param name="timerId">计时器Id。</param>
/// <returns>否在运行中。</returns>
public bool IsRunning(int timerId)
{
Timer timer = GetTimer(timerId);
return timer is { isRunning: true };
}
/// <summary>
/// 获得计时器剩余时间
/// </summary>
public float GetLeftTime(int timerId)
{
Timer timer = GetTimer(timerId);
if (timer == null) return 0;
return timer.curTime;
}
/// <summary>
/// 重置计时器,恢复到开始状态。
/// </summary>
public void Restart(int timerId)
{
Timer timer = GetTimer(timerId);
if (timer != null)
{
timer.curTime = timer.time;
timer.isRunning = true;
}
}
/// <summary>
/// 重置计时器。
/// </summary>
public void Reset(int timerId, TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false)
{
Timer timer = GetTimer(timerId);
if (timer != null)
{
timer.curTime = time;
timer.time = time;
timer.Handler = callback;
timer.isLoop = isLoop;
timer.isNeedRemove = false;
if (timer.isUnscaled != isUnscaled)
{
RemoveTimerImmediate(timerId);
timer.isUnscaled = isUnscaled;
InsertTimer(timer);
}
}
}
/// <summary>
/// 重置计时器。
/// </summary>
public void Reset(int timerId, float time, bool isLoop, bool isUnscaled)
{
Timer timer = GetTimer(timerId);
if (timer != null)
{
timer.curTime = time;
timer.time = time;
timer.isLoop = isLoop;
timer.isNeedRemove = false;
if (timer.isUnscaled != isUnscaled)
{
RemoveTimerImmediate(timerId);
timer.isUnscaled = isUnscaled;
InsertTimer(timer);
}
}
}
/// <summary>
/// 立即移除。
/// </summary>
/// <param name="timerId"></param>
private void RemoveTimerImmediate(int timerId)
{
for (int i = 0, len = _timerList.Count; i < len; i++)
{
if (_timerList[i].timerId == timerId)
{
_timerList.RemoveAt(i);
return;
}
}
for (int i = 0, len = _unscaledTimerList.Count; i < len; i++)
{
if (_unscaledTimerList[i].timerId == timerId)
{
_unscaledTimerList.RemoveAt(i);
return;
}
}
}
/// <summary>
/// 移除计时器。
/// </summary>
/// <param name="timerId">计时器Id。</param>
public void RemoveTimer(int timerId)
{
for (int i = 0, len = _timerList.Count; i < len; i++)
{
if (_timerList[i].timerId == timerId)
{
_timerList[i].isNeedRemove = true;
return;
}
}
for (int i = 0, len = _unscaledTimerList.Count; i < len; i++)
{
if (_unscaledTimerList[i].timerId == timerId)
{
_unscaledTimerList[i].isNeedRemove = true;
return;
}
}
}
/// <summary>
/// 移除所有计时器。
/// </summary>
public void RemoveAllTimer()
{
_timerList.Clear();
_unscaledTimerList.Clear();
}
private Timer GetTimer(int timerId)
{
for (int i = 0, len = _timerList.Count; i < len; i++)
{
if (_timerList[i].timerId == timerId)
{
return _timerList[i];
}
}
for (int i = 0, len = _unscaledTimerList.Count; i < len; i++)
{
if (_unscaledTimerList[i].timerId == timerId)
{
return _unscaledTimerList[i];
}
}
return null;
}
private void LoopCallInBadFrame()
{
bool isLoopCall = false;
for (int i = 0, len = _timerList.Count; i < len; i++)
{
Timer timer = _timerList[i];
if (timer.isLoop && timer.curTime <= 0)
{
if (timer.Handler != null)
{
timer.Handler(timer.Args);
}
timer.curTime += timer.time;
if (timer.curTime <= 0)
{
isLoopCall = true;
}
}
}
if (isLoopCall)
{
LoopCallInBadFrame();
}
}
private void LoopCallUnscaledInBadFrame()
{
bool isLoopCall = false;
for (int i = 0, len = _unscaledTimerList.Count; i < len; i++)
{
Timer timer = _unscaledTimerList[i];
if (timer.isLoop && timer.curTime <= 0)
{
if (timer.Handler != null)
{
timer.Handler(timer.Args);
}
timer.curTime += timer.time;
if (timer.curTime <= 0)
{
isLoopCall = true;
}
}
}
if (isLoopCall)
{
LoopCallUnscaledInBadFrame();
}
}
private void UpdateTimer(float elapseSeconds)
{
bool isLoopCall = false;
for (int i = 0, len = _timerList.Count; i < len; i++)
{
Timer timer = _timerList[i];
if (timer.isNeedRemove)
{
_cacheRemoveTimers.Add(i);
continue;
}
if (!timer.isRunning) continue;
timer.curTime -= elapseSeconds;
if (timer.curTime <= 0)
{
if (timer.Handler != null)
{
timer.Handler(timer.Args);
}
if (timer.isLoop)
{
timer.curTime += timer.time;
if (timer.curTime <= 0)
{
isLoopCall = true;
}
}
else
{
_cacheRemoveTimers.Add(i);
}
}
}
for (int i = _cacheRemoveTimers.Count - 1; i >= 0; i--)
{
_timerList.RemoveAt(_cacheRemoveTimers[i]);
_cacheRemoveTimers.RemoveAt(i);
}
if (isLoopCall)
{
LoopCallInBadFrame();
}
}
private void UpdateUnscaledTimer(float realElapseSeconds)
{
bool isLoopCall = false;
for (int i = 0, len = _unscaledTimerList.Count; i < len; i++)
{
Timer timer = _unscaledTimerList[i];
if (timer.isNeedRemove)
{
_cacheRemoveUnscaledTimers.Add(i);
continue;
}
if (!timer.isRunning) continue;
timer.curTime -= realElapseSeconds;
if (timer.curTime <= 0)
{
if (timer.Handler != null)
{
timer.Handler(timer.Args);
}
if (timer.isLoop)
{
timer.curTime += timer.time;
if (timer.curTime <= 0)
{
isLoopCall = true;
}
}
else
{
_cacheRemoveUnscaledTimers.Add(i);
}
}
}
for (int i = _cacheRemoveUnscaledTimers.Count - 1; i >= 0; i--)
{
_unscaledTimerList.RemoveAt(_cacheRemoveUnscaledTimers[i]);
_cacheRemoveUnscaledTimers.RemoveAt(i);
}
if (isLoopCall)
{
LoopCallUnscaledInBadFrame();
}
}
private readonly List<System.Timers.Timer> _ticker = new List<System.Timers.Timer>();
public System.Timers.Timer AddSystemTimer(Action<object, System.Timers.ElapsedEventArgs> callBack)
{
int interval = 1000;
var timerTick = new System.Timers.Timer(interval);
timerTick.AutoReset = true;
timerTick.Enabled = true;
timerTick.Elapsed += new System.Timers.ElapsedEventHandler(callBack);
_ticker.Add(timerTick);
return timerTick;
}
private void DestroySystemTimer()
{
foreach (var ticker in _ticker)
{
if (ticker != null)
{
ticker.Stop();
}
}
}
void IModuleUpdate.Update(float elapseSeconds, float realElapseSeconds)
{
lock (Locker)
{
Dictionary<Action<object>, TimerItem>.Enumerator enumerator;
if (_items.Count > 0)
{
enumerator = _items.GetEnumerator();
while (enumerator.MoveNext())
{
TimerItem timerItem = enumerator.Current.Value;
if (timerItem.Deleted)
{
_toRemove.Add(timerItem);
continue;
}
timerItem.Elapsed += realElapseSeconds;
if (timerItem.Elapsed < timerItem.Interval)
{
continue;
}
timerItem.Elapsed -= timerItem.Interval;
if (timerItem.Elapsed < 0 || timerItem.Elapsed > 0.03f)
timerItem.Elapsed = 0;
if (timerItem.Repeat > 0)
{
timerItem.Repeat--;
if (timerItem.Repeat == 0)
{
timerItem.Deleted = true;
_toRemove.Add(timerItem);
}
}
// var repeat = i.Repeat;
if (timerItem.Callback != null)
{
if (CatchCallbackExceptions)
{
try
{
timerItem.Callback(timerItem.Param);
}
catch (Exception e)
{
timerItem.Deleted = true;
Debug.LogWarning("Timer timer(internal=" + timerItem.Interval + ", repeat=" + timerItem.Repeat + ") callback error > " + e.Message);
}
}
else
{
timerItem.Callback(timerItem.Param);
}
}
}
enumerator.Dispose();
}
int len = _toRemove.Count;
if (len > 0)
{
for (int k = 0; k < len; k++)
{
TimerItem i = _toRemove[k];
if (i.Deleted && i.Callback != null)
{
_items.Remove(i.Callback);
ReturnToPool(i);
}
}
_toRemove.Clear();
}
if (_toAdd.Count > 0)
{
enumerator = _toAdd.GetEnumerator();
while (enumerator.MoveNext())
{
_items.Add(enumerator.Current.Key, enumerator.Current.Value);
}
enumerator.Dispose();
_toAdd.Clear();
}
}
UpdateTimer(elapseSeconds);
UpdateUnscaledTimer(realElapseSeconds);
}
void IModule.Dispose()
{
lock (Locker)
{
this._toRemove.Clear();
this._toAdd.Clear();
this._items.Clear();
}
RemoveAllTimer();
DestroySystemTimer();
}
/// <summary>
/// 添加一个定时调用的任务
/// </summary>
/// <param name="interval">间隔时间(以秒为单位)</param>
/// <param name="repeat">重复次数0 表示无限重复)</param>
/// <param name="callback">要执行的回调函数</param>
/// <param name="callbackParam">回调函数的参数(可选)</param>
public void Add(float interval, int repeat, Action<object> callback, object callbackParam = null)
{
lock (Locker)
{
if (callback == null)
{
Debug.LogWarning("timer callback is null, " + interval + "," + repeat);
return;
}
if (_items.TryGetValue(callback, out var t))
{
t.Set(interval, repeat, callback, callbackParam);
t.Elapsed = 0;
t.Deleted = false;
return;
}
if (_toAdd.TryGetValue(callback, out t))
{
t.Set(interval, repeat, callback, callbackParam);
return;
}
t = GetFromPool();
t.Interval = interval;
t.Repeat = repeat;
t.Callback = callback;
t.Param = callbackParam;
_toAdd[callback] = t;
}
}
/// <summary>
/// 添加一个只执行一次的任务
/// </summary>
/// <param name="interval">间隔时间(以秒为单位)</param>
/// <param name="callback">要执行的回调函数</param>
/// <param name="callbackParam">回调函数的参数(可选)</param>
public void AddOnce(float interval, Action<object> callback, object callbackParam = null)
{
Add(interval, 1, callback, callbackParam);
}
/// <summary>
/// 添加一个每帧更新执行的任务
/// </summary>
/// <param name="callback">要执行的回调函数</param>
public void AddUpdate(Action<object> callback)
{
Add(0.001f, 0, callback);
}
/// <summary>
/// 添加一个每帧更新执行的任务
/// </summary>
/// <param name="callback">要执行的回调函数</param>
/// <param name="callbackParam">回调函数的参数</param>
public void AddUpdate(Action<object> callback, object callbackParam)
{
Add(0.001f, 0, callback, callbackParam);
}
/// <summary>
/// 检查指定的任务是否存在
/// </summary>
/// <param name="callback">要检查的回调函数</param>
/// <returns>存在返回 true不存在返回 false</returns>
public bool Exists(Action<object> callback)
{
lock (Locker)
{
if (_toAdd.ContainsKey(callback))
{
return true;
}
if (_items.TryGetValue(callback, out var at))
{
return !at.Deleted;
}
return false;
}
}
/// <summary>
/// 移除指定的任务
/// </summary>
/// <param name="callback">要移除的回调函数</param>
public void Remove(Action<object> callback)
{
lock (Locker)
{
if (_toAdd.TryGetValue(callback, out var t))
{
_toAdd.Remove(callback);
ReturnToPool(t);
}
if (_items.TryGetValue(callback, out t))
{
t.Deleted = true;
}
}
}
private TimerItem GetFromPool()
{
TimerItem t;
int cnt = _pool.Count;
if (cnt > 0)
{
t = _pool[cnt - 1];
_pool.RemoveAt(cnt - 1);
t.Deleted = false;
t.Elapsed = 0;
}
else
{
t = new TimerItem();
}
return t;
}
private void ReturnToPool(TimerItem t)
{
t.Callback = null;
_pool.Add(t);
}
public int Priority
{
get => 0;
}
/// <summary>
/// 获取所有正在运行的定时器的信息
/// </summary>
/// <returns>一个列表,其中包含每个定时器的信息</returns>
public List<TimerInfo> GetTimerInfos()
{
List<TimerInfo> timerInfos = new List<TimerInfo>();
lock (Locker)
{
foreach (var timerItem in _items.Values)
{
if (!timerItem.Deleted) // 确保定时器未被删除
{
timerInfos.Add(new TimerInfo
{
Interval = timerItem.Interval,
Repeat = timerItem.Repeat,
Elapsed = timerItem.Elapsed,
});
}
}
}
return timerInfos;
}
public int Priority { get; }
}
}
}

View File

@ -0,0 +1,19 @@
{
"name": "AlicizaX.UI.Editor",
"rootNamespace": "AlicizaX.UI.Editor",
"references": [
"GUID:acfef7cabed3b0a42b25edb1cd4fa259",
"GUID:e9c35c8938f782649bb7e670099ca425"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

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

View File

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

View File

@ -0,0 +1,63 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b212f141eb1bc7b4d97c4dc8b938bc5f, type: 3}
m_Name: UIGenerateGlobalSettings
m_EditorClassIdentifier:
scriptGenerateRule:
- uiElementRegex: Obj
componentName: GameObject
- uiElementRegex: Item
componentName: GameObject
- uiElementRegex: Tf
componentName: Transform
- uiElementRegex: Rect
componentName: RectTransform
- uiElementRegex: Btn
componentName: Button
- uiElementRegex: Img
componentName: Image
- uiElementRegex: RImg
componentName: RawImage
- uiElementRegex: Scrollbar
componentName: Scrollbar
- uiElementRegex: ScrollRect
componentName: ScrollRect
- uiElementRegex: GridLayout
componentName: GridLayoutGroup
- uiElementRegex: HLayout
componentName: HorizontalLayoutGroup
- uiElementRegex: VLayout
componentName: VerticalLayoutGroup
- uiElementRegex: Slider
componentName: Slider
- uiElementRegex: TogGroup
componentName: ToggleGroup
- uiElementRegex: AnimationCurve
componentName: AnimationCurve
- uiElementRegex: CanvasGroup
componentName: CanvasGroup
- uiElementRegex: Input
componentName: TMP_InputField
- uiElementRegex: Text
componentName: TextMeshProUGUI
- uiElementRegex: Video
componentName: VideoPlayer
- uiElementRegex: SBtn
componentName: UIButtonSuper
- uiElementRegex: STBtn
componentName: UIButtonSuperText
- uiElementRegex: 3DDisplay
componentName: UI3DDisplay
- uiElementRegex: Mask2D
componentName: RectMask2D
- uiElementRegex: LText
componentName: Text

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 49e650f120e0eb443855b745d735c2db
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c775eb6a6aca4533bc75c89ef7a219a1
timeCreated: 1737704983

View File

@ -0,0 +1,61 @@
using AlicizaX.Editor;
using AlicizaX.UI.Runtime;
using UnityEditor;
using UnityEngine;
namespace AlicizaX.UI.Editor
{
[CustomEditor(typeof(UIComponent))]
internal sealed class UIComponentInspector : ComponentTypeComponentInspector
{
private SerializedProperty uiRoot;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
if (uiRoot.objectReferenceValue == null)
{
EditorGUILayout.HelpBox("uiroot can not be null!", MessageType.Error);
}
EditorGUILayout.BeginHorizontal();
GameObject rootPrefab = (GameObject)EditorGUILayout.ObjectField("UI根预设", uiRoot.objectReferenceValue, typeof(GameObject));
if (rootPrefab != uiRoot.objectReferenceValue)
{
uiRoot.objectReferenceValue = rootPrefab;
}
if (uiRoot.objectReferenceValue == null)
{
if (GUILayout.Button("设置默认"))
{
GameObject defaultPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Packages/com.alicizax.unity.ui/Resources/UIRoot.prefab");
uiRoot.objectReferenceValue = defaultPrefab;
}
}
EditorGUILayout.EndHorizontal();
}
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void RefreshTypeNames()
{
RefreshComponentTypeNames(typeof(IUIManager));
}
protected override void Enable()
{
uiRoot = serializedObject.FindProperty("uiRoot");
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6c8dd72e28584576864a33af24255060
timeCreated: 1737704960

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2f54df36513f40bd80b00f7149741495
timeCreated: 1737704936

View File

@ -0,0 +1,956 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using AlicizaX.UI.Runtime;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace AlicizaX.UI.Editor
{
internal static class ScriptGenerator
{
private static UIGenerateGlobalSettings m_GenerateGlobalSetting;
public static string UIGenerateGlobalSettingPath = $"Assets/AlicizaFramework/UISetting/UIGenerateGlobalSettings.asset";
const string RegisterUIHelper = "Assets/GameScripts/HotFix/GameLogic/Runtime/UI";
const string RegisterUIHelperMain = "Assets/GameScripts/Main/Launcher/Scripts";
#region
//Bind文件存放根路径
const string BindComponetsSavePath = "Assets/GameScripts/HotFix/GameLogic/Runtime/UI/BindComponents";
//界面逻辑文件存放根路径
const string UILogicSavePath = "Assets/GameScripts/HotFix/GameLogic/Runtime/UI/View";
//预制体存放根路径
const string UIPrefabSavePath = "Assets/AssetRaw/UI";
public const string HotfixNameSpace = "GameLogic.UI";
#endregion
#region
//Bind文件存放根路径
const string BindComponetsMainSavePath = "Assets/GameScripts/Main/Launcher/Scripts/UI/BindComponents";
//界面逻辑文件存放根路径
const string UILogicMainSavePath = "Assets/GameScripts/Main/Launcher/Scripts/UI/View";
//预制体存放根路径
const string UIPrefabMainSavePath = "Assets/GameScripts/Main/Launcher/Resources";
public const string MainNameSpace = "GameMain.UI";
#endregion
static string WindowPrefabSavePath = Path.Combine(UIPrefabSavePath, "UIWindow");
static string WidgetPrefabSavePath = Path.Combine(UIPrefabSavePath, "UIWidget");
static string ViewPrefabSavePath = Path.Combine(UIPrefabSavePath, "UIView");
static string WindowBindSavePath = Path.Combine(BindComponetsSavePath, "Window");
static string WidgetBindSavePath = Path.Combine(BindComponetsSavePath, "Widget");
static string ViewBindSavePath = Path.Combine(BindComponetsSavePath, "View");
static string WindowLogicSavePath = Path.Combine(UILogicSavePath, "Window");
static string WidgetLogicSavePath = Path.Combine(UILogicSavePath, "Widget");
static string ViewLogicSavePath = Path.Combine(UILogicSavePath, "View");
static string ScriptsNameSpace = "GameLogic.UI";
static void SwitchHotFitRootPath(UIBindComponent bindComponent)
{
bool isHotfix = bindComponent.ResLoadType == EUIResLoadType.AssetBundle;
WindowPrefabSavePath = Path.Combine(isHotfix ? UIPrefabSavePath : UIPrefabMainSavePath, "UIWindow");
WidgetPrefabSavePath = Path.Combine(isHotfix ? UIPrefabSavePath : UIPrefabMainSavePath, "UIWidget");
ViewPrefabSavePath = Path.Combine(isHotfix ? UIPrefabSavePath : UIPrefabMainSavePath, "UIView");
WindowBindSavePath = Path.Combine(isHotfix ? BindComponetsSavePath : BindComponetsMainSavePath, "Window");
WidgetBindSavePath = Path.Combine(isHotfix ? BindComponetsSavePath : BindComponetsMainSavePath, "Widget");
ViewBindSavePath = Path.Combine(isHotfix ? BindComponetsSavePath : BindComponetsMainSavePath, "View");
WindowLogicSavePath = Path.Combine(isHotfix ? UILogicSavePath : UILogicMainSavePath, "Window");
WidgetLogicSavePath = Path.Combine(isHotfix ? UILogicSavePath : UILogicMainSavePath, "Widget");
ViewLogicSavePath = Path.Combine(isHotfix ? UILogicSavePath : UILogicMainSavePath, "View");
ScriptsNameSpace = isHotfix ? HotfixNameSpace : MainNameSpace;
}
static void GenerateUIRegisterHelper(Assembly assembly, string path)
{
// 获取程序集中的所有类型
var types = assembly.GetTypes();
List<Type> eventTypes = new List<Type>();
// 遍历每个类型
foreach (Type type in types)
{
// 检查类型是否是接口
if (type.IsInterface)
{
continue;
}
var attribute = Attribute.GetCustomAttribute(type, typeof(WindowAttribute)) as WindowAttribute;
if (attribute != null)
{
eventTypes.Add(type);
}
}
var filePath = Path.Combine(path, "UIRegisterHelper.cs");
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.WriteLine("using AlicizaFramework;");
sw.WriteLine($"namespace {ScriptsNameSpace}");
sw.WriteLine("{");
sw.WriteLine("\tpublic static class UIRegisterHelper");
sw.WriteLine("\t{");
sw.WriteLine("\t\tpublic static void Initlize()");
sw.WriteLine("\t\t{\n");
foreach (var type in eventTypes)
{
sw.WriteLine($"\t\t\tUICacheRegister.Register<{type.FullName}>();\n");
}
sw.WriteLine("\t\t}");
sw.WriteLine("\t}");
sw.WriteLine("}");
}
}
static void GenerateUIRegisterHelper()
{
// Assembly mainAssembly = Assembly.GetAssembly(typeof(DisStripCode));
// GenerateUIRegisterHelper(mainAssembly, RegisterUIHelperMain);
//
// Assembly hotfixAssembly = Assembly.GetAssembly(typeof(GameLogic.GameModule));
// GenerateUIRegisterHelper(hotfixAssembly, RegisterUIHelper);
}
public static UIGenerateGlobalSettings UIGenerateGlobalSetting
{
get
{
if (m_GenerateGlobalSetting == null)
{
m_GenerateGlobalSetting = AssetDatabase.LoadAssetAtPath<UIGenerateGlobalSettings>(UIGenerateGlobalSettingPath);
}
return m_GenerateGlobalSetting;
}
}
public static void GenerateUIPanelScript(UIBindComponent uiBindComponent)
{
SwitchHotFitRootPath(uiBindComponent);
uiBindComponent.ScriptName = uiBindComponent.gameObject.name;
if (uiBindComponent.ResLoadType == EUIResLoadType.Resources)
{
uiBindComponent.Location = "UI" + uiBindComponent.UIType + "/" + uiBindComponent.gameObject.name;
}
else
{
uiBindComponent.Location = uiBindComponent.gameObject.name;
}
if (uiBindComponent.UIType == UIType.Window)
{
SaveAllChildWidgets(uiBindComponent);
CreateUIScript(uiBindComponent);
CreateWndUIPrefab(uiBindComponent);
}
else
{
CreateUIWidgetScript(uiBindComponent);
CreateWidgetUIPrefab(uiBindComponent);
}
GenerateUIRegisterHelper();
AssetDatabase.Refresh();
}
private static void SaveAllChildWidgets(UIBindComponent uiBindComponent)
{
List<UIBindComponent> childWidgets = new List<UIBindComponent>();
CheckIsSaveWidget(uiBindComponent.transform, ref childWidgets);
string CombineName = "包含多个组件\n";
foreach (var VARIABLE in childWidgets)
{
CombineName += VARIABLE.ScriptName + "\n";
}
if (childWidgets.Count > 0)
{
bool result = EditorUtility.DisplayDialog(
"Hello!", // 标题
CombineName, // 消息内容
"一起生成保存", // 确认按钮
"不保存子组件" // 取消按钮(可选)
);
if (result)
{
foreach (var VARIABLE in childWidgets)
{
BindComponent(VARIABLE);
GenerateUIPanelScript(VARIABLE);
}
}
}
}
private static void CheckIsSaveWidget(Transform root, ref List<UIBindComponent> childWidegt)
{
for (int i = 0; i < root.childCount; ++i)
{
Transform child = root.GetChild(i);
if (child.name.IndexOf("widget", StringComparison.OrdinalIgnoreCase) >= 0)
{
UIBindComponent childWd = child.GetComponent<UIBindComponent>();
if (childWd == null)
{
Debug.Log("Widget 不包含UIBindComponent 命名不正确" + child.name);
}
if (childWd && string.IsNullOrEmpty(childWd.ScriptName))
{
Debug.Log("Widget 生成脚本名不正确 检查UIBindComponent " + child.name);
}
if (childWd && !string.IsNullOrEmpty(childWd.ScriptName))
{
childWidegt.Add(childWd);
}
continue;
}
CheckIsSaveWidget(child, ref childWidegt);
}
}
#region UIView
private static void CreateUIViewScript(UIBindComponent uiBindComponent)
{
string logicFilePath = Path.Combine(ViewLogicSavePath, uiBindComponent.ScriptName + ".cs");
string bindFilePath = Path.Combine(ViewBindSavePath, uiBindComponent.ScriptName + ".BindComponents.cs");
string LogicText = GetWidgetLogicText(uiBindComponent);
string bindText = GetWidgetBingComponentLogicText(uiBindComponent);
if (!Directory.Exists(ViewBindSavePath))
{
Directory.CreateDirectory(ViewBindSavePath);
}
if (!Directory.Exists(ViewLogicSavePath))
{
Directory.CreateDirectory(ViewLogicSavePath);
}
File.WriteAllText(bindFilePath, bindText);
File.WriteAllText(logicFilePath, LogicText);
}
public static void CreateWidgetUIPrefab(UIBindComponent uiBindComponent)
{
string prefabPath = Path.Combine(WidgetPrefabSavePath, uiBindComponent.ScriptName + ".prefab");
if (!Directory.Exists(WidgetPrefabSavePath))
{
Directory.CreateDirectory(WidgetPrefabSavePath);
}
if (File.Exists(prefabPath))
{
File.Delete(prefabPath);
}
if (uiBindComponent.gameObject)
{
RectTransform rectTransform = uiBindComponent.gameObject.GetComponent<RectTransform>();
if (rectTransform != null)
{
// 修改RectTransform的锚点
rectTransform.localScale = Vector3.one;
}
}
PrefabUtility.SaveAsPrefabAsset(uiBindComponent.gameObject, prefabPath);
Debug.Log($"{uiBindComponent.ScriptName} Generate Succesd");
}
#endregion
#region UIWidget
private static void CreateUIWidgetScript(UIBindComponent uiBindComponent)
{
string logicFilePath = Path.Combine(WidgetLogicSavePath, uiBindComponent.ScriptName + ".cs");
string bindFilePath = Path.Combine(WidgetBindSavePath, uiBindComponent.ScriptName + ".BindComponents.cs");
string LogicText = GetWidgetLogicText(uiBindComponent);
string bindText = GetWidgetBingComponentLogicText(uiBindComponent);
if (!Directory.Exists(WidgetBindSavePath))
{
Directory.CreateDirectory(WidgetBindSavePath);
}
if (!Directory.Exists(WidgetLogicSavePath))
{
Directory.CreateDirectory(WidgetLogicSavePath);
}
File.WriteAllText(bindFilePath, bindText);
File.WriteAllText(logicFilePath, LogicText);
}
public static void CreateViewUIPrefab(UIBindComponent uiBindComponent)
{
string prefabPath = Path.Combine(ViewPrefabSavePath, uiBindComponent.ScriptName + ".prefab");
if (!Directory.Exists(ViewPrefabSavePath))
{
Directory.CreateDirectory(ViewPrefabSavePath);
}
if (File.Exists(prefabPath))
{
File.Delete(prefabPath);
}
if (uiBindComponent.gameObject)
{
RectTransform rectTransform = uiBindComponent.gameObject.GetComponent<RectTransform>();
if (rectTransform != null)
{
// 修改RectTransform的锚点
rectTransform.localScale = Vector3.one;
}
}
PrefabUtility.SaveAsPrefabAsset(uiBindComponent.gameObject, prefabPath);
Debug.Log($"{uiBindComponent.ScriptName} Generate Succesd");
}
private static string GetWidgetLogicText(UIBindComponent uiBindComponent)
{
string logicFilePath = Path.Combine(WidgetLogicSavePath, uiBindComponent.ScriptName + ".cs");
string logicRef = "";
if (File.Exists(logicFilePath))
{
logicRef = File.ReadAllText(logicFilePath);
}
StringBuilder logicTextBuilder = new StringBuilder();
var hasLogic = logicRef.Length > 0;
if (!hasLogic)
{
logicTextBuilder.Append("using UnityEngine;\n");
logicTextBuilder.Append("using AlicizaFramework;\n\n");
logicTextBuilder.Append($"namespace {ScriptsNameSpace}\n");
logicTextBuilder.Append("{\n");
logicTextBuilder.Append("\tpublic partial class " + uiBindComponent.ScriptName + " \n");
logicTextBuilder.Append("\t{\n");
logicTextBuilder.Append("\n");
logicTextBuilder.Append("\t\t#region UIBind事件\n");
logicTextBuilder.Append(GetCallBackText(uiBindComponent, logicRef));
logicTextBuilder.Append("\n");
logicTextBuilder.Append("\t\t#endregion\n\n");
logicTextBuilder.Append("\n\t}\n");
logicTextBuilder.Append("}\n");
}
else
{
int index = logicRef.ToString().IndexOf("UIBind事件");
if (index != -1)
{
logicTextBuilder.Append(logicRef.Insert(index + 8,
"\n" + GetCallBackText(uiBindComponent, logicRef)));
}
else
{
Debug.LogError("请检查该脚本自动生成关键字#region UIBind事件是否被去除!");
}
}
return logicTextBuilder.ToString();
}
private static string GetWidgetBingComponentLogicText(UIBindComponent uiBindComponent)
{
StringBuilder bindComponetsBuilder = new StringBuilder();
bindComponetsBuilder.Append(GetRefrenceNameSpace(uiBindComponent));
bindComponetsBuilder.Append($"using AlicizaFramework;\n");
bindComponetsBuilder.Append($"namespace {ScriptsNameSpace}\n");
bindComponetsBuilder.Append("{\n");
bindComponetsBuilder.Append("\tpublic partial class " + uiBindComponent.ScriptName + $" : UIWidget\n");
bindComponetsBuilder.Append("\t{\n");
// 脚本工具生成的代码
bindComponetsBuilder.Append("\t\t#region 脚本工具生成的代码\n");
bindComponetsBuilder.Append(GetVarText(uiBindComponent));
bindComponetsBuilder.Append("\t\tprotected override void OnBindUIComponents()\n");
bindComponetsBuilder.Append("\t\t{\n");
bindComponetsBuilder.Append("\t\t\tInitBindComponent();\n");
bindComponetsBuilder.Append(GetBindText(uiBindComponent));
bindComponetsBuilder.Append(GetBindUIEvent(uiBindComponent));
bindComponetsBuilder.Append("\t\t}\n");
bindComponetsBuilder.Append("\t\t#endregion");
bindComponetsBuilder.Append("\n\t}\n");
bindComponetsBuilder.Append("}\n");
return bindComponetsBuilder.ToString();
}
#endregion
public static void CreateWndUIPrefab(UIBindComponent uiBindComponent)
{
string prefabPath = Path.Combine(WindowPrefabSavePath, uiBindComponent.ScriptName + ".prefab");
if (!Directory.Exists(WindowPrefabSavePath))
{
Directory.CreateDirectory(WindowPrefabSavePath);
}
if (File.Exists(prefabPath))
{
File.Delete(prefabPath);
}
if (uiBindComponent.gameObject)
{
var prefabClone = GameObject.Instantiate(uiBindComponent.gameObject, uiBindComponent.transform.parent);
prefabClone.name = uiBindComponent.ScriptName;
RemoveChildWidget(prefabClone.transform);
RectTransform rectTransform = prefabClone.gameObject.GetComponent<RectTransform>();
if (rectTransform != null)
{
// 修改RectTransform的锚点
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.offsetMin = Vector2.zero;
rectTransform.offsetMax = Vector2.zero;
rectTransform.localScale = Vector3.one;
// rectTransform.anchoredPosition = Vector2.zero;
// rectTransform.position = Vector3.zero;
}
PrefabUtility.SaveAsPrefabAsset(prefabClone.gameObject, prefabPath);
Debug.Log($"{uiBindComponent.ScriptName} Generate Succesd");
Object.DestroyImmediate(prefabClone);
}
}
private static void RemoveChildWidget(Transform root)
{
for (int i = 0; i < root.childCount; ++i)
{
Transform child = root.GetChild(i);
if (child.name.IndexOf("widget", StringComparison.OrdinalIgnoreCase) >= 0)
{
Debug.Log("包含子Widget 移除保存" + child.name);
GameObject.DestroyImmediate(child.gameObject);
continue;
}
RemoveChildWidget(child);
}
}
private static void CreateUIScript(UIBindComponent uiBindComponent)
{
string logicFilePath = Path.Combine(WindowLogicSavePath, uiBindComponent.ScriptName + ".cs");
string bindFilePath = Path.Combine(WindowBindSavePath, uiBindComponent.ScriptName + ".BindComponents.cs");
string LogicText = GetUILogicText(uiBindComponent);
string bindText = GetUIBingComponentLogicText(uiBindComponent);
string attributeResText = $"[UIRes(location: \"{uiBindComponent.Location}\" , EUIResLoadType.{uiBindComponent.ResLoadType})]\n";
string attributeText = $"\t[Window(UILayer.{uiBindComponent.UILayer}, fullScreen:{uiBindComponent.FullScreen.ToString().ToLower()} , delayedClose:{uiBindComponent.CacheDuration.ToString()})]\n";
bindText = bindText.Replace("#AttributeMark", attributeResText + attributeText);
if (!Directory.Exists(WindowBindSavePath))
{
Directory.CreateDirectory(WindowBindSavePath);
}
if (!Directory.Exists(WindowLogicSavePath))
{
Directory.CreateDirectory(WindowLogicSavePath);
}
File.WriteAllText(bindFilePath, bindText);
File.WriteAllText(logicFilePath, LogicText);
}
private static string GetUILogicText(UIBindComponent uiBindComponent,
bool isHotfixProject = true)
{
string logicFilePath = Path.Combine(WindowLogicSavePath, uiBindComponent.ScriptName + ".cs");
string logicRef = "";
if (File.Exists(logicFilePath))
{
logicRef = File.ReadAllText(logicFilePath);
}
StringBuilder logicTextBuilder = new StringBuilder();
var hasLogic = logicRef.Length > 0;
if (!hasLogic)
{
logicTextBuilder.Append("using UnityEngine;\n");
logicTextBuilder.Append("using AlicizaFramework;\n\n");
logicTextBuilder.Append($"namespace {ScriptsNameSpace}\n");
logicTextBuilder.Append("{\n");
logicTextBuilder.Append("\tpartial class " + uiBindComponent.ScriptName + " \n");
logicTextBuilder.Append("\t{\n");
logicTextBuilder.Append("\n");
logicTextBuilder.Append("\t\t#region UIBind事件\n");
logicTextBuilder.Append(GetCallBackText(uiBindComponent, logicRef));
logicTextBuilder.Append("\n");
logicTextBuilder.Append("\t\t#endregion\n\n");
logicTextBuilder.Append(GetLogicLifeText(uiBindComponent));
logicTextBuilder.Append("\n\t}\n");
logicTextBuilder.Append("}\n");
}
else
{
int index = logicRef.ToString().IndexOf("UIBind事件");
if (index != -1)
{
logicTextBuilder.Append(logicRef.Insert(index + 8,
"\n" + GetCallBackText(uiBindComponent, logicRef)));
}
else
{
logicTextBuilder.Append(logicRef.ToString());
Debug.LogWarning("该脚本自动生成关键字#region UIBind事件被去除 不进行追加UI事件");
}
}
return logicTextBuilder.ToString();
}
/// <summary>
/// 构建部分类 xxxUI.BindComponetns
/// </summary>
/// <param name="uiBindComponent"></param>
/// <param name="isHotfixProject"></param>
/// <returns></returns>
private static string GetUIBingComponentLogicText(UIBindComponent uiBindComponent, bool isHotfixProject = true)
{
StringBuilder bindComponetsBuilder = new StringBuilder();
bindComponetsBuilder.Append(GetRefrenceNameSpace(uiBindComponent));
bindComponetsBuilder.Append($"using AlicizaFramework;\n");
bindComponetsBuilder.Append($"namespace {ScriptsNameSpace}\n");
bindComponetsBuilder.Append("{\n");
bindComponetsBuilder.Append("\t#AttributeMark");
bindComponetsBuilder.Append("\tpartial class " + uiBindComponent.ScriptName + " : UIWindow\n");
bindComponetsBuilder.Append("\t{\n");
// 脚本工具生成的代码
bindComponetsBuilder.Append("\t\t#region 脚本工具生成的代码\n");
bindComponetsBuilder.Append(GetVarText(uiBindComponent));
bindComponetsBuilder.Append("\t\tprotected override void OnBindUIComponents()\n");
bindComponetsBuilder.Append("\t\t{\n");
bindComponetsBuilder.Append("\t\t\tInitBindComponent();\n");
bindComponetsBuilder.Append(GetBindText(uiBindComponent));
bindComponetsBuilder.Append(GetBindUIEvent(uiBindComponent));
bindComponetsBuilder.Append("\t\t}\n");
bindComponetsBuilder.Append("\t\t#endregion");
bindComponetsBuilder.Append("\n\t}\n");
bindComponetsBuilder.Append("}\n");
return bindComponetsBuilder.ToString();
}
/// <summary>
/// 获取所有组件的对应命名空间引用
/// </summary>
/// <param name="uiBindComponent"></param>
/// <returns></returns>
private static string GetRefrenceNameSpace(UIBindComponent uiBindComponent)
{
StringBuilder refrenceNameSpaceBuilder = new StringBuilder();
List<string> nameSpaces = new List<string>();
for (int i = 0; i < uiBindComponent.bindComponents.Count; i++)
{
var nameSpace = uiBindComponent.Elements[i].BindCom.GetType().Namespace;
if (!nameSpaces.Contains(nameSpace))
{
nameSpaces.Add(nameSpace);
refrenceNameSpaceBuilder.Append($"using {nameSpace};\n");
}
}
return refrenceNameSpaceBuilder.ToString();
}
/// <summary>
/// 获取所有绑定组件的引用
/// </summary>
/// <param name="uiBindComponent"></param>
/// <returns></returns>
private static string GetBindText(UIBindComponent uiBindComponent)
{
StringBuilder bindTextBuilder = new StringBuilder();
for (int i = 0; i < uiBindComponent.bindComponents.Count; i++)
{
var varName = uiBindComponent.Elements[i].Name;
var varType = uiBindComponent.Elements[i].BindCom.GetType().Name;
switch (varType)
{
case "GameObject":
bindTextBuilder.Append(
$"\t\t\t{varName} = FChild<{varType}>({i}).gameObject;\n");
break;
case "RichItemIcon":
bindTextBuilder.Append(
$"\t\t\t{varName} = CreateWidgetByType<{varType}>(FChild(\"{varName}\"));\n");
break;
case "RedNoteWidget":
break;
case "TextButtonItem":
case "SwitchTabItem":
case "UIActorWidget":
case "UIEffectWidget":
case "UISpineWidget":
case "UIMainPlayerWidget":
bindTextBuilder.Append(
$"\t\t\t{varName} = CreateWidget<{varType}>(FChild(\"{varName}\").gameObject);\n");
break;
default:
bindTextBuilder.Append(
$"\t\t\t{varName} = FChild<{varType}>({i});\n");
break;
}
}
return bindTextBuilder.ToString();
}
/// <summary>
/// 获取所有组件的引用
/// </summary>
/// <param name="uiBindComponent"></param>
/// <returns></returns>
private static string GetVarText(UIBindComponent uiBindComponent)
{
StringBuilder varTextBuilder = new StringBuilder();
for (int i = 0; i < uiBindComponent.bindComponents.Count; i++)
{
var varName = uiBindComponent.Elements[i].Name;
varTextBuilder.Append("\t\tprivate " + uiBindComponent.Elements[i].BindCom.GetType().Name + " " + varName + ";\n");
}
return varTextBuilder.ToString();
}
/// <summary>
/// 获取所有组件的绑定事件
/// </summary>
/// <param name="uiBindComponent"></param>
/// <returns></returns>
private static string GetBindUIEvent(UIBindComponent uiBindComponent)
{
StringBuilder bingUIEventBuilder = new StringBuilder();
for (int i = 0; i < uiBindComponent.bindComponents.Count; i++)
{
var varName = uiBindComponent.Elements[i].SplitName;
var comName = uiBindComponent.Elements[i].Name;
var varType = uiBindComponent.Elements[i].BindCom.GetType().Name;
if (varType == "Button" || varType == "UIButtonSuper" || varType == "UIButtonSuperText")
{
string varFuncName = GetBtnFuncName(varName);
bingUIEventBuilder.Append($"\t\t\t{comName}.onClick.AddListener({varFuncName});\n");
}
else if (varType == "Toggle")
{
string varFuncName = GetToggleFuncName(varName);
bingUIEventBuilder.Append($"\t\t\t{comName}.onValueChanged.AddListener({varFuncName});\n");
}
else if (varType == "Slider")
{
string varFuncName = GetSliderFuncName(varName);
bingUIEventBuilder.Append($"\t\t\t{comName}.onValueChanged.AddListener({varFuncName});\n");
}
}
return bingUIEventBuilder.ToString();
}
/// <summary>
/// 获取所有组件的绑定回调
/// </summary>
/// <param name="uiBindComponent"></param>
/// <param name="logicRef"></param>
/// <returns></returns>
private static string GetCallBackText(UIBindComponent uiBindComponent, string logicRef)
{
StringBuilder callBackText = new StringBuilder();
for (int i = 0; i < uiBindComponent.bindComponents.Count; i++)
{
var varName = uiBindComponent.Elements[i].SplitName;
var varType = uiBindComponent.Elements[i].BindCom.GetType().Name;
if (varType == "Button" || varType == "UIButtonSuper" || varType == "UIButtonSuperText")
{
string varFuncName = GetBtnFuncName(varName);
if (!logicRef.Contains(varFuncName))
{
callBackText.Append($"\t\tprivate void {varFuncName}()\n");
callBackText.Append("\t\t{\n\t\t}\n");
}
}
else if (varType == "Toggle")
{
string varFuncName = GetToggleFuncName(varName);
if (!logicRef.Contains(varFuncName))
{
callBackText.Append($"\t\tprivate void {varFuncName}(bool isOn)\n");
callBackText.Append("\t\t{\n\t\t}\n");
}
}
else if (varType == "Slider")
{
string varFuncName = GetSliderFuncName(varName);
if (!logicRef.Contains(varFuncName))
{
callBackText.Append($"\t\tprivate void {varFuncName}(float valFue)\n");
callBackText.Append("\t\t{\n\t\t}\n");
}
}
}
return callBackText.ToString();
}
/// <summary>
/// 构建脚本生命周期
/// </summary>
/// <param name="uiBindComponent"></param>
/// <returns></returns>
private static string GetLogicLifeText(UIBindComponent uiBindComponent)
{
StringBuilder lifeTextBuilder = new StringBuilder();
//觉得还是没有必要加 需要哪个自己override吧
// lifeTextBuilder.Append("\t\t#region 生命周期事件\n");
// lifeTextBuilder.Append($"\t\tprotected override void OnInitlize()\n");
// lifeTextBuilder.Append("\t\t{\n");
// lifeTextBuilder.Append("\t\t\tbase.OnInitlize();\n");
// lifeTextBuilder.Append("\t\t}\n");
// lifeTextBuilder.Append($"\t\tprotected override void OnOpen()\n");
// lifeTextBuilder.Append("\t\t{\n");
// lifeTextBuilder.Append("\t\t\tbase.OnOpen();\n");
// lifeTextBuilder.Append("\t\t}\n");
// lifeTextBuilder.Append($"\t\tprotected override void OnUpdate()\n");
// lifeTextBuilder.Append("\t\t{\n");
// lifeTextBuilder.Append("\t\t\tbase.OnUpdate();\n");
// lifeTextBuilder.Append("\t\t}\n");
// lifeTextBuilder.Append($"\t\tprotected override void OnClose()\n");
// lifeTextBuilder.Append("\t\t{\n");
// lifeTextBuilder.Append("\t\t\tbase.OnClose();\n");
// lifeTextBuilder.Append("\t\t}\n");
// lifeTextBuilder.Append($"\t\tprotected override void OnDispose()\n");
// lifeTextBuilder.Append("\t\t{\n");
// lifeTextBuilder.Append("\t\t\tbase.OnDispose();\n");
// lifeTextBuilder.Append("\t\t}\n");
// lifeTextBuilder.Append("\t\t#endregion\n\n");
return lifeTextBuilder.ToString();
}
/// <summary>
/// 绑定组件
/// </summary>
/// <param name="bindComponent"></param>
public static void BindComponent(UIBindComponent bindComponent)
{
List<UIBindComponent.UIBindData> bindDatas = new List<UIBindComponent.UIBindData>();
CollectComponet(bindComponent.transform, ref bindDatas);
bindComponent.bindComponents.Clear();
foreach (var bindData in bindDatas)
{
bindComponent.bindComponents.Add(bindData.BindCom);
}
bindComponent.Elements = bindDatas;
}
/// <summary>
/// 收集组件
/// </summary>
/// <param name="root"></param>
/// <param name="bingDatas"></param>
private static void CollectComponet(Transform root, ref List<UIBindComponent.UIBindData> bingDatas)
{
for (int i = 0; i < root.childCount; ++i)
{
Transform child = root.GetChild(i);
if (child.name.IndexOf("widget", StringComparison.OrdinalIgnoreCase) >= 0)
{
Debug.Log("包含子Widget 如非Widget组件 请避开命名 路径" + child.name);
continue;
}
string[] comArray = SplitComName(child.name);
if (comArray != null)
{
string splitName = child.name.Substring(child.name.IndexOf("@") + 1);
foreach (var com in comArray)
{
var typeName = GetVerType(com);
var component = child.GetComponent(typeName);
var keyName = GetKeyName(com, child.name);
if (bingDatas.Find(a => a.Name == keyName) != null)
{
Debug.LogError("有重复的key:" + keyName);
continue;
}
if (component == null)
{
Debug.LogError($"{child.name}没有{typeName}组件");
continue;
}
bingDatas.Add(new UIBindComponent.UIBindData(keyName, component, splitName));
}
}
CollectComponet(child, ref bingDatas);
}
}
private static string[] SplitComName(string name)
{
bool hasCom = name.Contains("@");
if (!hasCom) return null;
string comStr = name.Substring(0, name.IndexOf("@"));
string[] comArray = comStr.Split("#");
return comArray;
}
private static string GetKeyName(string comName, string Key)
{
return $"m{comName}{Key.Substring(Key.IndexOf("@") + 1)}";
}
/// <summary>
/// 情况所有组件
/// </summary>
/// <param name="bindComponent"></param>
public static void ClearBindComponets(UIBindComponent bindComponent)
{
bindComponent.bindComponents.Clear();
bindComponent.Elements.Clear();
}
/// <summary>
/// 清楚空引用
/// </summary>
/// <param name="bindComponent"></param>
public static void ClearNullRefrence(UIBindComponent bindComponent)
{
for (var index = bindComponent.Elements.Count - 1; index >= 0; index--)
{
if (bindComponent.Elements[index].BindCom == null)
{
bindComponent.Elements.RemoveAt(index);
}
}
bindComponent.bindComponents.Clear();
foreach (var VARIABLE in bindComponent.Elements)
{
bindComponent.bindComponents.Add(VARIABLE.BindCom);
}
}
private static string GetBtnFuncName(string varName)
{
return $"OnBtn{varName}Click";
}
private static string GetToggleFuncName(string varName)
{
return "OnToggle" + varName + "Change";
}
private static string GetSliderFuncName(string varName)
{
return "OnSlider" + varName + "Change";
}
private static string GetVerType(string uiName)
{
foreach (var pair in UIGenerateGlobalSetting.scriptGenerateRule)
{
if (uiName.StartsWith(pair.uiElementRegex))
{
return pair.componentName;
}
}
return string.Empty;
}
private static string GetUIBindDataPrefix(string uiName)
{
foreach (var pair in UIGenerateGlobalSetting.scriptGenerateRule)
{
if (uiName.StartsWith(pair.uiElementRegex))
{
return pair.uiElementRegex;
}
}
return string.Empty;
}
}
}
#endif

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d7bb0ec8a5855b14cbeac868ca983c37

View File

@ -0,0 +1,26 @@
using AlicizaX.Editor;
using Sirenix.OdinInspector;
using UnityEditor;
namespace AlicizaX.UI.Editor
{
[System.Serializable]
[DisplayName("UI设置")]
internal sealed class UIGenerateGlobalSettingTab : GameFrameworkTabBase
{
[Required] [InlineEditor(InlineEditorObjectFieldModes.CompletelyHidden)] [DisableInPlayMode] [HideLabel]
public UIGenerateGlobalSettings UIGenerateGlobalSettings;
public UIGenerateGlobalSettingTab()
{
UIGenerateGlobalSettings = ScriptableSingletonUtil.Get<UIGenerateGlobalSettings>();
}
protected override void Save()
{
base.Save();
EditorUtility.SetDirty(UIGenerateGlobalSettings);
AssetDatabase.SaveAssets();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c093bf237b3e4243a52e04a5db36f86d
timeCreated: 1737705566

View File

@ -0,0 +1,30 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
namespace AlicizaX.UI.Editor
{
internal class UIGenerateGlobalSettings : ScriptableObject
{
[SerializeField] public List<ScriptGenerateRuler> scriptGenerateRule = new List<ScriptGenerateRuler>();
}
[Serializable]
internal class ScriptGenerateRuler
{
public string uiElementRegex;
public string componentName;
public ScriptGenerateRuler(string uiElementRegex, string componentName)
{
this.uiElementRegex = uiElementRegex;
this.componentName = componentName;
}
}
}
#endif

View File

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

View File

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

View File

@ -0,0 +1,312 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &500891838716286123
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5373281001294974998}
- component: {fileID: 743195302492612381}
- component: {fileID: 7227605137039161963}
m_Layer: 0
m_Name: UICamera
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5373281001294974998
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 500891838716286123}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 86062277508691697}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!20 &743195302492612381
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 500891838716286123}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 3
m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 10
far clip plane: 1000
field of view: 60
orthographic: 1
orthographic size: 5
m_Depth: 2
m_CullingMask:
serializedVersion: 2
m_Bits: 32
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 0
m_AllowMSAA: 0
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!114 &7227605137039161963
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 500891838716286123}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_RenderShadows: 0
m_RequiresDepthTextureOption: 0
m_RequiresOpaqueTextureOption: 0
m_CameraType: 0
m_Cameras: []
m_RendererIndex: -1
m_VolumeLayerMask:
serializedVersion: 2
m_Bits: 0
m_VolumeTrigger: {fileID: 0}
m_VolumeFrameworkUpdateModeOption: 2
m_RenderPostProcessing: 0
m_Antialiasing: 0
m_AntialiasingQuality: 2
m_StopNaN: 0
m_Dithering: 0
m_ClearDepth: 1
m_AllowXRRendering: 1
m_AllowHDROutput: 1
m_UseScreenCoordOverride: 0
m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
m_RequiresDepthTexture: 0
m_RequiresColorTexture: 0
m_Version: 2
m_TaaSettings:
m_Quality: 3
m_FrameInfluence: 0.1
m_JitterScale: 1
m_MipBias: 0
m_VarianceClampScale: 0.9
m_ContrastAdaptiveSharpening: 0
--- !u!1 &1735351593002053547
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3110666966229274110}
- component: {fileID: 4697108639102116370}
- component: {fileID: 3475475550181341661}
- component: {fileID: 6941144161958937340}
m_Layer: 5
m_Name: UICanvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3110666966229274110
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1735351593002053547}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 86062277508691697}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!223 &4697108639102116370
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1735351593002053547}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 1
m_Camera: {fileID: 743195302492612381}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 0
m_AdditionalShaderChannelsFlag: 27
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!114 &3475475550181341661
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1735351593002053547}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 1
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 1920, y: 1080}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 0
--- !u!114 &6941144161958937340
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1735351593002053547}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 55
--- !u!1 &4612363183729467837
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 86062277508691697}
- component: {fileID: 2601148299080526511}
- component: {fileID: 4177649269856392400}
m_Layer: 0
m_Name: UIRoot
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &86062277508691697
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4612363183729467837}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 1000, y: 1000, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3110666966229274110}
- {fileID: 5373281001294974998}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2601148299080526511
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4612363183729467837}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!114 &4177649269856392400
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4612363183729467837}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SendPointerHoverToParent: 1
m_MoveRepeatDelay: 0.5
m_MoveRepeatRate: 0.1
m_XRTrackingOrigin: {fileID: 0}
m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_DeselectOnBackgroundClick: 1
m_PointerBehavior: 0
m_CursorLockBehavior: 0
m_ScrollDeltaPerTick: 6

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9368ff38b2090b2468f8358242026e4b
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,20 @@
{
"name": "AlicizaX.UI.Runtime",
"rootNamespace": "AlicizaX.UI.Runtime",
"references": [
"GUID:75b6f2078d190f14dbda4a5b747d709c",
"GUID:56115dc8e38144842823f4ee0dcad88b",
"GUID:be2f20a77f3232f44b9711ef43234aac",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:6e66e5d3ebcffd845a40833b6f1d6426"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

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

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6b2b18ae4d9d49d6b032cababaf21c16
timeCreated: 1737704913

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,11 @@
using System.Collections.Generic;
using AnimationFlowCore;
using UnityEngine;
namespace AnimationFlowEditor {
public class AnimationFlowSerialize {
public string flag;
[SerializeReference]
public List<ActionNode> nodes = new();
}
}

View File

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

View File

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

View File

@ -0,0 +1,367 @@
using System;
using System.Collections.Generic;
using AnimationFlowCore;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;
namespace AnimationFlowEditor
{
public class GraphView : UnityEditor.Experimental.GraphView.GraphView
{
private readonly SearchWindowProvider searchWindowProvider;
private readonly GraphWindow graphWindow;
private readonly Dictionary<string, NodeView> dicNodeView = new();
private AnimationFlow animationFlow;
private const string applicationFlag = "@AnimationFlow";
private readonly Dictionary<string, ActionNode> pendingNodes = new();
public GraphView(GraphWindow graphWindow) : base()
{
this.graphWindow = graphWindow;
InitView();
SetupZoom(ContentZoomer.DefaultMinScale, ContentZoomer.DefaultMaxScale);
this.AddManipulator(new SelectionDragger());
this.AddManipulator(new RectangleSelector());
this.AddManipulator(new ContentDragger());
searchWindowProvider = ScriptableObject.CreateInstance<SearchWindowProvider>();
searchWindowProvider.Initialize(graphWindow, this);
SetCopyAndPaste();
graphViewChanged += OnGraphViewChanged;
}
private void InitView()
{
this.StretchToParentSize();
Insert(0, new GridBackground());
AddStyles();
MiniMap miniMap = new();
Add(miniMap);
miniMap.style.backgroundColor = new Color(0.12f, 0.12f, 0.12f, 1f);
miniMap.style.borderBottomColor = new Color(0.2f, 0.2f, 0.2f, 1f);
miniMap.style.borderRightColor = new Color(0.2f, 0.2f, 0.2f, 1f);
miniMap.style.borderTopColor = new Color(0.2f, 0.2f, 0.2f, 1f);
miniMap.style.borderLeftColor = new Color(0.2f, 0.2f, 0.2f, 1f);
}
private void SetCopyAndPaste()
{
serializeGraphElements += (IEnumerable<GraphElement> elements) =>
{
AnimationFlowSerialize serialize = new();
serialize.flag = applicationFlag;
foreach (var ele in elements)
{
if (ele is NodeView nodeView)
{
serialize.nodes.Add(nodeView.actionNode);
}
}
return JsonUtility.ToJson(serialize);
};
canPasteSerializedData += (string data) => { return data.Contains(applicationFlag); };
unserializeAndPaste += (string operationName, string data) =>
{
ClearSelection();
Undo.RecordObject(animationFlow, operationName);
Vector2 mousePos = contentViewContainer.WorldToLocal(contentRect.center);
try
{
AnimationFlowSerialize serialize = JsonUtility.FromJson<AnimationFlowSerialize>(data);
List<ActionNode> newDatas = new();
Dictionary<string, ActionNode> dicUid = new();
foreach (ActionNode node in serialize.nodes)
{
node.nodePos = node.nodePos + mousePos;
string uuid = node.uuid;
node.uuid = Guid.NewGuid().ToString();
NodeView nodeView = AddNodeView(node);
AddToSelection(nodeView);
newDatas.Add(node);
dicUid.Add(uuid, node);
}
foreach (ActionNode copyNode in newDatas)
{
for (int i = copyNode.Childs.Count - 1; i >= 0; i--)
{
if (dicUid.TryGetValue(copyNode.Childs[i].uuid, out ActionNode newNode))
{
copyNode.Childs[i] = newNode;
if (dicNodeView.TryGetValue(copyNode.uuid, out NodeView inNode) && dicNodeView.TryGetValue(newNode.uuid, out NodeView outNode))
{
AddElement(inNode.portOut.ConnectTo(outNode.portIn));
}
}
else
{
copyNode.Childs.RemoveAt(i);
}
}
}
}
catch (Exception)
{
}
};
}
private void ResetEdge()
{
List<ActionNode> nodes = new List<ActionNode>();
foreach (var item in animationFlow.AnimationNodes)
{
nodes.Add(item);
}
List<ActionNode> allNodes = new List<ActionNode>();
LoadAllChildNode(nodes, allNodes);
foreach (ActionNode data in allNodes)
{
foreach (ActionNode node in allNodes)
{
if (data.Childs.Count > 0 && data.Childs.Find(a => a.uuid == node.uuid) != null)
{
if (dicNodeView.TryGetValue(data.uuid, out NodeView inNode) && dicNodeView.TryGetValue(node.uuid, out NodeView outNode))
{
AddElement(inNode.portOut.ConnectTo(outNode.portIn));
}
}
}
}
}
private NodeView ResetNodeView(ActionNode data)
{
NodeView nodeView = new(data, graphWindow);
AddElement(nodeView);
nodeView.SetPosition(new Rect(data.nodePos, Vector2.zero));
dicNodeView.Add(data.uuid, nodeView);
return nodeView;
}
private void RemoveNodeView(NodeView nodeView)
{
dicNodeView.Remove(nodeView.actionNode.uuid);
pendingNodes.Remove(nodeView.actionNode.uuid);
if (nodeView.actionNode is EntryNode)
{
animationFlow.AnimationNodes.Remove(nodeView.actionNode as EntryNode);
}
}
private void AddStyles()
{
StyleSheet styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>(EditorResourceTool.editorAssets + "/AnimationFlowStyles.uss");
styleSheets.Add(styleSheet);
}
private GraphViewChange OnGraphViewChanged(GraphViewChange change)
{
change.edgesToCreate?.ForEach(edge =>
{
if (animationFlow == null)
{
ClearGraph();
return;
}
Undo.RecordObject(animationFlow, "Create Edge");
NodeView nodeIn = edge.input.node as NodeView;
NodeView nodeOut = edge.output.node as NodeView;
nodeOut.actionNode.Childs.Add(nodeIn.actionNode);
EditorUtility.SetDirty(animationFlow);
});
change.elementsToRemove?.ForEach(elem =>
{
if (animationFlow == null)
{
ClearGraph();
return;
}
if (elem is Edge edge)
{
Undo.RecordObject(animationFlow, "Rmove Edge");
NodeView nodeIn = edge.input.node as NodeView;
NodeView nodeOut = edge.output.node as NodeView;
nodeOut.actionNode.Childs.Remove(nodeIn.actionNode);
}
if (elem is NodeView node)
{
Undo.RecordObject(animationFlow, "Remove Node");
RemoveNodeView(node);
graphWindow.OnNodeRemove();
}
EditorUtility.SetDirty(animationFlow);
});
change.movedElements?.ForEach(elem =>
{
if (animationFlow == null)
{
ClearGraph();
return;
}
if (elem is NodeView nodeView)
{
Undo.RecordObject(animationFlow, "Move Node");
nodeView.actionNode.nodePos = nodeView.GetPosition().position;
}
EditorUtility.SetDirty(animationFlow);
});
return change;
}
public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
{
SearchWindow.Open(new SearchWindowContext(GUIUtility.GUIToScreenPoint(evt.mousePosition)), searchWindowProvider);
}
public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter)
{
List<Port> compatiblePorts = new();
ports.ForEach(port =>
{
if (startPort == port)
{
return;
}
if (startPort.node == port.node)
{
return;
}
if (startPort.direction == port.direction)
{
return;
}
if (startPort.portType != port.portType)
{
return;
}
compatiblePorts.Add(port);
});
return compatiblePorts;
}
protected override bool canDeleteSelection => base.canDeleteSelection && !Application.isPlaying && animationFlow != null && !animationFlow.InPlaying;
protected override bool canCopySelection => base.canCopySelection && !Application.isPlaying && animationFlow != null && !animationFlow.InPlaying;
protected override bool canCutSelection => base.canCutSelection && !Application.isPlaying && animationFlow != null && !animationFlow.InPlaying;
protected override bool canDuplicateSelection => base.canDuplicateSelection && !Application.isPlaying && animationFlow != null && !animationFlow.InPlaying;
protected override bool canPaste => base.canPaste && !Application.isPlaying && animationFlow != null;
public NodeView AddNodeView(ActionNode node)
{
if (animationFlow == null)
{
return null;
}
Undo.RecordObject(animationFlow, "Create Node");
if (node is EntryNode)
{
animationFlow.AnimationNodes.Add(node as EntryNode);
}
else
{
pendingNodes.Add(node.uuid, node);
}
return ResetNodeView(node);
}
public void ClearGraph()
{
graphElements.ForEach(g => RemoveElement(g));
dicNodeView.Clear();
animationFlow = null;
}
public void SetAnimationFlow(AnimationFlow animationFlow)
{
this.animationFlow = animationFlow;
List<ActionNode> nodes = new List<ActionNode>();
foreach (var VARIABLE in animationFlow.AnimationNodes)
{
nodes.Add(VARIABLE);
}
List<ActionNode> allNodes = new List<ActionNode>();
LoadAllChildNode(nodes, allNodes);
foreach (ActionNode data in allNodes)
{
ResetNodeView(data);
}
ResetEdge();
}
private void LoadAllChildNode(List<ActionNode> nodes, List<ActionNode> collector)
{
foreach (var item in nodes)
{
collector.Add(item);
if (item.Childs.Count > 0) LoadAllChildNode(item.Childs, collector);
}
}
public void ResetView()
{
foreach (NodeView nodeView in dicNodeView.Values)
{
nodeView.RemoveProgress();
nodeView.RemoveComplete();
}
}
public void OnNodeEnter(ActionNode actionNode)
{
if (dicNodeView.TryGetValue(actionNode.uuid, out NodeView nodeView))
{
nodeView.AddProgress();
}
}
public void OnNodeExit(ActionNode actionNode)
{
if (dicNodeView.TryGetValue(actionNode.uuid, out NodeView nodeView))
{
nodeView.RemoveProgress();
nodeView.AddComplete();
}
}
public void OnNodeUpdate(ActionNode actionNode)
{
if (dicNodeView.TryGetValue(actionNode.uuid, out NodeView nodeView))
{
nodeView.UpdateProgress();
}
}
}
}

View File

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

View File

@ -0,0 +1,123 @@
using System;
using System.Linq;
using AnimationFlowCore;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;
using static UnityEditor.Experimental.GraphView.Port;
namespace AnimationFlowEditor {
public class NodeView : Node {
public readonly ActionNode actionNode;
public Port portIn;
public Port portOut;
private readonly GraphWindow graphWindow;
private ProgressBar progressPlaying;
private Image imageComplete;
private Image imageWarning;
private Label sub_title;
public NodeView(ActionNode node, GraphWindow graphWindow) {
this.actionNode = node;
this.graphWindow = graphWindow;
Draw();
}
private void Draw() {
Type type = actionNode.GetType();
NameAttribute nameAttribute = type.GetCustomAttributes(typeof(NameAttribute), true).FirstOrDefault() as NameAttribute;
title = nameAttribute != null && !string.IsNullOrEmpty(nameAttribute.name) ? nameAttribute.name : type.Name;
if (actionNode.HasInputPort()) {
portIn = InstantiatePort(Orientation.Horizontal, Direction.Input, actionNode.MultiInputPort() ? Capacity.Multi : Capacity.Single, typeof(bool));
inputContainer.Add(portIn);
portIn.portName = "in";
}
if (actionNode.HasOutPort()) {
portOut = InstantiatePort(Orientation.Horizontal, Direction.Output, actionNode.MultiOutPort() ? Capacity.Multi : Capacity.Single, typeof(bool));
outputContainer.Add(portOut);
portOut.portName = "out";
}
titleContainer.Remove(titleButtonContainer);
imageComplete = new() {
image = AssetDatabase.LoadAssetAtPath<Texture2D>(EditorResourceTool.editorAssets + "/Complete.png"),
tintColor = new Color(0.4f, 0.7f, 0.2f),
style = { marginLeft = 3, marginRight = 10, visibility = Visibility.Hidden }
};
titleContainer.Add(imageComplete);
imageWarning = new() {
image = AssetDatabase.LoadAssetAtPath<Texture2D>(EditorResourceTool.editorAssets + "/Warning.png"),
tintColor = Color.red,
style = { position = Position.Absolute, right = 0, top = 5 }
};
titleContainer.Add(imageWarning);
RefreshState();
if (actionNode.HasSubTitle()) {
sub_title = new(actionNode.SubTitle()) {
style = { fontSize = 12, paddingLeft = 8, paddingBottom = 5, backgroundColor = new Color(0.23f, 0.23f, 0.23f, 1f) }
};
this.Q<VisualElement>("node-border").Insert(1, sub_title);
}
this.Q<VisualElement>("title").style.height = 25;
}
public void RefreshState() {
imageWarning.style.visibility = actionNode.Valid() ? Visibility.Hidden : Visibility.Visible;
if (sub_title != null) {
if (string.IsNullOrEmpty(actionNode.SubTitle())) {
sub_title.text = "<Empty>";
sub_title.style.color = Color.red;
} else {
sub_title.text = actionNode.SubTitle();
sub_title.style.color = new Color(0.82f, 0.82f, 0.82f, 1f);
}
}
}
public void AddComplete() {
imageComplete.style.visibility = Visibility.Visible;
}
public void RemoveComplete() {
imageComplete.style.visibility = Visibility.Hidden;
}
public void AddProgress() {
if (actionNode.Duration() == 0) {
return;
}
progressPlaying = new();
progressPlaying.style.height = 10;
contentContainer.Add(progressPlaying);
progressPlaying.highValue = actionNode.Duration();
progressPlaying.value = 0;
RefreshExpandedState();
}
public void UpdateProgress() {
if (actionNode.Duration() == 0) {
return;
}
if (progressPlaying == null) {
AddProgress();
}
progressPlaying.value = actionNode.elapsedTime;
}
public void RemoveProgress() {
if (progressPlaying == null) {
return;
}
contentContainer.Remove(progressPlaying);
progressPlaying = null;
RefreshExpandedState();
}
public override void OnSelected() {
base.OnSelected();
graphWindow.OnSelect(this);
}
}
}

View File

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

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AnimationFlowCore;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;
namespace AnimationFlowEditor {
public class SearchWindowProvider : ScriptableObject, ISearchWindowProvider {
private GraphWindow graphWindow;
private GraphView graphView;
private Texture2D icon;
public void Initialize(GraphWindow graphWindow, GraphView graphView) {
this.graphWindow = graphWindow;
this.graphView = graphView;
icon = new Texture2D(1, 1);
icon.SetPixel(0, 0, Color.clear);
icon.Apply();
}
List<SearchTreeEntry> ISearchWindowProvider.CreateSearchTree(SearchWindowContext context) {
List<SearchTreeEntry> entries = new() {
new SearchTreeGroupEntry(new GUIContent("Create Node",icon))
};
Dictionary<string, List<Type>> dicType = new();
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) {
foreach (var type in assembly.GetTypes()) {
if (type.IsClass && !type.IsAbstract && type.IsSubclassOf(typeof(ActionNode))) {
CategoryAttribute categoryAttribute = type.GetCustomAttributes(typeof(CategoryAttribute), true).FirstOrDefault() as CategoryAttribute;
if (categoryAttribute == null || string.IsNullOrEmpty(categoryAttribute.category)) {
NameAttribute nameAttribute = type.GetCustomAttributes(typeof(NameAttribute), true).FirstOrDefault() as NameAttribute;
entries.Add(new SearchTreeEntry(new GUIContent(nameAttribute != null && !string.IsNullOrEmpty(nameAttribute.name) ? nameAttribute.name : type.Name, icon)) { level = 1, userData = type });
} else {
if (dicType.TryGetValue(categoryAttribute.category, out var list)) {
list.Add(type);
} else {
dicType.Add(categoryAttribute.category, new List<Type>() { type });
}
}
}
}
}
foreach (var kv in dicType) {
entries.Add(new SearchTreeGroupEntry(new GUIContent(kv.Key), 1));
foreach (Type type in kv.Value) {
NameAttribute nameAttribute = type.GetCustomAttributes(typeof(NameAttribute), true).FirstOrDefault() as NameAttribute;
entries.Add(new SearchTreeEntry(new GUIContent(nameAttribute != null && !string.IsNullOrEmpty(nameAttribute.name) ? nameAttribute.name : type.Name, icon)) { level = 2, userData = type });
}
}
return entries;
}
bool ISearchWindowProvider.OnSelectEntry(SearchTreeEntry searchTreeEntry, SearchWindowContext context) {
var type = searchTreeEntry.userData as Type;
var data = Activator.CreateInstance(type) as ActionNode;
data.uuid = Guid.NewGuid().ToString();
data.nodePos = graphView.contentViewContainer.WorldToLocal(context.screenMousePosition - graphWindow.position.position);
graphView.AddNodeView(data);
return true;
}
}
}

View File

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

View File

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

View File

@ -0,0 +1,45 @@
using System;
using System.Linq;
using AnimationFlowCore;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace AnimationFlowEditor
{
public class GraphInspector : VisualElement
{
private PropertyTree propertyTree;
public void DrawNode(NodeView nodeView)
{
Clear();
if (nodeView.actionNode == null)
{
return;
}
// 使用 Odin PropertyTree 来处理非 UnityEngine.Object 对象
propertyTree = PropertyTree.Create(nodeView.actionNode);
var imguiContainer = new IMGUIContainer(() =>
{
if (propertyTree == null)
{
return;
}
propertyTree.Draw(false);
// 手动调用 Odin 的 Apply处理数据更新后的逻辑
if (propertyTree.ApplyChanges())
{
nodeView.RefreshState();
}
});
Add(imguiContainer);
propertyTree.Dispose();
}
}
}

View File

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

View File

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

View File

@ -0,0 +1,44 @@
using System.Collections.Generic;
using UnityEngine;
namespace AnimationFlowEditor {
public static class EditorResourceTool {
public static string editorAssets;
public static bool LocateEditorAssets() {
string projectPath = Application.dataPath;
if (projectPath.EndsWith("/Assets")) {
projectPath = projectPath.Remove(projectPath.Length - ("Assets".Length));
}
editorAssets = "Packages/com.yuliuren.alicizaframework/ThirdParty/AnimationFlow/Editor/Styles";
if (!System.IO.File.Exists(projectPath + editorAssets + "/AnimationFlowStyles.uss")) {
var sdir = new System.IO.DirectoryInfo(Application.dataPath);
var dirQueue = new Queue<System.IO.DirectoryInfo>();
dirQueue.Enqueue(sdir);
bool found = false;
while (dirQueue.Count > 0) {
System.IO.DirectoryInfo dir = dirQueue.Dequeue();
if (System.IO.File.Exists(dir.FullName + "/AnimationFlowStyles.uss")) {
string path = dir.FullName.Replace('\\', '/');
found = true;
path = path.Replace(projectPath, "");
if (path.StartsWith("/")) {
path = path.Remove(0, 1);
}
editorAssets = path;
return true;
}
var dirs = dir.GetDirectories();
for (int i = 0; i < dirs.Length; i++) {
dirQueue.Enqueue(dirs[i]);
}
}
if (!found) {
Debug.LogWarning("Could not locate editor assets folder. Make sure you have imported the package correctly.");
return false;
}
}
return true;
}
}
}

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