From e0b5f9431b2190d0fb95ac75ed3cc6c216410683 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 4 Jun 2025 12:30:19 -0700 Subject: [PATCH 1/6] add a pre-build hook to the parameter build processor --- Editor/Processors/ParameterBuildProcessor.cs | 26 +++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Editor/Processors/ParameterBuildProcessor.cs b/Editor/Processors/ParameterBuildProcessor.cs index c21936f..1caebfa 100644 --- a/Editor/Processors/ParameterBuildProcessor.cs +++ b/Editor/Processors/ParameterBuildProcessor.cs @@ -14,8 +14,13 @@ namespace PocketGems.Parameters.Processors.Editor /// Regenerate all parameters into a single flat buffer prior to starting build. /// [ExcludeFromCoverage] - internal class ParameterBuildProcessor : IPreprocessBuildWithReport + public class ParameterBuildProcessor : IPreprocessBuildWithReport { + /// + /// Called before parameter building occurs for any parameters modifiations/baking needed. + /// + public static event Action OnPreBuild; + public int callbackOrder => 0; /// @@ -30,9 +35,24 @@ public void OnPreprocessBuild(BuildReport report) internal static bool BuildAndValidateParameters() { - ParameterDebug.Log($"{typeof(ParameterBuildProcessor)} generating parameters."); + try + { + if (OnPreBuild != null) + { + Console.WriteLine($"{typeof(ParameterBuildProcessor)} calling prebuild event start."); + OnPreBuild.Invoke(); + Console.WriteLine($"{typeof(ParameterBuildProcessor)} calling prebuild event finished."); + } + } + catch (Exception e) + { + Console.Error.WriteLine(e.Message); + return false; + } + + Console.WriteLine($"{typeof(ParameterBuildProcessor)} generating parameters."); var success = EditorParameterDataManager.GenerateData(GenerateDataType.All, out var failedOperation); - ParameterDebug.Log($"{typeof(ParameterBuildProcessor)} finished generating parameters."); + Console.WriteLine($"{typeof(ParameterBuildProcessor)} finished generating parameters."); // in batch mode, write out to console for readability in console logs if (Application.isBatchMode && !success) From 2118dfeaa8baee1480d2eef03b271bfe4bd49fab Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 5 Jun 2025 10:57:53 -0700 Subject: [PATCH 2/6] Add validation warning if the sum of info validators is too long --- .../Validation/ParameterManagerValidator.cs | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Runtime/Validation/ParameterManagerValidator.cs b/Runtime/Validation/ParameterManagerValidator.cs index d029ebe..a3c9f57 100644 --- a/Runtime/Validation/ParameterManagerValidator.cs +++ b/Runtime/Validation/ParameterManagerValidator.cs @@ -96,6 +96,7 @@ public void Validate() where T : class, IBaseInfo // constants private const int SlowExecutingValidatorInfoMillis = 10; + private const int SlowExecutingValidatorInfoTotalMillis = 100; private const int SlowExecutingValidatorMillis = 100; // built in attributes @@ -157,7 +158,7 @@ private void ValidateInfoDataValidators(List infos, bool recurseInterfaces { var error = new ValidationError(typeof(T), null, null, $"{dataValidator.GetType().Name}.{nameof(dataValidator.ValidateParameters)} took {stopwatch.ElapsedMilliseconds}ms to run validation.", - severity:ValidationError.Severity.Warning); + severity: ValidationError.Severity.Warning); _errors.Add(error); } } @@ -169,6 +170,8 @@ private void ValidateInfoDataValidators(List infos, bool recurseInterfaces _verifiedInfosMap[dataValidator] = verifiedInfos; } + stopwatch.Restart(); + Stopwatch individualInfoStopwatch = new(); for (int j = 0; j < infos.Count; j++) { var info = infos[j]; @@ -178,7 +181,7 @@ private void ValidateInfoDataValidators(List infos, bool recurseInterfaces verifiedInfos.Add(info); try { - stopwatch.Restart(); + individualInfoStopwatch.Restart(); dataValidator.ValidateInfo(_parameterManager, info); } catch (Exception e) @@ -189,14 +192,23 @@ private void ValidateInfoDataValidators(List infos, bool recurseInterfaces Debug.LogError(e); } - stopwatch.Stop(); - if (stopwatch.ElapsedMilliseconds >= SlowExecutingValidatorInfoMillis) + individualInfoStopwatch.Stop(); + if (individualInfoStopwatch.ElapsedMilliseconds >= SlowExecutingValidatorInfoMillis) { - var error = new ValidationError(typeof(T), info.Identifier, null, $"Took {stopwatch.ElapsedMilliseconds}ms to run info validation.", + var error = new ValidationError(typeof(T), info.Identifier, null, $"Took {individualInfoStopwatch.ElapsedMilliseconds}ms to run info validation.", severity: ValidationError.Severity.Warning); _errors.Add(error); } } + + stopwatch.Stop(); + if (stopwatch.ElapsedMilliseconds >= SlowExecutingValidatorInfoTotalMillis) + { + var error = new ValidationError(typeof(T), null, null, + $"Took {stopwatch.ElapsedMilliseconds}ms to run all {nameof(IDataValidator.ValidateInfo)} methods.", + severity: ValidationError.Severity.Warning); + _errors.Add(error); + } } } From 2f8ad76e3cdcf62dccd4afee087d46deb0e0da26 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 5 Jun 2025 12:20:34 -0700 Subject: [PATCH 3/6] Optimize the validation performance for checking addressables existance --- .../AssertAssignedReferenceExistsAttribute.cs | 14 +++++++------ .../Validation/ParameterManagerValidator.cs | 21 +++++++++++++++++-- .../Validation/Attributes/AttributesTest.cs | 13 +++++++++++- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/Runtime/Validation/Attributes/AssertAssignedReferenceExistsAttribute.cs b/Runtime/Validation/Attributes/AssertAssignedReferenceExistsAttribute.cs index 14c305b..5127275 100644 --- a/Runtime/Validation/Attributes/AssertAssignedReferenceExistsAttribute.cs +++ b/Runtime/Validation/Attributes/AssertAssignedReferenceExistsAttribute.cs @@ -1,12 +1,9 @@ using System; +using System.Collections.Generic; using System.Reflection; using PocketGems.Parameters.Interface; -using UnityEngine; #if ADDRESSABLE_PARAMS using UnityEngine.AddressableAssets; -#if UNITY_EDITOR -using UnityEditor.AddressableAssets; -#endif #endif namespace PocketGems.Parameters.Validation.Attributes @@ -17,9 +14,15 @@ internal class AssertAssignedReferenceExistsAttribute : BaseValidationAttribute private bool _isAssetReference; #endif private MethodInfo _paramRefGetInfoMethod; + private HashSet _addressablesGuidHashSet; protected override bool CompatibleWithReadOnlyLists => true; + internal AssertAssignedReferenceExistsAttribute(HashSet addressablesGuidHashSet) + { + _addressablesGuidHashSet = addressablesGuidHashSet; + } + protected override bool CheckType(Type type) { #if ADDRESSABLE_PARAMS @@ -66,8 +69,7 @@ private string ValidateAssetReference(AssetReference assetReference) if (string.IsNullOrEmpty(assetReference.AssetGUID)) return null; - var settings = AddressableAssetSettingsDefaultObject.Settings; - bool foundEntry = settings.FindAssetEntry(assetReference.AssetGUID) != null; + bool foundEntry = _addressablesGuidHashSet.Contains(assetReference.AssetGUID); return foundEntry ? null : $"cannot find addressable with guid {assetReference.AssetGUID}"; #else return null; diff --git a/Runtime/Validation/ParameterManagerValidator.cs b/Runtime/Validation/ParameterManagerValidator.cs index a3c9f57..226b28c 100644 --- a/Runtime/Validation/ParameterManagerValidator.cs +++ b/Runtime/Validation/ParameterManagerValidator.cs @@ -6,6 +6,9 @@ using System.Reflection; using PocketGems.Parameters.Interface; using PocketGems.Parameters.Validation.Attributes; +#if ADDRESSABLE_PARAMS && UNITY_EDITOR +using UnityEditor.AddressableAssets; +#endif using Debug = UnityEngine.Debug; namespace PocketGems.Parameters.Validation @@ -46,9 +49,23 @@ public ParameterManagerValidator(IParameterManager parameterManager) _parameterManager = parameterManager; _errors = new List(); - // auto added attributes - add any others here + var addressablesGuidHashSet = new HashSet(); +#if ADDRESSABLE_PARAMS && UNITY_EDITOR + // caching addressable entries so lookup is faster + var settings = AddressableAssetSettingsDefaultObject.Settings; + foreach (var group in settings.groups) + { + if (group == null) continue; + foreach (var entry in group.entries) + { + if (!string.IsNullOrEmpty(entry.guid)) + addressablesGuidHashSet.Add(entry.guid); + } + } +#endif + _builtInAttributesCreators = - new Func[] { () => new AssertAssignedReferenceExistsAttribute() }; + new Func[] { () => new AssertAssignedReferenceExistsAttribute(addressablesGuidHashSet) }; _builtInAttributesInstancePool = new IValidationAttribute[_builtInAttributesCreators.Length]; for (int i = 0; i < _builtInAttributesCreators.Length; i++) _builtInAttributesInstancePool[i] = _builtInAttributesCreators[i].Invoke(); diff --git a/Tests/Runtime/Validation/Attributes/AttributesTest.cs b/Tests/Runtime/Validation/Attributes/AttributesTest.cs index 0c11620..cfda0c5 100644 --- a/Tests/Runtime/Validation/Attributes/AttributesTest.cs +++ b/Tests/Runtime/Validation/Attributes/AttributesTest.cs @@ -411,7 +411,8 @@ public void AssertStringNotEmpty() [Test] public void AssertAssignedReferenceExists() { - var attribute = new AssertAssignedReferenceExistsAttribute(); + var addressablesGuidHashSet = new HashSet(); + var attribute = new AssertAssignedReferenceExistsAttribute(addressablesGuidHashSet); // can validate AssertCanValidate(attribute, nameof(ParameterReference), true); @@ -500,6 +501,16 @@ public void AssertAssignedReferenceExists() AssertAttribute(attribute, nameof(AssetReferenceArray), AssetReferenceArray, false); AssertAttribute(attribute, nameof(AssetReferenceSprite), AssetReferenceSprite, false); AssertAttribute(attribute, nameof(AssetReferenceSpriteArray), AssetReferenceSpriteArray, false); + + addressablesGuidHashSet.Add(validGuid); + AssetReference = new AssetReference(validGuid); + AssetReferenceArray = new[] { new AssetReference(validGuid) }; + AssetReferenceSprite = new AssetReferenceSprite(validGuid); + AssetReferenceSpriteArray = new[] { new AssetReferenceSprite(validGuid) }; + AssertAttribute(attribute, nameof(AssetReference), AssetReference, true); + AssertAttribute(attribute, nameof(AssetReferenceArray), AssetReferenceArray, true); + AssertAttribute(attribute, nameof(AssetReferenceSprite), AssetReferenceSprite, true); + AssertAttribute(attribute, nameof(AssetReferenceSpriteArray), AssetReferenceSpriteArray, true); #endif } From 46bd6cfdc0a656fe136e6adf40b968b474a3040d Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 9 Jun 2025 10:22:16 -0700 Subject: [PATCH 4/6] support selecting and copying of validation error messages in the window --- Editor/Editor/Validation/ValidationTreeView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Editor/Editor/Validation/ValidationTreeView.cs b/Editor/Editor/Validation/ValidationTreeView.cs index f11de10..19dc081 100644 --- a/Editor/Editor/Validation/ValidationTreeView.cs +++ b/Editor/Editor/Validation/ValidationTreeView.cs @@ -158,7 +158,7 @@ void CellGUI(Rect cellRect, TreeViewItem item, Columns co } if (column == Columns.ErrorMessage) value = item.data.ValidationError?.Message; - DefaultGUI.Label(cellRect, value, args.selected, args.focused); + EditorGUI.SelectableLabel(cellRect, value, EditorStyles.label); } break; } From d0fecc920079ef9c027fa39ec03a763a8ff16f1b Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 9 Jul 2025 10:46:17 -0700 Subject: [PATCH 5/6] update code gen min version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 47c476a..01c56f9 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "name": "Pocket Gems", "url": "https://www.pocketgems.com/" }, - "codegen": "0.0.1", + "codegen": "0.0.3", "dependencies": { "com.unity.nuget.newtonsoft-json": "2.0.2", "com.unity.testtools.codecoverage": "1.2.4", From e352c167172e16fe31b3fc82ac05085bf66117a4 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 4 Jun 2025 12:41:52 -0700 Subject: [PATCH 6/6] changelog and package --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ce7ba0..c9a08ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All package updates & migration steps will be listed in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.6.0] - 2025-07-24 +### Added +- Support to add pre-build events to the `ParameterBuildProcessor` +- Validation warning if the sum of info validators is too lon +- Support for selecting and copying of validation error messages in the window. +### Changed +- Optimize the validation performance for checking addressables existance. + ## [4.5.1] - 2025-04-29 ### Fixes - Fix support for multiple parameter managers initalized at once. diff --git a/package.json b/package.json index 01c56f9..272e619 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.pocketgems.scriptableobject.flatbuffer", - "version": "4.5.1", + "version": "4.6.0", "displayName": "Scriptable Object - FlatBuffer", "description": "Seamless syncing between Scriptable Objects and CSVs. Scriptable Object data built to Google FlatBuffers for optimal runtime loading & access.", "unity": "2021.3",