From 98f1d8272136c236c73cae890019ffa4f77520e6 Mon Sep 17 00:00:00 2001 From: MichaelO Date: Thu, 14 Mar 2024 04:27:23 +0800 Subject: [PATCH] updated to v2.10.1 --- Assets/OxGFrame/CHANGELOG.md | 41 ++++ .../Editor/BindCodeAutoGenerateEditor.cs | 91 +++++++-- .../Scripts/Editor/BindCodeSetting.cs | 71 ++++++- .../CoreFrame/Scripts/Editor/Dictionary.meta | 8 + .../Dictionary/AttrGenericDictionary.cs | 192 ++++++++++++++++++ .../Dictionary/AttrGenericDictionary.cs.meta | 11 + .../{ => Dictionary}/GenericDictionary.cs | 0 .../GenericDictionary.cs.meta | 0 .../Dictionary/VariableGenericDictionary.cs | 192 ++++++++++++++++++ .../VariableGenericDictionary.cs.meta | 11 + .../Scripts/Runtime/Core/Common/Binder.cs | 45 +++- .../Runtime/Core/Common/FrameConfig.cs | 1 + .../Runtime/Core/AudioFrame/AudioBase.cs | 3 +- .../Runtime/Core/AudioFrame/AudioManager.cs | 4 + .../Scripts/Runtime/Core/Cache.meta | 8 + .../Runtime/Core/Cache/MediaLRUCache.cs | 112 ++++++++++ .../Runtime/Core/Cache/MediaLRUCache.cs.meta | 11 + .../Runtime/Core/Implement/MediaBase.cs | 1 + .../Runtime/Core/Implement/MediaManager.cs | 21 +- .../Runtime/Core/VideoFrame/VideoBase.cs | 3 +- .../Runtime/Core/VideoFrame/VideoManager.cs | 5 + .../Resources/Example/Prefabs/Demo2CP.prefab | 4 +- .../Samples~/CPFrameDemo/Scripts/Demo1CP.cs | 25 ++- .../Samples~/CPFrameDemo/Scripts/Demo2CP.cs | 23 ++- .../Example/ScenePrefabs/CubeSceneSR.prefab | 10 +- .../SRFrameDemo/Scripts/CubeSceneSR.cs | 19 +- .../Samples~/SRFrameDemo/Scripts/MeshResSR.cs | 7 +- .../Example/UI/ScreenUI/Demo1UI.prefab | 8 +- .../Example/UI/ScreenUI/Demo2UI.prefab | 4 +- .../Example/UI/ScreenUI/Demo3UI.prefab | 2 +- .../Example/UI/WorldUI/Demo1UI.prefab | 8 +- .../Example/UI/WorldUI/Demo2UI.prefab | 4 +- .../Example/UI/WorldUI/Demo3UI.prefab | 2 +- .../Samples~/UIFrameDemo/Scripts/Demo1UI.cs | 33 ++- .../Samples~/UIFrameDemo/Scripts/Demo2UI.cs | 28 ++- .../Samples~/UIFrameDemo/Scripts/Demo3UI.cs | 19 +- .../Samples~/UIFrameDemo/Scripts/Demo4UI.cs | 3 + Assets/OxGFrame/package.json | 2 +- .../Settings/OxGFrame/BindCodeSetting.asset | 20 +- Docs/img_18.png | Bin 69904 -> 129104 bytes Docs/img_19.png | Bin 0 -> 110765 bytes README.md | 6 + 42 files changed, 965 insertions(+), 93 deletions(-) create mode 100644 Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary.meta create mode 100644 Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/AttrGenericDictionary.cs create mode 100644 Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/AttrGenericDictionary.cs.meta rename Assets/OxGFrame/CoreFrame/Scripts/Editor/{ => Dictionary}/GenericDictionary.cs (100%) rename Assets/OxGFrame/CoreFrame/Scripts/Editor/{ => Dictionary}/GenericDictionary.cs.meta (100%) create mode 100644 Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/VariableGenericDictionary.cs create mode 100644 Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/VariableGenericDictionary.cs.meta create mode 100644 Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache.meta create mode 100644 Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache/MediaLRUCache.cs create mode 100644 Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache/MediaLRUCache.cs.meta create mode 100644 Docs/img_19.png diff --git a/Assets/OxGFrame/CHANGELOG.md b/Assets/OxGFrame/CHANGELOG.md index f859b862..1cc41171 100644 --- a/Assets/OxGFrame/CHANGELOG.md +++ b/Assets/OxGFrame/CHANGELOG.md @@ -1,5 +1,46 @@ # CHANGELOG +## [2.10.1] - 2024-03-14 +- Fixed AudioBase and VideoBase to avoid executing Stop again in OnDestroy if they are being destroyed. +- Added MediaLRUCache to handle audios or videos that have not been Unloaded for a long time (Optimize memory). +- Added binding access modifier rules in BindCodeSetting, split by "$". + - _Node@MyObj*Txt$public (UIBase, SRBase). + - ~Node@MyObj*Txt$public (CPBase). +``` +// Default is protected, no set required (depends on the first element in BindCodeSetting) +UIBase, SRBase: +_Node@MyObj*Txt +CPBase: +~Node@MyObj*Txt + +// Assign access modifier +UIBase, SRBase: +_Node@MyObj*Txt$public +_Node@MyObj*Txt$private +CPBase: +~Node@MyObj*Txt$public +~Node@MyObj*Txt$private +``` +- Added binding attr rules in BindCodeSetting, pattern is "\[\]" (supported multi-attrs \[\]\[\]...). + - _Node@MyObj*Txt$public\[hi\] (UIBase, SRBase). + - ~Node@MyObj*Txt$public\[hi\] (CPBase). +``` +[hi] = [HideInInspector] +UIBase, SRBase: +_Node@MyObj*Txt$public[hi] +CPBase: +~Node@MyObj*Txt$public[hi] + +[sf] = [SerializeField] +UIBase, SRBase: +_Node@MyObj*Txt[sf] +CPBase: +~Node@MyObj*Txt[sf] +``` +- Modified UIFrameDemo. +- Modified SRFrameDemo. +- Modified CPFrameDemo. + ## [2.10.0] - 2024-03-07 - Added BuiltinQueryMode option on PatchLauncher, can switch built-in query mode. ```C# diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Editor/BindCodeAutoGenerateEditor.cs b/Assets/OxGFrame/CoreFrame/Scripts/Editor/BindCodeAutoGenerateEditor.cs index 1c98e56b..06adadee 100644 --- a/Assets/OxGFrame/CoreFrame/Scripts/Editor/BindCodeAutoGenerateEditor.cs +++ b/Assets/OxGFrame/CoreFrame/Scripts/Editor/BindCodeAutoGenerateEditor.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; using UnityEditor; using UnityEngine; @@ -8,14 +10,18 @@ public static class BindCodeAutoGenerateEditor { private class BindInfo { + public string[] attrNames; + public string variableAccessModifier; public string bindName; public string variableName; public string componentName; public BindCodeSetting.Pluralize pluralize; public int count; - public BindInfo(string bindName, string variableName, string componentName, int count) + public BindInfo(string[] attrNames, string variableAccessModifier, string bindName, string variableName, string componentName, int count) { + this.attrNames = attrNames; + this.variableAccessModifier = variableAccessModifier; this.bindName = bindName; this.variableName = variableName; this.componentName = componentName; @@ -129,25 +135,68 @@ private static void _CollectBindInfo(string name) string[] heads = Binder.GetHeadSplitNameBySeparator(name); string bindType = heads[0]; // 綁定類型(會去查找 dictComponentFinder 裡面有沒有符合的類型) - string bindName = heads[1]; // 要成為取得綁定物件後的Key + string bindInfo = heads[1]; // 要成為取得綁定物件後的 Key // 再去判斷取得後的字串陣列是否綁定格式資格 - if (heads == null || heads.Length < 2 || !FrameConfig.BIND_COMPONENTS.ContainsKey(bindType)) + if (heads == null || + heads.Length < 2 || + !FrameConfig.BIND_COMPONENTS.ContainsKey(bindType)) { return; } + #region Common with Binder + // 變數存取權檢測 + string[] bindArgs = Binder.GetAccessModifierSplitNameBySeparator(bindInfo); + + // MyObj*Txt$public => ["MyObj*Txt", "public"] + string bindName = bindArgs[0]; + string variableAccessModifier = (bindArgs.Length > 1) ? bindArgs[1] : null; + + // 匹配 Attr [] + string pattern = @"\[(.*?)\]"; + string[] attrNames = new string[] { }; + if (!string.IsNullOrEmpty(variableAccessModifier)) + { + MatchCollection attrMatches = Regex.Matches(variableAccessModifier, pattern); + if (attrMatches.Count > 0) + { + // 將匹配的子字符串存入陣列 + attrNames = attrMatches.Cast().Select(m => m.Value).ToArray(); + // 將所有方括號替換為空字串 + variableAccessModifier = Regex.Replace(variableAccessModifier, pattern, ""); + } + } + else + { + MatchCollection attrMatches = Regex.Matches(bindName, pattern); + if (attrMatches.Count > 0) + { + // 將匹配的子字符串存入陣列 + attrNames = attrMatches.Cast().Select(m => m.Value).ToArray(); + // 將所有方括號替換為空字串 + bindName = Regex.Replace(bindName, pattern, ""); + } + } + #endregion + // 組件結尾檢測 string[] tails = Binder.GetTailSplitNameBySeparator(bindName); - string variableName = bindName.Replace(" ", string.Empty); - string componentName = _DEF_COMPONENT_NAME; + string variableName, componentName; - if (tails != null && tails.Length >= 2) + if (tails != null && + tails.Length >= 2) + // Component { variableName = tails[0] + tails[1]; - variableName.Replace(" ", string.Empty); componentName = tails[1]; } + // GameObject + else + { + variableName = bindName; + componentName = _DEF_COMPONENT_NAME; + } // 修正 Case switch (_settings.variableCaseType) @@ -165,7 +214,7 @@ private static void _CollectBindInfo(string name) { _collectBindInfos[bindName].count++; } - else _collectBindInfos.Add(bindName, new BindInfo(bindName, variableName, componentName, 1)); + else _collectBindInfos.Add(bindName, new BindInfo(attrNames, variableAccessModifier, bindName, variableName, componentName, 1)); } #endregion @@ -200,28 +249,34 @@ private static void _GenerateCodes() // For GameObjects if (bindInfo.Value.componentName == _DEF_COMPONENT_NAME) { - _builder += space + $"{_settings.variableAccessModifier} "; + for (int i = 0; i < bindInfo.Value.attrNames.Length; i++) + _builder += space + $"{_settings.GetAttrReference(bindInfo.Value.attrNames[i])}\n"; + _builder += space + $"{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[0]} "; _builder += $"{bindInfo.Value.componentName}[] "; - _builder += $"{_settings.variablePrefix}{bindInfo.Value.variableName}s;\n"; + _builder += $"{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[1]}{bindInfo.Value.variableName}s;\n"; } else { - _builder += space + $"{_settings.variableAccessModifier} "; + for (int i = 0; i < bindInfo.Value.attrNames.Length; i++) + _builder += space + $"{_settings.GetAttrReference(bindInfo.Value.attrNames[i])}\n"; + _builder += space + $"{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[0]} "; _builder += $"{bindInfo.Value.componentName}[] "; int varNameLength = bindInfo.Value.variableName.Length; int endRemoveCount = (bindInfo.Value.pluralize.endRemoveCount > varNameLength) ? 0 : bindInfo.Value.pluralize.endRemoveCount; string varName = bindInfo.Value.variableName.Substring(0, varNameLength - endRemoveCount); string endPluralTxt = bindInfo.Value.pluralize.endPluralTxt; string newVarName = $"{varName}{endPluralTxt}"; - _builder += $"{_settings.variablePrefix}{newVarName};\n"; + _builder += $"{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[1]}{newVarName};\n"; } } // Single else { - _builder += space + $"{_settings.variableAccessModifier} "; + for (int i = 0; i < bindInfo.Value.attrNames.Length; i++) + _builder += space + $"{_settings.GetAttrReference(bindInfo.Value.attrNames[i])}\n"; + _builder += space + $"{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[0]} "; _builder += $"{bindInfo.Value.componentName} "; - _builder += $"{_settings.variablePrefix}{bindInfo.Value.variableName};\n"; + _builder += $"{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[1]}{bindInfo.Value.variableName};\n"; } } #endregion @@ -244,7 +299,7 @@ private static void _GenerateCodes() // For GameObjects if (bindInfo.Value.componentName == _DEF_COMPONENT_NAME) { - _builder += space + $" {_settings.GetIndicateModifier()}{_settings.variablePrefix}{bindInfo.Value.variableName}s = "; + _builder += space + $" {_settings.GetIndicateModifier()}{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[1]}{bindInfo.Value.variableName}s = "; _builder += $"{_settings.GetIndicateModifier()}collector.GetNodes(\"{bindInfo.Value.bindName}\");\n"; } else @@ -255,7 +310,7 @@ private static void _GenerateCodes() string varName = bindInfo.Value.variableName.Substring(0, varNameLength - endRemoveCount); string endPluralTxt = bindInfo.Value.pluralize.endPluralTxt; string newVarName = $"{varName}{endPluralTxt}"; - _builder += space + $"{_settings.GetIndicateModifier()}{_settings.variablePrefix}{newVarName} = "; + _builder += space + $"{_settings.GetIndicateModifier()}{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[1]}{newVarName} = "; _builder += $"{_settings.GetIndicateModifier()}collector.GetNodeComponents<{bindInfo.Value.componentName}>(\"{bindInfo.Value.bindName}\");\n"; } } @@ -265,12 +320,12 @@ private static void _GenerateCodes() // For GameObject if (bindInfo.Value.componentName == _DEF_COMPONENT_NAME) { - _builder += space + $" {_settings.GetIndicateModifier()}{_settings.variablePrefix}{bindInfo.Value.variableName} = "; + _builder += space + $" {_settings.GetIndicateModifier()}{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[1]}{bindInfo.Value.variableName} = "; _builder += $"{_settings.GetIndicateModifier()}collector.GetNode(\"{bindInfo.Value.bindName}\");\n"; } else { - _builder += space + $" {_settings.GetIndicateModifier()}{_settings.variablePrefix}{bindInfo.Value.variableName} = "; + _builder += space + $" {_settings.GetIndicateModifier()}{_settings.GetVariableAccessPairs(bindInfo.Value.variableAccessModifier)[1]}{bindInfo.Value.variableName} = "; _builder += $"{_settings.GetIndicateModifier()}collector.GetNodeComponent<{bindInfo.Value.componentName}>(\"{bindInfo.Value.bindName}\");\n"; } } diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Editor/BindCodeSetting.cs b/Assets/OxGFrame/CoreFrame/Scripts/Editor/BindCodeSetting.cs index 46d3eea8..a988ed63 100644 --- a/Assets/OxGFrame/CoreFrame/Scripts/Editor/BindCodeSetting.cs +++ b/Assets/OxGFrame/CoreFrame/Scripts/Editor/BindCodeSetting.cs @@ -1,7 +1,8 @@ -using System; -using UnityEngine; -using MyBox; +using MyBox; +using System; +using System.Linq; using UnityEditor; +using UnityEngine; namespace OxGFrame.CoreFrame.Editor { @@ -52,15 +53,27 @@ public enum IndicateModifier This } - [Separator("Variable Setting")] - public CaseType variableCaseType = CaseType.CamelCase; - public string variableAccessModifier = "protected"; - public string variablePrefix = "_"; - - [Separator("Method Setting")] + [Separator("Binding Method Setting")] [Tooltip("*[Auto] Automatically save binding content to script.\n\n*[Manual] Manually copy the binding content from the clipboard to the script.")] public MethodType methodType = MethodType.Auto; + [Separator("Attribute Setting")] + public AttrGenericDictionary attrReferenceRules = new AttrGenericDictionary() + { + { "[hi]", "[HideInInspector]" }, + { "[sf]", "[SerializeField]"} + }; + + [Separator("Variable Setting")] + public CaseType variableCaseType = CaseType.CamelCase; + [Tooltip("The first element will be default")] + public VariableGenericDictionary variableAccessRules = new VariableGenericDictionary() + { + { "protected", "_" }, + { "private", "_" }, + { "public" , "" } + }; + [Separator("Indicate Modifier Setting")] public IndicateModifier indicateModifier = IndicateModifier.This; @@ -104,6 +117,46 @@ public string GetIndicateModifier() } } + public string GetAttrReference(string key) + { + if (string.IsNullOrEmpty(key)) + return string.Empty; + + this.attrReferenceRules.TryGetValue(key, out var result); + if (result == null) + return string.Empty; + + return result; + } + + public string[] GetVariableAccessPairs(string key) + { + if (string.IsNullOrEmpty(key)) + { + return new string[] + { + this.variableAccessRules.Keys.First(), + this.variableAccessRules.Values.First() + }; + } + + this.variableAccessRules.TryGetValue(key, out var result); + if (result == null) + { + return new string[] + { + this.variableAccessRules.Keys.First(), + this.variableAccessRules.Values.First() + }; + } + + return new string[] + { + key, + result + }; + } + public string GetMethodAccessModifier() { return "protected"; diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary.meta b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary.meta new file mode 100644 index 00000000..9f3fb76d --- /dev/null +++ b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f9d23a6495b22947b8fddf3971a7361 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/AttrGenericDictionary.cs b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/AttrGenericDictionary.cs new file mode 100644 index 00000000..cf101c32 --- /dev/null +++ b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/AttrGenericDictionary.cs @@ -0,0 +1,192 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System; +using System.Linq; + +namespace OxGFrame.CoreFrame.Editor +{ + /// + /// Generic Serializable Dictionary for Unity 2020.1 and above. + /// Simply declare your key/value types and you're good to go - zero boilerplate. + /// + [Serializable] + public class AttrGenericDictionary : IDictionary, ISerializationCallbackReceiver + { + // Internal + [SerializeField] + private List list = new List(); + [SerializeField, HideInInspector] + private Dictionary indexByKey = new Dictionary(); + [SerializeField, HideInInspector] + private Dictionary dict = new Dictionary(); + +#pragma warning disable 0414 + [SerializeField, HideInInspector] + private bool keyCollision; +#pragma warning restore 0414 + + [Serializable] + private struct KeyValuePair + { + public TKey AttrName; + public TValue AttrReference; + public KeyValuePair(TKey Key, TValue Value) + { + this.AttrName = Key; + this.AttrReference = Value; + } + } + + // Lists are serialized natively by Unity, no custom implementation needed. + public void OnBeforeSerialize() { } + + // Populate dictionary with pairs from list and flag key-collisions. + public void OnAfterDeserialize() + { + dict.Clear(); + indexByKey.Clear(); + keyCollision = false; + for (int i = 0; i < list.Count; i++) + { + var key = list[i].AttrName; + if (key != null && !ContainsKey(key)) + { + dict.Add(key, list[i].AttrReference); + indexByKey.Add(key, i); + } + else + { + keyCollision = true; + } + } + } + + // IDictionary + public TValue this[TKey key] + { + get => dict[key]; + set + { + dict[key] = value; + if (indexByKey.ContainsKey(key)) + { + var index = indexByKey[key]; + list[index] = new KeyValuePair(key, value); + } + else + { + list.Add(new KeyValuePair(key, value)); + indexByKey.Add(key, list.Count - 1); + } + } + } + + public ICollection Keys => dict.Keys; + public ICollection Values => dict.Values; + + public void Sort() + { + this.list = this.list.OrderBy(o => o.AttrName).ToList(); + } + + public void Add(TKey key, TValue value) + { + dict.Add(key, value); + list.Add(new KeyValuePair(key, value)); + indexByKey.Add(key, list.Count - 1); + } + + public bool ContainsKey(TKey key) => dict.ContainsKey(key); + + public bool Remove(TKey key) + { + if (dict.Remove(key)) + { + var index = indexByKey[key]; + list.RemoveAt(index); + UpdateIndexLookup(index); + indexByKey.Remove(key); + return true; + } + else + { + return false; + } + } + + private void UpdateIndexLookup(int removedIndex) + { + for (int i = removedIndex; i < list.Count; i++) + { + var key = list[i].AttrName; + indexByKey[key]--; + } + } + + public bool TryGetValue(TKey key, out TValue value) => dict.TryGetValue(key, out value); + + // ICollection + public int Count => dict.Count; + public bool IsReadOnly { get; set; } + + public void Add(KeyValuePair pair) + { + Add(pair.Key, pair.Value); + } + + public void Clear() + { + dict.Clear(); + list.Clear(); + indexByKey.Clear(); + } + + public bool Contains(KeyValuePair pair) + { + TValue value; + if (dict.TryGetValue(pair.Key, out value)) + { + return EqualityComparer.Default.Equals(value, pair.Value); + } + else + { + return false; + } + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (array == null) + throw new ArgumentException("The array cannot be null."); + if (arrayIndex < 0) + throw new ArgumentOutOfRangeException("The starting array index cannot be negative."); + if (array.Length - arrayIndex < dict.Count) + throw new ArgumentException("The destination array has fewer elements than the collection."); + + foreach (var pair in dict) + { + array[arrayIndex] = pair; + arrayIndex++; + } + } + + public bool Remove(KeyValuePair pair) + { + TValue value; + if (dict.TryGetValue(pair.Key, out value)) + { + bool valueMatch = EqualityComparer.Default.Equals(value, pair.Value); + if (valueMatch) + { + return Remove(pair.Key); + } + } + return false; + } + + // IEnumerable + public IEnumerator> GetEnumerator() => dict.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => dict.GetEnumerator(); + } +} \ No newline at end of file diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/AttrGenericDictionary.cs.meta b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/AttrGenericDictionary.cs.meta new file mode 100644 index 00000000..74abc889 --- /dev/null +++ b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/AttrGenericDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eea7014dbd082fc4da32804aaac8930b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Editor/GenericDictionary.cs b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/GenericDictionary.cs similarity index 100% rename from Assets/OxGFrame/CoreFrame/Scripts/Editor/GenericDictionary.cs rename to Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/GenericDictionary.cs diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Editor/GenericDictionary.cs.meta b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/GenericDictionary.cs.meta similarity index 100% rename from Assets/OxGFrame/CoreFrame/Scripts/Editor/GenericDictionary.cs.meta rename to Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/GenericDictionary.cs.meta diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/VariableGenericDictionary.cs b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/VariableGenericDictionary.cs new file mode 100644 index 00000000..a6658ac8 --- /dev/null +++ b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/VariableGenericDictionary.cs @@ -0,0 +1,192 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System; +using System.Linq; + +namespace OxGFrame.CoreFrame.Editor +{ + /// + /// Generic Serializable Dictionary for Unity 2020.1 and above. + /// Simply declare your key/value types and you're good to go - zero boilerplate. + /// + [Serializable] + public class VariableGenericDictionary : IDictionary, ISerializationCallbackReceiver + { + // Internal + [SerializeField] + private List list = new List(); + [SerializeField, HideInInspector] + private Dictionary indexByKey = new Dictionary(); + [SerializeField, HideInInspector] + private Dictionary dict = new Dictionary(); + +#pragma warning disable 0414 + [SerializeField, HideInInspector] + private bool keyCollision; +#pragma warning restore 0414 + + [Serializable] + private struct KeyValuePair + { + public TKey VariableAccessModifier; + public TValue VariablePrefix; + public KeyValuePair(TKey Key, TValue Value) + { + this.VariableAccessModifier = Key; + this.VariablePrefix = Value; + } + } + + // Lists are serialized natively by Unity, no custom implementation needed. + public void OnBeforeSerialize() { } + + // Populate dictionary with pairs from list and flag key-collisions. + public void OnAfterDeserialize() + { + dict.Clear(); + indexByKey.Clear(); + keyCollision = false; + for (int i = 0; i < list.Count; i++) + { + var key = list[i].VariableAccessModifier; + if (key != null && !ContainsKey(key)) + { + dict.Add(key, list[i].VariablePrefix); + indexByKey.Add(key, i); + } + else + { + keyCollision = true; + } + } + } + + // IDictionary + public TValue this[TKey key] + { + get => dict[key]; + set + { + dict[key] = value; + if (indexByKey.ContainsKey(key)) + { + var index = indexByKey[key]; + list[index] = new KeyValuePair(key, value); + } + else + { + list.Add(new KeyValuePair(key, value)); + indexByKey.Add(key, list.Count - 1); + } + } + } + + public ICollection Keys => dict.Keys; + public ICollection Values => dict.Values; + + public void Sort() + { + this.list = this.list.OrderBy(o => o.VariableAccessModifier).ToList(); + } + + public void Add(TKey key, TValue value) + { + dict.Add(key, value); + list.Add(new KeyValuePair(key, value)); + indexByKey.Add(key, list.Count - 1); + } + + public bool ContainsKey(TKey key) => dict.ContainsKey(key); + + public bool Remove(TKey key) + { + if (dict.Remove(key)) + { + var index = indexByKey[key]; + list.RemoveAt(index); + UpdateIndexLookup(index); + indexByKey.Remove(key); + return true; + } + else + { + return false; + } + } + + private void UpdateIndexLookup(int removedIndex) + { + for (int i = removedIndex; i < list.Count; i++) + { + var key = list[i].VariableAccessModifier; + indexByKey[key]--; + } + } + + public bool TryGetValue(TKey key, out TValue value) => dict.TryGetValue(key, out value); + + // ICollection + public int Count => dict.Count; + public bool IsReadOnly { get; set; } + + public void Add(KeyValuePair pair) + { + Add(pair.Key, pair.Value); + } + + public void Clear() + { + dict.Clear(); + list.Clear(); + indexByKey.Clear(); + } + + public bool Contains(KeyValuePair pair) + { + TValue value; + if (dict.TryGetValue(pair.Key, out value)) + { + return EqualityComparer.Default.Equals(value, pair.Value); + } + else + { + return false; + } + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (array == null) + throw new ArgumentException("The array cannot be null."); + if (arrayIndex < 0) + throw new ArgumentOutOfRangeException("The starting array index cannot be negative."); + if (array.Length - arrayIndex < dict.Count) + throw new ArgumentException("The destination array has fewer elements than the collection."); + + foreach (var pair in dict) + { + array[arrayIndex] = pair; + arrayIndex++; + } + } + + public bool Remove(KeyValuePair pair) + { + TValue value; + if (dict.TryGetValue(pair.Key, out value)) + { + bool valueMatch = EqualityComparer.Default.Equals(value, pair.Value); + if (valueMatch) + { + return Remove(pair.Key); + } + } + return false; + } + + // IEnumerable + public IEnumerator> GetEnumerator() => dict.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => dict.GetEnumerator(); + } +} \ No newline at end of file diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/VariableGenericDictionary.cs.meta b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/VariableGenericDictionary.cs.meta new file mode 100644 index 00000000..a338b33c --- /dev/null +++ b/Assets/OxGFrame/CoreFrame/Scripts/Editor/Dictionary/VariableGenericDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b5466c6bc3dabbc41be36b814c633f78 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Runtime/Core/Common/Binder.cs b/Assets/OxGFrame/CoreFrame/Scripts/Runtime/Core/Common/Binder.cs index b6a0222c..7fe58b00 100644 --- a/Assets/OxGFrame/CoreFrame/Scripts/Runtime/Core/Common/Binder.cs +++ b/Assets/OxGFrame/CoreFrame/Scripts/Runtime/Core/Common/Binder.cs @@ -1,5 +1,6 @@ using OxGFrame.CoreFrame.CPFrame; using OxGKit.LoggingSystem; +using System.Text.RegularExpressions; using UnityEngine; namespace OxGFrame.CoreFrame @@ -54,10 +55,29 @@ private static void _BindIntoCollector(string name, GameObject go, FrameBase fBa string[] heads = GetHeadSplitNameBySeparator(name); string bindType = heads[0]; // 綁定類型(會去查找 dictComponentFinder 裡面有沒有符合的類型) - string bindName = heads[1]; // 要成為取得綁定物件後的Key + string bindInfo = heads[1]; // 要成為取得綁定物件後的Key + + #region Common + // 變數存取權檢測 + string[] bindArgs = GetAccessModifierSplitNameBySeparator(bindInfo); + + // MyObj*Txt$public => ["MyObj*Txt", "public"] + string bindName = bindArgs[0]; + + // 匹配 Attr [] + string pattern = @"\[(.*?)\]"; + MatchCollection attrMatches = Regex.Matches(bindName, pattern); + if (attrMatches.Count > 0) + { + // 將所有方括號替換為空字串 + bindName = Regex.Replace(bindName, pattern, ""); + } + #endregion // 再去判斷取得後的字串陣列是否綁定格式資格 - if (heads == null || heads.Length < 2 || !FrameConfig.BIND_COMPONENTS.ContainsKey(bindType)) + if (heads == null || + heads.Length < 2 || + !FrameConfig.BIND_COMPONENTS.ContainsKey(bindType)) { Logging.Print($"{name} => Naming format error. Please check the bind name."); return; @@ -113,8 +133,8 @@ public static bool CheckNodeHasPrefix(string name) } /// - /// 透過【BIND_HEAD_SEPARATOR】去 Split 字串, 返回取得字串陣列 - /// ※備註: (Example) _Node@MyObj => ["_Node", "MyObj"] + /// 透過【BIND_HEAD_SEPARATOR】執行 Split 字串, 返回取得字串陣列 + /// ※備註: (Example) _Node@MyObj*Txt => ["_Node", "MyObj*Txt"] /// /// /// @@ -126,8 +146,8 @@ public static string[] GetHeadSplitNameBySeparator(string name) } /// - /// 透過【BIND_TAIL_SEPARATOR】去 Split 字串, 返回取得字串陣列 - /// ※備註: (Example) _Node@MyObj*Txt => ["MyObj", "Txt"] + /// 透過【BIND_TAIL_SEPARATOR】執行 Split 字串, 返回取得字串陣列 + /// ※備註: (Example) MyObj*Txt => ["MyObj", "Txt"] /// /// /// @@ -137,6 +157,19 @@ public static string[] GetTailSplitNameBySeparator(string name) return name.Split(FrameConfig.BIND_TAIL_SEPARATOR); } + + /// + /// 透過【BIND_ACCESS_MODIFIER_SEPARATOR】執行 Split 字串, 返回取得字串陣列 + /// ※備註: (Example) MyObj*Txt$public => ["MyObj*Txt", "public"] + /// + /// + /// + public static string[] GetAccessModifierSplitNameBySeparator(string name) + { + if (string.IsNullOrEmpty(name)) return null; + + return name.Split(FrameConfig.BIND_ACCESS_MODIFIER_SEPARATOR); + } #endregion } } \ No newline at end of file diff --git a/Assets/OxGFrame/CoreFrame/Scripts/Runtime/Core/Common/FrameConfig.cs b/Assets/OxGFrame/CoreFrame/Scripts/Runtime/Core/Common/FrameConfig.cs index fa3317ec..24524e68 100644 --- a/Assets/OxGFrame/CoreFrame/Scripts/Runtime/Core/Common/FrameConfig.cs +++ b/Assets/OxGFrame/CoreFrame/Scripts/Runtime/Core/Common/FrameConfig.cs @@ -7,6 +7,7 @@ public class FrameConfig /* 規範符號 */ public static readonly string BIND_HEAD_SEPARATOR = "@"; public static readonly string BIND_TAIL_SEPARATOR = "*"; + public static readonly string BIND_ACCESS_MODIFIER_SEPARATOR = "$"; public static readonly string BIND_STOP_END = "#"; /* 綁定規範前墜 */ diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/AudioFrame/AudioBase.cs b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/AudioFrame/AudioBase.cs index 6f8e2be2..e0761aa8 100644 --- a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/AudioFrame/AudioBase.cs +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/AudioFrame/AudioBase.cs @@ -247,7 +247,8 @@ private void OnDestroy() try { - AudioManager.GetInstance().Stop(this, true, true); + if (!this.isDestroying) + AudioManager.GetInstance().Stop(this, true, true); } catch { diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/AudioFrame/AudioManager.cs b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/AudioFrame/AudioManager.cs index c0642f41..ff6ddb64 100644 --- a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/AudioFrame/AudioManager.cs +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/AudioFrame/AudioManager.cs @@ -206,6 +206,10 @@ private void _Play(AudioBase audBase, int loops, float volume) { if (audBase == null) return; + // 處理長期沒有被 Unload 的 Audio + if (!audBase.onDestroyAndUnload) + this.TryLRUCache(audBase.assetName); + this.LoadAndPlay(audBase, loops, volume); Logging.Print(string.Format("Play Audio: {0}, Current Length: {1} (s)", audBase?.mediaName, audBase?.CurrentLength())); diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache.meta b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache.meta new file mode 100644 index 00000000..1ff14061 --- /dev/null +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ea49d76f2fd2e8a4a9a2eb6f0f9e61f2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache/MediaLRUCache.cs b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache/MediaLRUCache.cs new file mode 100644 index 00000000..b883a2ae --- /dev/null +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache/MediaLRUCache.cs @@ -0,0 +1,112 @@ +using OxGFrame.MediaFrame.AudioFrame; +using OxGFrame.MediaFrame.VideoFrame; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; + +namespace OxGFrame.MediaFrame.Cacher +{ + internal class MediaLRUCache + { + private readonly int _capacity; + private readonly ConcurrentDictionary> _cache; + private readonly LinkedList _lruList; + + public int Count => this._cache.Count; + + public MediaLRUCache(int capacity) + { + if (capacity <= 0) + throw new ArgumentException("Capacity must be greater than zero."); + + this._capacity = capacity; + this._cache = new ConcurrentDictionary>(); + this._lruList = new LinkedList(); + } + + public string[] GetKeys() + { + return this._cache.Keys.ToArray(); + } + + public bool Contains(string key) + { + return this._cache.ContainsKey(key); + } + + public string Get(string key) + { + if (this._cache.TryGetValue(key, out var node)) + { + // Move the accessed item to the front of the LRU list + this._lruList.Remove(node); + this._lruList.AddFirst(node); + + return node.Value.Value; + } + + return default; + } + + public void Add(string key, string value) + { + if (this._cache.Count >= this._capacity) + this.RemoveLRUItem(); + + var cacheItem = new CacheItem(key, value); + var newNode = new LinkedListNode(cacheItem); + this._lruList.AddFirst(newNode); + this._cache.TryAdd(key, newNode); + } + + public bool Remove(string key) + { + if (this._cache.TryGetValue(key, out var node)) + { + node.Value.Value = default; + this._lruList.Remove(node); + this._cache.Remove(key, out _); + return true; + } + return false; + } + + public void Clear() + { + var keys = this.GetKeys(); + foreach (var key in keys) + { + this.Remove(key); + } + this._lruList.Clear(); + this._cache.Clear(); + } + + protected void RemoveLRUItem() + { + var lastNode = this._lruList.Last; + var key = lastNode.Value.Key; + var value = lastNode.Value.Value; + if (key.IndexOf(nameof(AudioBase)) != -1) + AudioManager.GetInstance().ForceUnload(value); + else if (key.IndexOf(nameof(VideoBase)) != -1) + VideoManager.GetInstance().ForceUnload(value); + lastNode.Value.Value = default; + this._cache.TryRemove(lastNode.Value.Key, out _); + this._lruList.RemoveLast(); + } + + private class CacheItem + { + public string Key { get; } + public string Value { get; set; } + + public CacheItem(string key, string value) + { + this.Key = key; + this.Value = value; + } + } + } +} \ No newline at end of file diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache/MediaLRUCache.cs.meta b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache/MediaLRUCache.cs.meta new file mode 100644 index 00000000..b8a39a8f --- /dev/null +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Cache/MediaLRUCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 80d75259b6f102e40ad2e50694e05932 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaBase.cs b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaBase.cs index e1e67774..d25db79c 100644 --- a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaBase.cs +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaBase.cs @@ -90,6 +90,7 @@ public async UniTask GetFileText() protected float _currentLength = 0f; // 影音當前長度 protected Action _endEvent = null; // 停止播放時的事件調用 public bool isPrepared { get; protected set; } = false; // 影音準備好的標記 + internal bool isDestroying = false; // 正在被銷毀的標記 internal void HandleFixedUpdate(float dt) { diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaManager.cs b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaManager.cs index 63584f1d..027f3687 100644 --- a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaManager.cs +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/Implement/MediaManager.cs @@ -1,5 +1,6 @@ using Cysharp.Threading.Tasks; using OxGFrame.AssetLoader; +using OxGFrame.MediaFrame.Cacher; using OxGKit.LoggingSystem; using System.Collections.Generic; using UnityEngine; @@ -11,6 +12,7 @@ internal abstract class MediaManager : MonoBehaviour where T : MediaBase protected Dictionary _dictAssetCache = new Dictionary(); // 【常駐】所有資源緩存 protected HashSet _loadingFlags = new HashSet(); // 用來標記正在加載中的資源 (暫存緩存) protected List _listAllCache = new List(); // 【常駐】所有進入播放的影音柱列緩存 (只會在 Destroy 時, Remove 對應的緩存) + protected MediaLRUCache _mediaLruCache = new MediaLRUCache(128); private static float _fdt; @@ -56,6 +58,19 @@ protected bool HasInLoadingFlags(string assetName) return this._loadingFlags.Contains(assetName); } + /// + /// 處理不常用的影音, 僅針對沒有啟用 onDestroyAndUnload 的設置 + /// + /// + /// + protected void TryLRUCache(string assetName) where U : T + { + string key = $"{typeof(U).Name}_{assetName}"; + if (!this._mediaLruCache.Contains(key)) + this._mediaLruCache.Add(key, assetName); + this._mediaLruCache.Get(key); + } + /// /// 從緩存中取的資源 /// @@ -254,7 +269,11 @@ protected virtual void Destroy(T mBase) mBase.OnRelease(); // 刪除物件 - if (!mBase.gameObject.IsDestroyed()) Destroy(mBase.gameObject); + if (!mBase.gameObject.IsDestroyed()) + { + mBase.isDestroying = true; + Destroy(mBase.gameObject); + } // 刪除柱列緩存 this._listAllCache.Remove(mBase); diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/VideoFrame/VideoBase.cs b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/VideoFrame/VideoBase.cs index 00527ea8..12f4cf5c 100644 --- a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/VideoFrame/VideoBase.cs +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/VideoFrame/VideoBase.cs @@ -314,7 +314,8 @@ private void OnDestroy() try { - VideoManager.GetInstance().Stop(this, true, true); + if (!this.isDestroying) + VideoManager.GetInstance().Stop(this, true, true); } catch { diff --git a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/VideoFrame/VideoManager.cs b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/VideoFrame/VideoManager.cs index 6c34aede..49b4928b 100644 --- a/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/VideoFrame/VideoManager.cs +++ b/Assets/OxGFrame/MediaFrame/Scripts/Runtime/Core/VideoFrame/VideoManager.cs @@ -1,4 +1,5 @@ using Cysharp.Threading.Tasks; +using OxGFrame.MediaFrame.AudioFrame; using OxGKit.LoggingSystem; using UnityEngine; @@ -52,6 +53,10 @@ private void _Play(VideoBase vidBase, int loops, float volume) { if (vidBase == null) return; + // 處理長期沒有被 Unload 的 Video + if (!vidBase.onDestroyAndUnload) + this.TryLRUCache(vidBase.assetName); + this.LoadAndPlay(vidBase, loops, volume); Logging.Print(string.Format("Play Video: {0}", vidBase?.mediaName)); diff --git a/Assets/OxGFrame/Samples~/CPFrameDemo/Resources/Example/Prefabs/Demo2CP.prefab b/Assets/OxGFrame/Samples~/CPFrameDemo/Resources/Example/Prefabs/Demo2CP.prefab index 7987ddbe..295b20f3 100644 --- a/Assets/OxGFrame/Samples~/CPFrameDemo/Resources/Example/Prefabs/Demo2CP.prefab +++ b/Assets/OxGFrame/Samples~/CPFrameDemo/Resources/Example/Prefabs/Demo2CP.prefab @@ -45,7 +45,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a8eab09c4e9c40c4f83660a4b158a58d, type: 3} m_Name: m_EditorClassIdentifier: - isCloseAndDestroy: 0 + allowInstantiate: 0 + onCloseAndDestroy: 0 + price: 0 --- !u!1 &7108754004220404273 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/OxGFrame/Samples~/CPFrameDemo/Scripts/Demo1CP.cs b/Assets/OxGFrame/Samples~/CPFrameDemo/Scripts/Demo1CP.cs index ef30fab5..5bcabd25 100644 --- a/Assets/OxGFrame/Samples~/CPFrameDemo/Scripts/Demo1CP.cs +++ b/Assets/OxGFrame/Samples~/CPFrameDemo/Scripts/Demo1CP.cs @@ -1,8 +1,25 @@ -using OxGFrame.CoreFrame.CPFrame; +using OxGFrame.CoreFrame.CPFrame; using UnityEngine; public class Demo1CP : CPBase { + // Use ~Node@XXX to Bind + + #region Binding Components + protected GameObject _b1; + protected GameObject[] _b2s; + + /// + /// Auto Binding Section + /// + protected override void OnAutoBind() + { + base.OnAutoBind(); + this._b1 = this.collector.GetNode("B1"); + this._b2s = this.collector.GetNodes("B2"); + } + #endregion + public override void OnCreate() { Debug.Log($"InitThis: {this.gameObject.name}"); @@ -11,11 +28,11 @@ public override void OnCreate() protected override void OnBind() { // Single Bind - Debug.Log($"Found: {this.gameObject.name} => {this.collector.GetNode("B1").name}"); + Debug.Log($"Found: {this.gameObject.name} => {_b1.name}"); // Multi Bind (Same Name) - Debug.Log($"Found Array Binds: {this.gameObject.name} => {this.collector.GetNodes("B2").Length}"); - foreach (var node in this.collector.GetNodes("B2")) + Debug.Log($"Found Array Binds: {this.gameObject.name} => {_b2s.Length}"); + foreach (var node in _b2s) { Debug.Log($"Found: {this.gameObject.name} => {node.name}"); } diff --git a/Assets/OxGFrame/Samples~/CPFrameDemo/Scripts/Demo2CP.cs b/Assets/OxGFrame/Samples~/CPFrameDemo/Scripts/Demo2CP.cs index df82794a..caec5b4c 100644 --- a/Assets/OxGFrame/Samples~/CPFrameDemo/Scripts/Demo2CP.cs +++ b/Assets/OxGFrame/Samples~/CPFrameDemo/Scripts/Demo2CP.cs @@ -1,10 +1,27 @@ -using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks; using OxGFrame.CoreFrame; using OxGFrame.CoreFrame.CPFrame; using UnityEngine; public class Demo2CP : CPBase { + // Use ~Node@XXX to Bind + + #region Binding Components + protected GameObject _b1; + protected GameObject _b2; + + /// + /// Auto Binding Section + /// + protected override void OnAutoBind() + { + base.OnAutoBind(); + this._b1 = this.collector.GetNode("B1"); + this._b2 = this.collector.GetNode("B2"); + } + #endregion + public override void OnCreate() { Debug.Log($"InitThis: {this.gameObject.name}"); @@ -12,8 +29,8 @@ public override void OnCreate() protected override void OnBind() { - Debug.Log($"Found: {this.gameObject.name} => {this.collector.GetNode("B1").name}"); - Debug.Log($"Found: {this.gameObject.name} => {this.collector.GetNode("B2").name}"); + Debug.Log($"Found: {this.gameObject.name} => {this._b1.name}"); + Debug.Log($"Found: {this.gameObject.name} => {this._b1.name}"); } protected override void OnShow() diff --git a/Assets/OxGFrame/Samples~/SRFrameDemo/Resources/Example/ScenePrefabs/CubeSceneSR.prefab b/Assets/OxGFrame/Samples~/SRFrameDemo/Resources/Example/ScenePrefabs/CubeSceneSR.prefab index 03aad92b..caf30e14 100644 --- a/Assets/OxGFrame/Samples~/SRFrameDemo/Resources/Example/ScenePrefabs/CubeSceneSR.prefab +++ b/Assets/OxGFrame/Samples~/SRFrameDemo/Resources/Example/ScenePrefabs/CubeSceneSR.prefab @@ -13,7 +13,7 @@ GameObject: - component: {fileID: 8899546002309488419} - component: {fileID: 5922267057065990076} m_Layer: 0 - m_Name: Cube + m_Name: _Node@Cube m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -110,7 +110,7 @@ GameObject: - component: {fileID: 8701044861067494743} - component: {fileID: 5177086667333995691} m_Layer: 0 - m_Name: Cube (3) + m_Name: _Node@Cube m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -244,7 +244,7 @@ MonoBehaviour: m_EditorClassIdentifier: allowInstantiate: 1 onCloseAndDestroy: 0 - gsSetting: + srSetting: whenCloseAllToSkip: 0 whenHideAllToSkip: 0 --- !u!1 &7655318841875574380 @@ -260,7 +260,7 @@ GameObject: - component: {fileID: 3496350111037615807} - component: {fileID: 4142412492571997849} m_Layer: 0 - m_Name: Cube (2) + m_Name: _Node@Cube m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -357,7 +357,7 @@ GameObject: - component: {fileID: 8117388445162294548} - component: {fileID: 3455565230967714968} m_Layer: 0 - m_Name: Cube (1) + m_Name: _Node@Cube m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 diff --git a/Assets/OxGFrame/Samples~/SRFrameDemo/Scripts/CubeSceneSR.cs b/Assets/OxGFrame/Samples~/SRFrameDemo/Scripts/CubeSceneSR.cs index ee730176..c9f0c3c8 100644 --- a/Assets/OxGFrame/Samples~/SRFrameDemo/Scripts/CubeSceneSR.cs +++ b/Assets/OxGFrame/Samples~/SRFrameDemo/Scripts/CubeSceneSR.cs @@ -1,9 +1,24 @@ -using UnityEngine; +using UnityEngine; using Cysharp.Threading.Tasks; using OxGFrame.CoreFrame.SRFrame; public class CubeSceneSR : SRBase { + // Use _Node@XXX to Bind + + #region Binding Components + protected GameObject[] _cubes; + + /// + /// Auto Binding Section + /// + protected override void OnAutoBind() + { + base.OnAutoBind(); + this._cubes = this.collector.GetNodes("Cube"); + } + #endregion + public override void OnCreate() { } @@ -52,4 +67,4 @@ protected override void OnClose() { } -} +} \ No newline at end of file diff --git a/Assets/OxGFrame/Samples~/SRFrameDemo/Scripts/MeshResSR.cs b/Assets/OxGFrame/Samples~/SRFrameDemo/Scripts/MeshResSR.cs index f2def355..b8cdeae1 100644 --- a/Assets/OxGFrame/Samples~/SRFrameDemo/Scripts/MeshResSR.cs +++ b/Assets/OxGFrame/Samples~/SRFrameDemo/Scripts/MeshResSR.cs @@ -4,6 +4,11 @@ public class MeshResSR : SRBase { + // Use _Node@XXX to Bind + + #region Binding Components + #endregion + public override void OnCreate() { @@ -63,4 +68,4 @@ public Mesh GetSphereMesh() { return this.collector.GetNode("Sphere").GetComponent().mesh; } -} +} \ No newline at end of file diff --git a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo1UI.prefab b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo1UI.prefab index 4ef049e5..9154623d 100644 --- a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo1UI.prefab +++ b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo1UI.prefab @@ -93,7 +93,7 @@ GameObject: - component: {fileID: 8844711520655062969} - component: {fileID: 6792892691383569100} m_Layer: 0 - m_Name: _Node@OpenBtn + m_Name: _Node@Open*Btn$private m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -214,7 +214,7 @@ GameObject: - component: {fileID: 2537838258604403230} - component: {fileID: 7219099323406835009} m_Layer: 0 - m_Name: Image + m_Name: _Node@Decor*Img$public[hi] m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -290,7 +290,7 @@ GameObject: - component: {fileID: 1110609142422051904} - component: {fileID: 3295446933826572382} m_Layer: 0 - m_Name: _Node@Image1 + m_Name: _Node@View*Img[sf] m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -466,6 +466,8 @@ MonoBehaviour: sprite: {fileID: 0} material: {fileID: 0} isClickMaskToClose: 1 + decorImg: {fileID: 0} + _viewImg: {fileID: 0} --- !u!1 &8326820277654019497 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo2UI.prefab b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo2UI.prefab index 54697be6..21285ec5 100644 --- a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo2UI.prefab +++ b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo2UI.prefab @@ -92,7 +92,7 @@ GameObject: - component: {fileID: 6060700927929970216} - component: {fileID: 9120905121253565105} m_Layer: 0 - m_Name: _Node@Image2 + m_Name: _Node@View*Img m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -5174,7 +5174,7 @@ GameObject: - component: {fileID: 5066250251986725119} - component: {fileID: 2536554217800717421} m_Layer: 0 - m_Name: _Node@OpenBtn + m_Name: _Node@Open*Btn m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 diff --git a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo3UI.prefab b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo3UI.prefab index d6e0bddd..1d04dcf1 100644 --- a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo3UI.prefab +++ b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/ScreenUI/Demo3UI.prefab @@ -12,7 +12,7 @@ GameObject: - component: {fileID: 5067921289219293211} - component: {fileID: 8828821989333466438} m_Layer: 0 - m_Name: _Node@Image3 + m_Name: _Node@View*Img m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 diff --git a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo1UI.prefab b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo1UI.prefab index 18b5303f..7456e31b 100644 --- a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo1UI.prefab +++ b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo1UI.prefab @@ -93,7 +93,7 @@ GameObject: - component: {fileID: 8844711520655062969} - component: {fileID: 6792892691383569100} m_Layer: 0 - m_Name: _Node@OpenBtn + m_Name: _Node@Open*Btn$private m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -214,7 +214,7 @@ GameObject: - component: {fileID: 2537838258604403230} - component: {fileID: 7219099323406835009} m_Layer: 0 - m_Name: Image + m_Name: _Node@Decor*Img$public[hi] m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -290,7 +290,7 @@ GameObject: - component: {fileID: 1110609142422051904} - component: {fileID: 3295446933826572382} m_Layer: 0 - m_Name: _Node@Image1 + m_Name: _Node@View*Img[sf] m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -466,6 +466,8 @@ MonoBehaviour: sprite: {fileID: 0} material: {fileID: 0} isClickMaskToClose: 1 + decorImg: {fileID: 0} + _viewImg: {fileID: 0} --- !u!1 &8326820277654019497 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo2UI.prefab b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo2UI.prefab index ab57d754..494ea903 100644 --- a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo2UI.prefab +++ b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo2UI.prefab @@ -92,7 +92,7 @@ GameObject: - component: {fileID: 6060700927929970216} - component: {fileID: 9120905121253565105} m_Layer: 0 - m_Name: _Node@Image2 + m_Name: _Node@View*Img m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -5174,7 +5174,7 @@ GameObject: - component: {fileID: 5066250251986725119} - component: {fileID: 2536554217800717421} m_Layer: 0 - m_Name: _Node@OpenBtn + m_Name: _Node@Open*Btn m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 diff --git a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo3UI.prefab b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo3UI.prefab index a5b2880f..9d3f3b3b 100644 --- a/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo3UI.prefab +++ b/Assets/OxGFrame/Samples~/UIFrameDemo/Resources/Example/UI/WorldUI/Demo3UI.prefab @@ -12,7 +12,7 @@ GameObject: - component: {fileID: 5067921289219293211} - component: {fileID: 8828821989333466438} m_Layer: 0 - m_Name: _Node@Image3 + m_Name: _Node@View*Img m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 diff --git a/Assets/OxGFrame/Samples~/UIFrameDemo/Scripts/Demo1UI.cs b/Assets/OxGFrame/Samples~/UIFrameDemo/Scripts/Demo1UI.cs index 79860f26..1ba67edb 100644 --- a/Assets/OxGFrame/Samples~/UIFrameDemo/Scripts/Demo1UI.cs +++ b/Assets/OxGFrame/Samples~/UIFrameDemo/Scripts/Demo1UI.cs @@ -1,4 +1,4 @@ -using UnityEngine; +using UnityEngine; using OxGFrame.CoreFrame.UIFrame; using Cysharp.Threading.Tasks; using UnityEngine.UI; @@ -6,9 +6,26 @@ public class Demo1UI : UIBase { - private Image myImage; - private Button oepnBtn; - private Image myImage2; + // Use _Node@XXX to Bind + + #region Binding Components + private Button _openBtn; + [HideInInspector] + public Image decorImg; + [SerializeField] + protected Image _viewImg; + + /// + /// Auto Binding Section + /// + protected override void OnAutoBind() + { + base.OnAutoBind(); + this._openBtn = this.collector.GetNodeComponent