#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