Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion Editor/Editor/Validation/ValidationTreeView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void CellGUI(Rect cellRect, TreeViewItem<ValidationTreeElement> 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;
}
Expand Down
26 changes: 23 additions & 3 deletions Editor/Processors/ParameterBuildProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ namespace PocketGems.Parameters.Processors.Editor
/// Regenerate all parameters into a single flat buffer prior to starting build.
/// </summary>
[ExcludeFromCoverage]
internal class ParameterBuildProcessor : IPreprocessBuildWithReport
public class ParameterBuildProcessor : IPreprocessBuildWithReport
{
/// <summary>
/// Called before parameter building occurs for any parameters modifiations/baking needed.
/// </summary>
public static event Action OnPreBuild;

public int callbackOrder => 0;

/// <summary>
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -17,9 +14,15 @@ internal class AssertAssignedReferenceExistsAttribute : BaseValidationAttribute
private bool _isAssetReference;
#endif
private MethodInfo _paramRefGetInfoMethod;
private HashSet<string> _addressablesGuidHashSet;

protected override bool CompatibleWithReadOnlyLists => true;

internal AssertAssignedReferenceExistsAttribute(HashSet<string> addressablesGuidHashSet)
{
_addressablesGuidHashSet = addressablesGuidHashSet;
}

protected override bool CheckType(Type type)
{
#if ADDRESSABLE_PARAMS
Expand Down Expand Up @@ -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;
Expand Down
43 changes: 36 additions & 7 deletions Runtime/Validation/ParameterManagerValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -46,9 +49,23 @@ public ParameterManagerValidator(IParameterManager parameterManager)
_parameterManager = parameterManager;
_errors = new List<ValidationError>();

// auto added attributes - add any others here
var addressablesGuidHashSet = new HashSet<string>();
#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<IValidationAttribute>[] { () => new AssertAssignedReferenceExistsAttribute() };
new Func<IValidationAttribute>[] { () => new AssertAssignedReferenceExistsAttribute(addressablesGuidHashSet) };
_builtInAttributesInstancePool = new IValidationAttribute[_builtInAttributesCreators.Length];
for (int i = 0; i < _builtInAttributesCreators.Length; i++)
_builtInAttributesInstancePool[i] = _builtInAttributesCreators[i].Invoke();
Expand Down Expand Up @@ -96,6 +113,7 @@ public void Validate<T>() where T : class, IBaseInfo

// constants
private const int SlowExecutingValidatorInfoMillis = 10;
private const int SlowExecutingValidatorInfoTotalMillis = 100;
private const int SlowExecutingValidatorMillis = 100;

// built in attributes
Expand Down Expand Up @@ -157,7 +175,7 @@ private void ValidateInfoDataValidators<T>(List<T> 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);
}
}
Expand All @@ -169,6 +187,8 @@ private void ValidateInfoDataValidators<T>(List<T> infos, bool recurseInterfaces
_verifiedInfosMap[dataValidator] = verifiedInfos;
}

stopwatch.Restart();
Stopwatch individualInfoStopwatch = new();
for (int j = 0; j < infos.Count; j++)
{
var info = infos[j];
Expand All @@ -178,7 +198,7 @@ private void ValidateInfoDataValidators<T>(List<T> infos, bool recurseInterfaces
verifiedInfos.Add(info);
try
{
stopwatch.Restart();
individualInfoStopwatch.Restart();
dataValidator.ValidateInfo(_parameterManager, info);
}
catch (Exception e)
Expand All @@ -189,14 +209,23 @@ private void ValidateInfoDataValidators<T>(List<T> 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);
}
}
}

Expand Down
13 changes: 12 additions & 1 deletion Tests/Runtime/Validation/Attributes/AttributesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,8 @@ public void AssertStringNotEmpty()
[Test]
public void AssertAssignedReferenceExists()
{
var attribute = new AssertAssignedReferenceExistsAttribute();
var addressablesGuidHashSet = new HashSet<string>();
var attribute = new AssertAssignedReferenceExistsAttribute(addressablesGuidHashSet);

// can validate
AssertCanValidate(attribute, nameof(ParameterReference), true);
Expand Down Expand Up @@ -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
}

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -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",
Expand Down
Loading