A UI ScenePanel subclass used by the Goo UI system that hosts stateful visual variants and mouse event handlers. It stores a StateController, exposes methods to apply/clear visual state variants, accepts event delegates from a BlobEvents payload, and forwards engine mouse events to those delegates via EventDispatch helper calls.
using System;
using Sandbox;
using Sandbox.UI;
namespace Goo.Internal;
internal sealed class StatefulScenePanel : Sandbox.UI.ScenePanel, IStatefulHost, IStatefulEventHost
{
StateController? _state;
internal Action<MousePanelEvent>? _onClick;
internal Action<MousePanelEvent>? _onRightClick;
internal Action<MousePanelEvent>? _onMiddleClick;
internal Action<MousePanelEvent>? _onMouseEnter;
internal Action<MousePanelEvent>? _onMouseLeave;
bool _hoverInside; // gates true enter/leave over the engine's bubbling over/out
internal Action<MousePanelEvent>? _onMouseDown;
internal Action<MousePanelEvent>? _onMouseUp;
internal Action<MousePanelEvent>? _onMouseMove;
internal bool _userSetPointerEvents;
internal Action? _requestRebuild;
public Action? RequestRebuild { set => _requestRebuild = value; }
// Parameterless ctor: scene-ref payload path; Applier assigns RenderScene afterward.
public StatefulScenePanel() { }
// String-ctor: ScenePath payload path; engine constructs + owns the scene via SceneLoadOptions.
public StatefulScenePanel(string sceneFilename) : base(sceneFilename) { }
// No camera handling here: the engine ScenePanel renders the scene through its authored Main Camera natively.
public void ApplyStateVariants(
Color? baseBg, Color? baseFg,
Color? hoverBg, Color? activeBg, Color? focusBg,
Color? hoverFg, Color? activeFg, Color? focusFg,
int? transitionMs)
{
_state ??= new StateController(this);
_state.ApplyVariants(
baseBg, baseFg,
hoverBg, activeBg, focusBg,
hoverFg, activeFg, focusFg,
transitionMs);
}
public void ClearStateVariants() => _state?.ClearVariants();
public bool HasActiveStateVariants => _state?.HasActiveVariants ?? false;
public void ApplyEvents(in BlobEvents events)
{
_onClick = events.OnClick;
_onRightClick = events.OnRightClick;
_onMiddleClick = events.OnMiddleClick;
_onMouseEnter = events.OnMouseEnter;
_onMouseLeave = events.OnMouseLeave;
_onMouseDown = events.OnMouseDown;
_onMouseUp = events.OnMouseUp;
_onMouseMove = events.OnMouseMove;
}
public bool HasEventHandlers =>
_onClick != null || _onRightClick != null || _onMiddleClick != null || _onMouseEnter != null || _onMouseLeave != null ||
_onMouseDown != null || _onMouseUp != null || _onMouseMove != null;
public bool UserSetPointerEvents
{
get => _userSetPointerEvents;
set => _userSetPointerEvents = value;
}
protected override void OnClick(MousePanelEvent e)
{
base.OnClick(e);
EventDispatch.Fire(_onClick, e, _requestRebuild);
}
protected override void OnRightClick(MousePanelEvent e)
{
base.OnRightClick(e);
EventDispatch.Fire(_onRightClick, e, _requestRebuild);
}
protected override void OnMiddleClick(MousePanelEvent e)
{
base.OnMiddleClick(e);
EventDispatch.Fire(_onMiddleClick, e, _requestRebuild);
}
protected override void OnMouseOver(MousePanelEvent e)
{
base.OnMouseOver(e);
EventDispatch.FireEnter(ref _hoverInside, _onMouseEnter, e, _requestRebuild);
}
protected override void OnMouseOut(MousePanelEvent e)
{
base.OnMouseOut(e);
EventDispatch.FireLeave(this, ref _hoverInside, _onMouseLeave, e, _requestRebuild);
}
protected override void OnMouseDown(MousePanelEvent e)
{
base.OnMouseDown(e);
EventDispatch.Fire(_onMouseDown, e, _requestRebuild);
}
protected override void OnMouseUp(MousePanelEvent e)
{
base.OnMouseUp(e);
EventDispatch.Fire(_onMouseUp, e, _requestRebuild);
}
protected override void OnMouseMove(MousePanelEvent e)
{
base.OnMouseMove(e);
EventDispatch.Fire(_onMouseMove, e, _requestRebuild);
}
}