-
Notifications
You must be signed in to change notification settings - Fork 176
/
DXOverlayEngine.cs
225 lines (191 loc) · 7.1 KB
/
DXOverlayEngine.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Capture.Hook.Common;
using SharpDX.Direct3D11;
using SharpDX;
using System.Diagnostics;
namespace Capture.Hook.DX11
{
internal class DXOverlayEngine: Component
{
public List<IOverlay> Overlays { get; set; }
public bool DeferredContext
{
get
{
return _deviceContext.TypeInfo == DeviceContextType.Deferred;
}
}
bool _initialised = false;
bool _initialising = false;
Device _device;
DeviceContext _deviceContext;
Texture2D _renderTarget;
RenderTargetView _renderTargetView;
DXSprite _spriteEngine;
Dictionary<string, DXFont> _fontCache = new Dictionary<string, DXFont>();
Dictionary<Element, DXImage> _imageCache = new Dictionary<Element, DXImage>();
public DXOverlayEngine()
{
Overlays = new List<IOverlay>();
}
private void EnsureInitiliased()
{
if (!_initialised)
throw new InvalidOperationException("DXOverlayEngine must be initialised.");
}
public bool Initialise(SharpDX.DXGI.SwapChain swapChain)
{
return Initialise(swapChain.GetDevice<Device>(), swapChain.GetBackBuffer<Texture2D>(0));
}
public bool Initialise(Device device, Texture2D renderTarget)
{
if (_initialising)
return false;
_initialising = true;
try
{
_device = device;
_renderTarget = renderTarget;
try
{
_deviceContext = ToDispose(new DeviceContext(_device));
}
catch (SharpDXException)
{
_deviceContext = _device.ImmediateContext;
}
_renderTargetView = ToDispose(new RenderTargetView(_device, _renderTarget));
//if (DeferredContext)
//{
// ViewportF[] viewportf = { new ViewportF(0, 0, _renderTarget.Description.Width, _renderTarget.Description.Height, 0, 1) };
// _deviceContext.Rasterizer.SetViewports(viewportf);
// _deviceContext.OutputMerger.SetTargets(_renderTargetView);
//}
_spriteEngine = ToDispose(new DXSprite(_device, _deviceContext));
if (!_spriteEngine.Initialize())
return false;
// Initialise any resources required for overlay elements
InitialiseElementResources();
_initialised = true;
return true;
}
finally
{
_initialising = false;
}
}
void InitialiseElementResources()
{
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()
{
//if (!DeferredContext)
//{
SharpDX.Mathematics.Interop.RawViewportF[] viewportf = { new ViewportF(0, 0, _renderTarget.Description.Width, _renderTarget.Description.Height, 0, 1) };
_deviceContext.Rasterizer.SetViewports(viewportf);
_deviceContext.OutputMerger.SetTargets(_renderTargetView);
//}
}
/// <summary>
/// Draw the overlay(s)
/// </summary>
public void Draw()
{
EnsureInitiliased();
Begin();
foreach (var overlay in Overlays)
{
if (overlay.Hidden)
continue;
foreach (var element in overlay.Elements)
{
if (element.Hidden)
continue;
var textElement = element as TextElement;
var imageElement = element as ImageElement;
if (textElement != null)
{
DXFont font = GetFontForTextElement(textElement);
if (font != null && !String.IsNullOrEmpty(textElement.Text))
_spriteEngine.DrawString(textElement.Location.X, textElement.Location.Y, textElement.Text, textElement.Color, font);
}
else if (imageElement != null)
{
DXImage image = GetImageForImageElement(imageElement);
if (image != null)
_spriteEngine.DrawImage(imageElement.Location.X, imageElement.Location.Y, imageElement.Scale, imageElement.Angle, imageElement.Tint, image);
}
}
}
End();
}
private void End()
{
if (DeferredContext)
{
var commandList = _deviceContext.FinishCommandList(true);
_device.ImmediateContext.ExecuteCommandList(commandList, true);
commandList.Dispose();
}
}
DXFont GetFontForTextElement(TextElement element)
{
DXFont 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 DXFont(_device, _deviceContext));
result.Initialize(element.Font.Name, element.Font.Size, element.Font.Style, element.AntiAliased);
_fontCache[fontKey] = result;
}
return result;
}
DXImage GetImageForImageElement(ImageElement element)
{
DXImage result = null;
if (!_imageCache.TryGetValue(element, out result))
{
result = ToDispose(new DXImage(_device, _deviceContext));
result.Initialise(element.Bitmap);
_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();
}
}
}