|
- using RenderHookAPI.Hook.Common;
- using SharpDX;
- using SharpDX.Direct3D9;
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
-
- namespace RenderHookAPI.Hook.DX9
- {
- internal class DXOverlayEngine : Component
- {
- public List<IOverlay> Overlays { get; set; }
-
- bool _initialised = false;
- bool _initialising = false;
-
- Device _device;
- Sprite _sprite;
- Dictionary<string, Font> _fontCache = new Dictionary<string, Font>();
- Dictionary<Element, Texture> _imageCache = new Dictionary<Element, Texture>();
-
- public Device Device { get { return _device; } }
-
- public DXOverlayEngine()
- {
- Overlays = new List<IOverlay>();
- }
-
- private void EnsureInitiliased()
- {
- Debug.Assert(_initialised);
- }
-
- public bool Initialise(Device device)
- {
- Debug.Assert(!_initialised);
- if (_initialising)
- return false;
-
- _initialising = true;
-
- try
- {
-
- _device = device;
-
- _sprite = ToDispose(new Sprite(_device));
-
- // Initialise any resources required for overlay elements
- IntialiseElementResources();
-
- _initialised = true;
- return true;
- }
- finally
- {
- _initialising = false;
- }
- }
-
- private void IntialiseElementResources()
- {
- foreach (var overlay in Overlays)
- {
- foreach (var element in overlay.Elements)
- {
- var textElement = element as TextElement;
- var imageElement = element as ImageElement;
-
- if (textElement != null)
- {
- GetFontForTextElement(textElement);
- }
- else if (imageElement != null)
- {
- GetImageForImageElement(imageElement);
- }
- }
- }
- }
-
- private void Begin()
- {
- _sprite.Begin(SpriteFlags.AlphaBlend);
- }
-
- /// <summary>
- /// Draw the overlay(s)
- /// </summary>
- public void Draw()
- {
- EnsureInitiliased();
-
- Begin();
-
- foreach (var overlay in Overlays)
- {
- foreach (var element in overlay.Elements)
- {
- if (element.Hidden)
- continue;
-
- var textElement = element as TextElement;
- var imageElement = element as ImageElement;
-
- if (textElement != null)
- {
- Font font = GetFontForTextElement(textElement);
- if (font != null && !String.IsNullOrEmpty(textElement.Text))
- font.DrawText(_sprite, textElement.Text, textElement.Location.X, textElement.Location.Y, new SharpDX.ColorBGRA(textElement.Color.R, textElement.Color.G, textElement.Color.B, textElement.Color.A));
- }
- else if (imageElement != null)
- {
- //Apply the scaling of the imageElement
- var rotation = Matrix.RotationZ(imageElement.Angle);
- var scaling = Matrix.Scaling(imageElement.Scale);
- _sprite.Transform = rotation * scaling;
-
- Texture image = GetImageForImageElement(imageElement);
- if (image != null)
- _sprite.Draw(image, new SharpDX.ColorBGRA(imageElement.Tint.R, imageElement.Tint.G, imageElement.Tint.B, imageElement.Tint.A), null, null, new Vector3(imageElement.Location.X, imageElement.Location.Y, 0));
-
- //Reset the transform for other elements
- _sprite.Transform = Matrix.Identity;
- }
- }
- }
-
- End();
- }
-
- private void End()
- {
- _sprite.End();
- }
-
- /// <summary>
- /// In Direct3D9 it is necessary to call OnLostDevice before any call to device.Reset(...) for certain interfaces found in D3DX (e.g. ID3DXSprite, ID3DXFont, ID3DXLine) - https://msdn.microsoft.com/en-us/library/windows/desktop/bb172979(v=vs.85).aspx
- /// </summary>
- public void BeforeDeviceReset()
- {
- try
- {
- foreach (var item in _fontCache)
- item.Value.OnLostDevice();
-
- if (_sprite != null)
- _sprite.OnLostDevice();
- }
- catch { }
- }
-
- Font GetFontForTextElement(TextElement element)
- {
- Font result = null;
-
- string fontKey = String.Format("{0}{1}{2}{3}", element.Font.Name, element.Font.Size, element.Font.Style, element.AntiAliased);
-
- if (!_fontCache.TryGetValue(fontKey, out result))
- {
- result = ToDispose(new Font(_device, new FontDescription {
- FaceName = element.Font.Name,
- Italic = (element.Font.Style & System.Drawing.FontStyle.Italic) == System.Drawing.FontStyle.Italic,
- Quality = (element.AntiAliased ? FontQuality.Antialiased : FontQuality.Default),
- Weight = ((element.Font.Style & System.Drawing.FontStyle.Bold) == System.Drawing.FontStyle.Bold) ? FontWeight.Bold : FontWeight.Normal,
- Height = (int)element.Font.SizeInPoints
- }));
- _fontCache[fontKey] = result;
- }
- return result;
- }
-
- Texture GetImageForImageElement(ImageElement element)
- {
- Texture result = null;
-
- if (!String.IsNullOrEmpty(element.Filename))
- {
- if (!_imageCache.TryGetValue(element, out result))
- {
- result = ToDispose(SharpDX.Direct3D9.Texture.FromFile(_device, element.Filename));
-
- _imageCache[element] = result;
- }
- }
- else if (!_imageCache.TryGetValue(element, out result) && element.Bitmap != null)
- {
- using (var ms = new MemoryStream())
- {
- element.Bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
- ms.Seek(0, SeekOrigin.Begin);
- result = ToDispose(Texture.FromStream(Device, ms));
- }
-
- _imageCache[element] = result;
- }
- return result;
- }
-
- /// <summary>
- /// Releases unmanaged and optionally managed resources
- /// </summary>
- /// <param name="disposing">true if disposing both unmanaged and managed</param>
- protected override void Dispose(bool disposing)
- {
- if (true)
- {
- _device = null;
- }
-
- base.Dispose(disposing);
- }
-
- void SafeDispose(DisposeBase disposableObj)
- {
- if (disposableObj != null)
- disposableObj.Dispose();
- }
-
- }
- }
|