Skip to content

3.3.0

Choose a tag to compare

@github-actions github-actions released this 08 May 21:50
· 170 commits to refs/heads/main since this release
bb15a67

Changelog

Added

  • Failed Tests Exporter: New editor utility that hooks into the Unity Test Runner to automatically capture test failures and export them to timestamped text files
    • Automatically records test name, failure message, and stack trace for each failed test
    • Configurable output directory with a visual folder picker — defaults to the project root if not set
    • Path validation on every use: falls back to the project root if the configured directory is missing, invalid, or outside the project
    • Menu items under Tools > Wallstop Studios > Unity Helpers to export or clear captured failures
    • Disabled by default — enable via Project Settings > Wallstop Studios > Unity Helpers

Fixed

  • Editor asset import-loop pressure from unchanged metadata saves: ScriptableObjectSingletonMetadata and AttributeMetadataCache now skip SetDirty / SaveAssets work when regenerated metadata is unchanged. This prevents initialize-on-load and explicit singleton ensure passes from repeatedly re-saving identical assets during Unity test runs or editor refreshes, reducing the chance of Unity's "infinite import loop" detector tripping on native runs.
  • AssetPostprocessorDeferral dedup regressing structurally-equal-but-distinct drains: AssetPostprocessorDeferral.Schedule now dedups pending drains via ReferenceEquals instead of List<Action>.Contains (which invokes Delegate.Equals). The prior structural-equality behavior silently coalesced two distinct delegates that shared the same Method+Target -- common when a local helper returns a lambda that captures only outer-method variables -- so a self-rescheduling drain could be dropped entirely. Matches the documented intent in the AssetPostprocessor safety skill and is pinned by the new ScheduleStructurallyEqualButDistinctDelegatesAreNotDeduplicated regression test
  • WButton conflict warnings hidden in collapsed foldouts: Fixed group conflict warnings (placement, priority, and draw order) not rendering when foldout groups are collapsed. Conflict warnings now render in the group header area regardless of foldout expansion state, and warning cache population is validated across collapsed, expanded, and always-open foldout behavior.
  • Spurious "SendMessage cannot be called..." warnings from asset processors: Eliminated spurious "SendMessage cannot be called during Awake, CheckConsistency, or OnValidate" warnings from DetectAssetChangeProcessor and related editor processors (LlmArtifactCleaner, SpriteLabelProcessor) by deferring callback invocation out of Unity's asset-import phase via a shared AssetPostprocessorDeferral helper backed by EditorApplication.delayCall. The prior synchronous path called AssetDatabase.LoadAllAssetsAtPath / GetComponentsInChildren / user callbacks during the import phase, which triggered Unity's internal sprite/renderer lifecycle relays and produced per-import warning storms. A new opt-out setting (Project Settings > Wallstop Studios > Unity Helpers > Detect Asset Changes, option Defer Post-process Callbacks, default on) restores the old synchronous behavior for users who require it. (#234)
  • Pool auto-purge throttle dropping real purges: Fixed WallstopGenericPool<T>.PurgeInternalCore letting the 1-second MinAutoPurgeIntervalSeconds throttle block MaxPoolSize enforcement. A Rent/Return that advanced _lastAutoPurgeTime on a healthy-pool scan would block a subsequent same-tick call that pushed the pool past MaxPoolSize, silently skipping the CapacityExceeded purge and dropping the matching OnPurge notification. The throttle now has two orthogonal rules: (1) when the pool is observably over MaxPoolSize, the throttle is bypassed entirely so a burst of returns cannot accumulate beyond capacity within a single clock tick; (2) otherwise the throttle still rate-limits scans (preserving the O(1) amortized fast path for healthy pools under contention). The multithreaded variant also guards the timestamp advance with CAS max-semantics so concurrent out-of-order writes cannot regress the throttle clock. Applies to both the multithreaded and SINGLE_THREADED pool variants
  • Pool performance regression from O(n) usage tracking: Fixed RollingHighWaterMark (used by pool purge system) performing O(n) operations on every pool rent/return, causing 100x slowdowns under sustained load. Replaced List<Sample> with CyclicBuffer<Sample> for O(1) add/remove, added incremental running sum for O(1) average computation, and added a monotonic deque for O(1) amortized peak tracking. Previously, 100K rent/return cycles took 20+ seconds; now completes within 200ms budget
  • TexturePlatformOverrideEntryDrawer render-phase mutations: Fixed OnGUI writing to SerializedProperty values every frame without BeginChangeCheck/EndChangeCheck guards. Direct assignments like apply.boolValue = EditorGUI.ToggleLeft(...) and nameProp.stringValue = EditorGUI.TextField(...) dirtied the SerializedObject on every repaint, corrupting undo history. Also removed a redundant render-phase writeback of the computed display label to the platform name property
  • TexturePlatformOverrideEntryDrawer GenericMenu undo and Custom handling: Fixed GenericMenu callback not calling Undo.RecordObjects before mutation and not handling the "Custom" menu option. Selecting "Custom" from the dropdown now correctly sets the platform name to string.Empty (triggering custom mode), and all selections are undoable
  • SourceFolderEntryDrawer render-phase mutation: Fixed EnumFlagsField for selection mode writing to modeProp.intValue every frame without a BeginChangeCheck/EndChangeCheck guard
  • AttributeMetadataCache generator path mismatch: Fixed AttributeMetadataCacheGenerator.GetOrCreateCache() using hardcoded asset paths that did not match the [ScriptableSingletonPath("Wallstop Studios/Unity Helpers")] attribute on AttributeMetadataCache. The generator was creating and loading the cache asset from Assets/Resources/Wallstop Studios/ instead of the correct Assets/Resources/Wallstop Studios/Unity Helpers/ path, causing cache generation to silently fail when the singleton was already loaded at the correct path
  • IntDropDown invalid value handling: Fixed IntDropDownDrawer to properly handle property values that fall outside the configured options. Invalid values (values not in the options array) are now preserved without modification during render and clearly displayed with an "(Invalid)" suffix. Previously, invalid values were displayed as-is without any visual indication. The UI Toolkit IntDropDownSelector.GetDefaultValue() now returns the first option instead of 0
  • Linux dropdown rendering phantom rows: Replaced all EditorGUI.Popup usage with GenericMenu-based dropdowns to eliminate phantom empty rows when selected index is -1 on Linux. Affected drawers: WValueDropDownDrawer, IntDropDownDrawer, StringInListDrawer, TexturePlatformOverrideEntryDrawer (standard variants), and WValueDropDownOdinDrawer, IntDropDownOdinDrawer, StringInListOdinDrawer (Odin Inspector variants). Odin drawers now always use GenericMenu regardless of the page limit setting, since GenericMenu handles all list sizes correctly without the rendering issues that required the threshold (#209)
  • Multi-object editing for WValueDropDown: Added typed SerializedProperty setters for Unity-native types (Vector2, Vector3, Vector4, Color, Rect, Bounds, Quaternion, AnimationCurve, Hash128, and their Int variants) in WValueDropDownDrawer.ApplyOption to avoid the reflection fallback for known property types. The generic reflection path now iterates over all serializedObject.targetObjects for proper multi-object editing support instead of only updating the first selected object
  • SerializableSet undo not working for add, clear, sort, and commit operations: Fixed TryClearSet, TryAddNewElement, TryCommitPendingEntry, AppendNullPlaceholderEntry, and TrySortElements in SerializableSetPropertyDrawer not calling Undo.FlushUndoRecordObjects() after direct object mutation. These methods used Undo.RecordObjects to snapshot pre-change state but never finalized the undo record, causing Undo.PerformUndo() to silently do nothing
  • GUIContent GC pressure in drawer OnGUI: Fixed per-frame GUIContent allocations in IntDropDownDrawer.DrawGenericMenuDropDown and PoolTypeConfigurationDrawer.OnGUI that created avoidable garbage collection pressure in the Inspector. Both drawers now reuse static GUIContent instances (consistent with WValueDropDownDrawer and StringInListDrawer which already followed this pattern)

Pull Requests

Contributors

@Copilot, Dependabot (@dependabot)[bot], Eli Pinkerton (@wallstop), copilot-swe-agent[bot] and dependabot[bot]