using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using Decal.Adapter.Support;
using Decal.Interop.Core;
using Decal.Interop.Render;
namespace Decal.Adapter.Wrappers;
[CLSCompliant(true)]
public class HudRenderTarget : MarshalByRefObject, IDisposable
{
private IRenderTarget myTarget;
private bool isDisposed;
private Rectangle areaRect;
private bool inRender;
private bool inText;
public bool Lost => myTarget.Lost;
[EditorBrowsable(EditorBrowsableState.Never)]
public Rectangle Constraint
{
get
{
Rectangle region = Region;
return new Rectangle(0, 0, region.Width, region.Height);
}
}
public Rectangle Region
{
get
{
return Util.toRectangle(myTarget.Region);
}
set
{
tagRECT pVal = Util.toTagRECT(value);
myTarget.Region = ref pVal;
areaRect.Width = value.Width;
areaRect.Height = value.Height;
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public object UnsafeSurface => myTarget.GetSurface();
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public tagRECT UnsafeRegion
{
get
{
return myTarget.Region;
}
set
{
myTarget.Region = ref value;
}
}
protected bool IsDisposed => isDisposed;
[CLSCompliant(false)]
protected HudRenderTarget(IRenderTarget newTarget)
{
if (newTarget == null)
{
throw new ArgumentNullException("newTarget");
}
myTarget = newTarget;
tagRECT region = myTarget.Region;
areaRect = new Rectangle(0, 0, region.right - region.left, region.bottom - region.top);
}
~HudRenderTarget()
{
Dispose(disposing: false);
}
///
/// Begin rendering to this object, must be paired with EndRender
///
public void BeginRender()
{
BeginRender(enableTextureFilter: false);
}
///
/// Begin rendering to this object, must be paired with EndRender
///
/// True to enable texture filtering during rendering
public void BeginRender(bool enableTextureFilter)
{
if (!inRender)
{
myTarget.BeginRender(enableTextureFilter);
inRender = true;
return;
}
throw new RenderViolationException("Cannot call 'BeginRender' when already rendering");
}
///
/// End rendering to this object, must be paired with BeginRender
///
public void EndRender()
{
if (inRender)
{
myTarget.EndRender();
inRender = false;
return;
}
throw new RenderViolationException("Cannot call 'EndRender' without a previous call to 'BeginRender'");
}
///
/// Begin writing text
///
/// Name of the font to use for writing text
/// Height in pixels to use when writing text
public void BeginText(string fontName, int pixelHeight)
{
BeginText(fontName, pixelHeight, FontWeight.Normal, italic: false);
}
///
/// Begin writing text
///
/// Name of the font to use for writing text
/// Height in pixels to use when writing text
/// Bold, Strong, etc, indicator for text to be written
/// Write text in italics?
public void BeginText(string fontName, int pixelHeight, FontWeight weight, bool italic)
{
UnsafeBeginText(fontName, pixelHeight, (int)weight, italic);
}
///
/// Display text,using the full rectangle of the render target as the area.
/// This overload will draw the text in black.
///
/// Text to display
public void WriteText(string text)
{
WriteText(text, Color.Black, WriteTextFormats.None, areaRect);
}
///
/// Display text,using the full rectangle of the render target as the area.
///
/// Text to display
/// Color to use to display the text. (Including alpha channel)
public void WriteText(string text, Color color)
{
WriteText(text, color, WriteTextFormats.None, areaRect);
}
///
/// Display text,using the full rectangle of the render target as the area.
///
/// Text to display
/// Color to use to display the text. (Including alpha channel)
/// Format specifiers, including centered, etc.
/// Rectangle relative to this object to use to bound the text
public void WriteText(string text, Color color, WriteTextFormats format, Rectangle region)
{
UnsafeWriteText(Util.toTagRECT(region), color.ToArgb(), (int)format, text);
}
///
/// Display text,using the full rectangle of the render target as the area.
///
/// Text to display
/// Color to use to display the text. (Including alpha channel)
/// Format specifiers, including centered, etc.
/// Rectangle relative to this object to use to bound the text
public void WriteText(string text, int color, WriteTextFormats format, Rectangle region)
{
UnsafeWriteText(Util.toTagRECT(region), color, (int)format, text);
}
///
/// End drawing of text.
///
public void EndText()
{
if (inRender && inText)
{
myTarget.EndText();
inText = false;
return;
}
throw new RenderViolationException("Cannot call 'EndText' without a previous call to 'BeginText'");
}
public void Clear()
{
Clear(areaRect);
}
public void Clear(Rectangle clearArea)
{
UnsafeClear(Util.toTagRECT(clearArea));
}
public void DrawPortalImage(int portalFile, Rectangle destinationArea)
{
UnsafeDrawPortalImage(portalFile, Util.toTagRECT(destinationArea));
}
public void DrawPortalImage(int portalFile, int alpha, Rectangle srcArea, Rectangle destinationArea)
{
UnsafeDrawPortalImage(portalFile, alpha, Util.toTagRECT(srcArea), Util.toTagRECT(destinationArea));
}
public void DrawPortalImage(int portalFile, Rectangle srcArea, Rectangle destinationArea)
{
UnsafeDrawPortalImage(portalFile, 255, Util.toTagRECT(srcArea), Util.toTagRECT(destinationArea));
}
public void TilePortalImage(int portalFile, Rectangle destinationArea)
{
UnsafeTilePortalImage(portalFile, Util.toTagRECT(destinationArea));
}
public void TilePortalImage(int portalFile, Rectangle srcArea, Rectangle destinationArea)
{
UnsafeTilePortalImage(portalFile, Util.toTagRECT(srcArea), Util.toTagRECT(destinationArea));
}
public void DrawImage(Image image, Rectangle destinationRegion)
{
DrawImage(image, destinationRegion, Color.Cyan.ToArgb());
}
public void DrawImage(Image image, Rectangle destinationRegion, Color colorKey)
{
DrawImage(image, destinationRegion, colorKey.ToArgb());
}
public void DrawImage(Image image, Rectangle destinationRegion, int colorKey)
{
if (image == null)
{
throw new ArgumentNullException("image");
}
MemoryStream memoryStream = new MemoryStream();
image.Save(memoryStream, ImageFormat.Bmp);
byte[] buffer = memoryStream.GetBuffer();
IntPtr zero = IntPtr.Zero;
int num = buffer.Length;
zero = Marshal.AllocCoTaskMem(num);
try
{
Marshal.Copy(buffer, 0, zero, num);
if (zero != IntPtr.Zero)
{
UnsafeDrawImage(zero, num, Util.toTagRECT(destinationRegion), colorKey);
}
}
finally
{
Marshal.FreeCoTaskMem(zero);
memoryStream.Dispose();
}
}
public void Fill(Color color)
{
Fill(areaRect, color);
}
public void Fill(Rectangle fillArea, Color color)
{
Fill(fillArea, color.ToArgb());
}
public void Fill(Rectangle fillArea, int color)
{
UnsafeFill(Util.toTagRECT(fillArea), color);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeBeginText(string fontName, int pixelHeight, int weight, bool italic)
{
if (inRender && !inText)
{
myTarget.BeginText(fontName, pixelHeight, weight, italic);
inText = true;
return;
}
if (inRender && inText)
{
throw new RenderViolationException("Cannot call 'BeginText' when already rendering text");
}
throw new RenderViolationException("Cannot call 'BeginText' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeWriteText(tagRECT region, int color, int format, string text)
{
if (inRender && inText)
{
myTarget.WriteText(ref region, color, format, text);
return;
}
throw new RenderViolationException("Cannot call 'WriteText' outside of a BeginText/EndText block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeClear(tagRECT clearArea)
{
if (!inRender)
{
myTarget.Clear(ref clearArea);
return;
}
throw new RenderViolationException("MUST call 'Clear' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeDrawPortalImage(int portalFile, tagRECT destinationArea)
{
if (inRender)
{
myTarget.DrawPortalImage(portalFile, ref destinationArea);
return;
}
throw new RenderViolationException("Cannot call 'DrawPortalImage' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeDrawPortalImage(int portalFile, int alpha, tagRECT srcArea, tagRECT destinationArea)
{
if (inRender)
{
myTarget.DrawPortalImageEx(portalFile, alpha, ref srcArea, ref destinationArea);
return;
}
throw new RenderViolationException("Cannot call 'DrawPortalImageEx' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeTilePortalImage(int portalFile, tagRECT destinationArea)
{
if (inRender)
{
myTarget.TilePortalImage(portalFile, ref destinationArea);
return;
}
throw new RenderViolationException("Cannot call 'TilePortalImage' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeTilePortalImage(int portalFile, tagRECT srcArea, tagRECT destinationArea)
{
if (inRender)
{
myTarget.TilePortalImageEx(portalFile, ref srcArea, ref destinationArea);
return;
}
throw new RenderViolationException("Cannot call 'TilePortalImageEx' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeDrawImage(IntPtr buffer, int size, tagRECT destinationRegion, int colorKey)
{
if (inRender)
{
myTarget.DrawImage((int)buffer, size, ref destinationRegion, colorKey);
return;
}
throw new RenderViolationException("Cannot call 'DrawImage' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeFill(tagRECT fillArea, int color)
{
if (!inRender)
{
myTarget.Fill(ref fillArea, color);
return;
}
throw new RenderViolationException("MUST call 'Fill' outside of a BeginRender/EndRender block");
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeSetSurface(object pSurface)
{
myTarget.SetSurface(pSurface);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
}
if (myTarget != null)
{
Marshal.ReleaseComObject(myTarget);
}
myTarget = null;
isDisposed = true;
}
}