#if UGX_BRIDGE || UNITY_EDITOR
using System;
using System.Collections.Generic;
using Uigenx.Actions;
using Uigenx.Protocol;
namespace Uigenx.Bridge
{
///
/// Bridges the action bus both ways: `action.emit` from the studio raises an action in the
/// game, and every action the game raises is reported as `action.fired`.
///
public sealed class UgxActionHandler : IDisposable
{
readonly UgxBridgeClient _client;
readonly IDisposable _subscription;
bool _emittingFromDaemon;
bool _disposed;
public UgxActionHandler(UgxBridgeClient client)
{
_client = client ?? throw new ArgumentNullException(nameof(client));
client.Register(UgxMessageTypes.ActionEmit, OnEmit);
_subscription = UgxActionBus.SubscribeAll(OnBusAction);
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
_client.Unregister(UgxMessageTypes.ActionEmit);
_subscription.Dispose();
}
void OnEmit(UgxEnvelope envelope)
{
var body = envelope.BodyAs();
if (string.IsNullOrEmpty(body.Action))
{
_client.SendError(UgxErrorCodes.BadRequest, "action.emit needs an action name", envelope.Id);
return;
}
var payload = body.Payload != null && body.Payload.Count > 0
? new UgxActionPayload(new Dictionary(body.Payload))
: default;
// Without this the action we just raised would be reported straight back as `action.fired`.
_emittingFromDaemon = true;
try
{
UgxActionBus.Emit(new UgxAction(body.Action, payload));
}
finally
{
_emittingFromDaemon = false;
}
}
void OnBusAction(UgxAction action)
{
if (_disposed || _emittingFromDaemon) return;
var fired = new UgxActionFired
{
Action = action.Name,
Screen = action.Screen,
NodeId = action.NodeId,
Source = UgxActionSource.Ui,
};
foreach (var pair in action.Payload) fired.Payload[pair.Key] = pair.Value;
_client.Send(UgxMessageTypes.ActionFired, fired);
}
}
}
#endif