using System; using System.ComponentModel; using System.Drawing; using System.Runtime.InteropServices; using Decal.Adapter.Support; using Decal.Interop.Core; using Decal.Interop.Inject; using Decal.Interop.Render; namespace Decal.Adapter.Wrappers; /// /// RenderServiceWrapper is a wrapper for RenderService /// [CLSCompliant(true)] public class RenderServiceWrapper : MarshalByRefObject, IDisposable { private RenderService internalRender; private bool isDisposed; private EventHandler myDeviceLost; [EditorBrowsable(EditorBrowsableState.Never)] public object UnsafeDevice => internalRender.Device; internal event EventHandler DeviceLost { add { myDeviceLost = (EventHandler)Delegate.Combine(myDeviceLost, value); } remove { myDeviceLost = (EventHandler)Delegate.Combine(myDeviceLost, value); } } internal RenderServiceWrapper(RenderService render) { internalRender = render; internalRender.DeviceLost += internalRender_DeviceLost; } ~RenderServiceWrapper() { Dispose(disposing: false); } private void internalRender_DeviceLost() { if (myDeviceLost != null) { myDeviceLost(this, new EventArgs()); } } private void myHUD_Disposing(object sender, EventArgs e) { if (sender is Hud hud) { RemoveHud(hud); hud.Disposing -= myHUD_Disposing; } } /// /// Create a new Background object to be used as a background in HUDS /// /// The rectangle to use for the size of the background /// Newly created and wrapped RenderService.HUDBackground public Background CreateBackground(Rectangle region) { return UnsafeCreateBackground(Util.toTagRECT(region)); } /// /// Create a new HUD. New huds need to be made visible before they render. /// /// Size and location of where the HUD should be rendered /// Newly created and wrapped RenderService.HUDView public Hud CreateHud(Rectangle region) { return UnsafeCreateHud(Util.toTagRECT(region)); } /// /// Remove a HUD from the render pipeline /// /// HUD To remove public void RemoveHud(Hud hud) { if (hud == null) { throw new ArgumentNullException("hud"); } internalRender.RemoveHUD(hud.Underlying); } [CLSCompliant(false)] [EditorBrowsable(EditorBrowsableState.Never)] public Background UnsafeCreateBackground(tagRECT pRegion) { return new Background(internalRender.CreateBackground(ref pRegion)); } [CLSCompliant(false)] [EditorBrowsable(EditorBrowsableState.Never)] public Hud UnsafeCreateHud(tagRECT pRegion) { Hud hud = new Hud(internalRender.CreateHUD(ref pRegion)); hud.Disposing += myHUD_Disposing; return hud; } [CLSCompliant(false)] [EditorBrowsable(EditorBrowsableState.Never)] public Background EncapsulateBackground(tagPOINT coordinates, object surface) { return new Background(internalRender.EncapsulateBackground(ref coordinates, surface)); } [CLSCompliant(false)] [EditorBrowsable(EditorBrowsableState.Never)] public Hud EncapsulateHud(tagPOINT coordinates, object surface) { return new Hud(internalRender.EncapsulateHUD(ref coordinates, surface)); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!isDisposed && disposing) { internalRender.DeviceLost -= internalRender_DeviceLost; } if (internalRender != null) { Marshal.ReleaseComObject(internalRender); } internalRender = null; isDisposed = true; } }