Skip to content

Commit

Permalink
feat: add extract-observe API, respond to animation mode changes (#279)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdunderscore authored Jul 2, 2024
1 parent 9f810f8 commit a0b6ec3
Show file tree
Hide file tree
Showing 17 changed files with 418 additions and 245 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- [#279] Added an `Observe` overload which checks for changes to an extracted value, to help respond to animation mode
changes

### Fixed

Expand Down
36 changes: 20 additions & 16 deletions Editor/ChangeStream/ListenerSet.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
#region

using System;
using UnityEditor;

#endregion

namespace nadena.dev.ndmf.rq.unity.editor
{
internal class Listener<T> : IDisposable
{
private ListenerSet<T> _owner;
internal Listener<T> _next, _prev;

private readonly ListenerSet<T>.Invokee _callback;
private readonly WeakReference<object> _param;
private readonly ListenerSet<T>.Filter _filter;
private readonly WeakReference<ComputeContext> _ctx;

internal Listener(
ListenerSet<T> owner,
ListenerSet<T>.Invokee callback,
object param
ListenerSet<T>.Filter filter,
ComputeContext ctx
)
{
_owner = owner;
_next = _prev = this;
_callback = callback;
_param = new WeakReference<object>(param);
_filter = filter;
_ctx = ctx == null ? null : new WeakReference<ComputeContext>(ctx);
}

public void Dispose()
Expand All @@ -35,12 +33,12 @@ public void Dispose()
}

_next = _prev = null;
_param.SetTarget(null);
_ctx.SetTarget(null);
}

internal void MaybePrune()
{
if (!_param.TryGetTarget(out _))
if (!_ctx.TryGetTarget(out var ctx) || ctx.IsInvalidated)
{
Dispose();
}
Expand All @@ -49,22 +47,28 @@ internal void MaybePrune()
// Invoked under lock(_owner)
internal void MaybeFire(T info)
{
if (!_param.TryGetTarget(out var target) || _callback(target, info))
if (!_ctx.TryGetTarget(out var ctx) || ctx.IsInvalidated)
{
Dispose();
}
else if (_filter(info))
{
ctx.Invalidate();
EditorApplication.delayCall += SceneView.RepaintAll;
Dispose();
}
}
}

internal class ListenerSet<T>
{
public delegate bool Invokee(object target, T info);
public delegate bool Filter(T info);

private Listener<T> _head;

public ListenerSet()
{
_head = new Listener<T>(this, (object _, T _) => false, null);
_head = new Listener<T>(_ => false, null);
_head._next = _head._prev = _head;
}

Expand All @@ -73,9 +77,9 @@ public bool HasListeners()
return _head._next != _head;
}

public IDisposable Register(Invokee callback, object param)
public IDisposable Register(Filter filter, ComputeContext ctx)
{
var listener = new Listener<T>(this, callback, param);
var listener = new Listener<T>(filter, ctx);

listener._next = _head._next;
listener._prev = _head;
Expand Down
Loading

0 comments on commit a0b6ec3

Please sign in to comment.