using Editor.PluginInterface;
using HmEG;
using Recordingtest.Bridge;
using Recordingtest.Hmeg.Bridge;
namespace Recordingtest.Sut.EgBim.PluginHost;
///
/// MEF/PluginLoader-discovered plugin. Inherits the SUT's EditorPlugin
/// abstract base (which itself implements HmEG.IPlugin), and on construction
/// boots a localhost HTTP bridge that exposes HmEG state to recordingtest.
///
public sealed class HmEgBridgePlugin : EditorPlugin, IDisposable
{
private BridgeHttpServer? _server;
public HmEgBridgePlugin()
{
StartBridge();
}
public override string Name => "Recordingtest.Sut.EgBim.PluginHost";
public override string Description => "recordingtest engine-bridge v3 (HTTP sidecar)";
protected override void Initialize()
{
// Construction already started the bridge; Initialize is a no-op safeguard.
}
private void StartBridge()
{
try
{
var port = PortResolver.Resolve();
var provider = BuildProvider();
var router = new StateRouter(provider, port);
_server = new BridgeHttpServer(router, port);
_server.Start();
}
catch
{
// never throw out of plugin construction; SUT must remain stable.
}
}
///
/// Choose the best available :
///
/// 1. HmegDirectStateProvider — HmEG-aware tier, calls into HmEG
/// public API. Reusable across any HmEG-hosting WPF app. Active
/// space/viewport handles are resolved via lambdas; the EgBim
/// app-specific entry-point lookup lives in this method only.
/// 2. ReflectionEngineStateProvider — fallback that uses
/// IAppManagerAccessor reflection on Editor.AppManager.AppManager.
/// Used when the direct provider can't resolve any handle.
///
/// Both providers are wrapped to never throw; the SUT must remain stable.
///
private IEngineStateProvider BuildProvider()
{
// EG-BIM Modeler entry points (resolved via EditorPlugin base):
// RootSpace = AppManager.ViewportManager.RootSpace
// View (EGViewport : HmEGViewport) — plugin-injected active viewport
// AppManager.FileManager.CurrentFile — document path on disk
//
// Each lambda is wrapped in try/catch so plugin construction never
// throws even if the host state is in flight at boot time.
Func spaceProvider = () =>
{
try { return RootSpace; }
catch { return null; }
};
Func viewportProvider = () =>
{
try
{
// EGViewport implements HmEGViewport; the base class exposes it
// as EGViewport on the Obsolete View property. We catch and
// return null to survive the obsolete warning at runtime.
#pragma warning disable CS0618 // Obsolete API on EditorPlugin.View
return View;
#pragma warning restore CS0618
}
catch { return null; }
};
Func documentPathProvider = () =>
{
try
{
var path = AppManager?.FileManager?.CurrentFile;
return string.IsNullOrEmpty(path) ? null : path;
}
catch { return null; }
};
var direct = new HmegDirectStateProvider(spaceProvider, viewportProvider, documentPathProvider);
var fallback = new ReflectionEngineStateProvider(this);
return new ChainedEngineStateProvider(direct, fallback);
}
public void Dispose()
{
try { _server?.Dispose(); } catch { }
_server = null;
}
}