Add presenter interfaces and a capability event binder
IAbsorbPresenter/IGrabPresenter/IMeleePresenter/IThrustPresenter let a Unity component declare which capability events it visualizes without knowing about CapabilityEvents itself. CapabilityPresentationBinder is the only thing that subscribes a presenter to its matching stream, resolving a GrabEvent's plain target handle to a live Transform (and initial velocity) through delegates its owner supplies, since the engine-free GrabEvent can't carry a Unity reference. Neither file knows about FieldDriver or any other concrete presentation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
fdea06f27f
commit
450d0731f7
4 changed files with 124 additions and 0 deletions
72
Assets/Scripts/Gameplay/CapabilityPresentationBinder.cs
Normal file
72
Assets/Scripts/Gameplay/CapabilityPresentationBinder.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
|
||||
// Wires one CapabilityEvents source to whatever presenter components live on this object or its
|
||||
// children, subscribing each presenter only to the event kinds it implements (docs/headless-
|
||||
// playground-cut.md fork L: "presentation is chosen per item, independently of capability... one
|
||||
// presentation... can visualize any subset of an item's capabilities"). This binder has no knowledge
|
||||
// of FieldDriver or any other concrete presentation, and no knowledge of what publishes events --
|
||||
// today the FieldShieldTest scene calls Bind() directly; a real capability owner will do the same
|
||||
// later without this binder changing.
|
||||
public class CapabilityPresentationBinder : MonoBehaviour
|
||||
{
|
||||
private readonly List<IDisposable> _subscriptions = new List<IDisposable>();
|
||||
private Func<int, Transform> _grabTargetResolver;
|
||||
private Func<int, Vector3> _grabInitialVelocityResolver;
|
||||
|
||||
// Subscribes every presenter interface implemented by components on this object or its children to
|
||||
// the matching stream of `events`. `grabTargetResolver`/`grabInitialVelocityResolver` resolve a
|
||||
// GrabEvent's plain target handle to the live Transform/velocity a grab presenter needs; the owner
|
||||
// of `events` supplies them (the test scene today; the real pickup capability's caller later).
|
||||
public void Bind(CapabilityEvents events, Func<int, Transform> grabTargetResolver = null,
|
||||
Func<int, Vector3> grabInitialVelocityResolver = null)
|
||||
{
|
||||
Unbind();
|
||||
if (events == null) return;
|
||||
|
||||
_grabTargetResolver = grabTargetResolver;
|
||||
_grabInitialVelocityResolver = grabInitialVelocityResolver;
|
||||
|
||||
foreach (var presenter in GetComponentsInChildren<IAbsorbPresenter>(true))
|
||||
{
|
||||
var p = presenter;
|
||||
_subscriptions.Add(events.Absorb.Subscribe(e => p.Absorb(e)));
|
||||
}
|
||||
|
||||
foreach (var presenter in GetComponentsInChildren<IGrabPresenter>(true))
|
||||
{
|
||||
var p = presenter;
|
||||
_subscriptions.Add(events.Grab.Subscribe(e =>
|
||||
{
|
||||
var target = _grabTargetResolver?.Invoke(e.TargetHandle);
|
||||
var velocity = _grabInitialVelocityResolver?.Invoke(e.TargetHandle) ?? Vector3.zero;
|
||||
p.Grab(e, target, velocity);
|
||||
}));
|
||||
}
|
||||
|
||||
foreach (var presenter in GetComponentsInChildren<IMeleePresenter>(true))
|
||||
{
|
||||
var p = presenter;
|
||||
_subscriptions.Add(events.Melee.Subscribe(e => p.Melee(e)));
|
||||
}
|
||||
|
||||
foreach (var presenter in GetComponentsInChildren<IThrustPresenter>(true))
|
||||
{
|
||||
var p = presenter;
|
||||
_subscriptions.Add(events.Thrust.Subscribe(e => p.Thrust(e)));
|
||||
}
|
||||
}
|
||||
|
||||
public void Unbind()
|
||||
{
|
||||
foreach (var s in _subscriptions) s.Dispose();
|
||||
_subscriptions.Clear();
|
||||
_grabTargetResolver = null;
|
||||
_grabInitialVelocityResolver = null;
|
||||
}
|
||||
|
||||
private void OnDisable() => Unbind();
|
||||
private void OnDestroy() => Unbind();
|
||||
}
|
||||
11
Assets/Scripts/Gameplay/CapabilityPresentationBinder.cs.meta
Normal file
11
Assets/Scripts/Gameplay/CapabilityPresentationBinder.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d8f4aa77146e46a2a4b28d9fefb98496
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
30
Assets/Scripts/Gameplay/CapabilityPresenters.cs
Normal file
30
Assets/Scripts/Gameplay/CapabilityPresenters.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using UnityEngine;
|
||||
|
||||
// Presentation-side contract for the capability events in Assets/Scripts/ServerShared/CapabilityEvents.cs
|
||||
// (docs/headless-playground-cut.md fork L). A presentation implements whichever of these interfaces
|
||||
// match what it visualizes -- one presentation may implement all four (the field shield), or just one
|
||||
// (a dedicated melee-blade effect). CapabilityPresentationBinder is what actually wires a presenter's
|
||||
// method to the matching event stream; a presenter never talks to CapabilityEvents itself.
|
||||
public interface IAbsorbPresenter
|
||||
{
|
||||
void Absorb(AbsorbEvent e);
|
||||
}
|
||||
|
||||
// Grab needs a live Transform to animate, which the engine-free GrabEvent cannot carry (its
|
||||
// TargetHandle is a plain identity, not a Unity reference). The binder resolves the handle through a
|
||||
// delegate supplied by the event source's owner and hands the presenter the result, along with the
|
||||
// initial velocity the target was already moving with (also owner-supplied, for the same reason).
|
||||
public interface IGrabPresenter
|
||||
{
|
||||
void Grab(GrabEvent e, Transform target, Vector3 initialVelocity);
|
||||
}
|
||||
|
||||
public interface IMeleePresenter
|
||||
{
|
||||
void Melee(MeleeEvent e);
|
||||
}
|
||||
|
||||
public interface IThrustPresenter
|
||||
{
|
||||
void Thrust(ThrustEvent e);
|
||||
}
|
||||
11
Assets/Scripts/Gameplay/CapabilityPresenters.cs.meta
Normal file
11
Assets/Scripts/Gameplay/CapabilityPresenters.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 68fda84533414b48ac1722696ddb113d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Reference in a new issue