diff --git a/TrueCraft.Client/Rendering/ChunkMesh.cs b/TrueCraft.Client/Rendering/ChunkMesh.cs
index 26b934b..3ed766a 100644
--- a/TrueCraft.Client/Rendering/ChunkMesh.cs
+++ b/TrueCraft.Client/Rendering/ChunkMesh.cs
@@ -29,6 +29,23 @@ namespace TrueCraft.Client.Rendering
Vertices = vertices;
SetSubmesh(0, indices);
}
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ChunkMesh(ReadOnlyChunk chunk, GraphicsDevice device, VertexPositionNormalTexture[] vertices, int[] opaqueIndices, int[] transparentIndices)
+ : base(device, 2, true)
+ {
+ Chunk = chunk;
+ Vertices = vertices;
+ SetSubmesh(0, opaqueIndices);
+ SetSubmesh(1, transparentIndices);
+ }
///
///
diff --git a/TrueCraft.Client/Rendering/ChunkRenderer.cs b/TrueCraft.Client/Rendering/ChunkRenderer.cs
index accd367..69e1259 100644
--- a/TrueCraft.Client/Rendering/ChunkRenderer.cs
+++ b/TrueCraft.Client/Rendering/ChunkRenderer.cs
@@ -19,7 +19,7 @@ namespace TrueCraft.Client.Rendering
/// A daemon of sorts that creates meshes from chunks.
/// Passing meshes back is NOT thread-safe.
///
- public class ChunkRenderer
+ public class ChunkRenderer : Renderer
{
public class ChunkSorter : Comparer
{
@@ -39,85 +39,16 @@ namespace TrueCraft.Client.Rendering
}
}
- public class MeshGeneratedEventArgs : EventArgs
- {
- public bool Transparent { get; set; }
- public ChunkMesh Mesh { get; set; }
-
- public MeshGeneratedEventArgs(ChunkMesh mesh, bool transparent)
- {
- Transparent = transparent;
- Mesh = mesh;
- }
- }
-
- public event EventHandler MeshGenerated;
-
- private ConcurrentQueue ChunkQueue { get; set; }
private GraphicsDevice GraphicsDevice { get; set; }
private IBlockRepository BlockRepository { get; set; }
- private List> RenderThreads { get; set; }
public ChunkRenderer(GraphicsDevice graphics, IBlockRepository blockRepository)
+ : base()
{
- ChunkQueue = new ConcurrentQueue();
- RenderThreads = new List>();
- var threads = Environment.ProcessorCount - 2;
- if (threads < 1)
- threads = 1;
- for (int i = 0; i < threads; i++)
- {
- var token = new CancellationTokenSource();
- var worker = new Thread(() => DoChunks(token));
- worker.IsBackground = true;
- RenderThreads.Add(new Tuple(worker, token));
- }
-
BlockRepository = blockRepository;
GraphicsDevice = graphics;
}
- public void QueueChunk(ReadOnlyChunk chunk)
- {
- ChunkQueue.Enqueue(chunk);
- }
-
- public void QueueHighPriorityChunk(ReadOnlyChunk chunk)
- {
- // TODO: Overwrite existing chunks
- Task.Factory.StartNew(() =>
- {
- ProcessChunk(chunk, new RenderState());
- });
- }
-
- public void Start()
- {
- RenderThreads.ForEach(t => t.Item1.Start());
- }
-
- public void Stop()
- {
- RenderThreads.ForEach(t => t.Item2.Cancel());
- }
-
- private void DoChunks(CancellationTokenSource token)
- {
- var state = new RenderState();
- while (true)
- {
- if (token.Token.IsCancellationRequested)
- return;
-
- ReadOnlyChunk chunk;
- if (ChunkQueue.TryDequeue(out chunk))
- {
- ProcessChunk(chunk, state);
- }
- Thread.Sleep(1);
- }
- }
-
private static readonly Coordinates3D[] AdjacentCoordinates =
{
Coordinates3D.Up,
@@ -128,20 +59,30 @@ namespace TrueCraft.Client.Rendering
Coordinates3D.West
};
+ protected override bool TryRender(ReadOnlyChunk item, out Mesh result)
+ {
+ var state = new RenderState();
+ ProcessChunk(item, state);
+
+ result = new ChunkMesh(item, GraphicsDevice, state.Verticies.ToArray(),
+ state.OpaqueIndicies.ToArray(), state.TransparentIndicies.ToArray());
+
+ return (result != null);
+
+ }
+
private class RenderState
{
- public readonly List OpaqueVerticies = new List();
+ public readonly List Verticies = new List();
public readonly List OpaqueIndicies = new List();
- public readonly List TransparentVerticies = new List();
public readonly List TransparentIndicies = new List();
public readonly HashSet DrawableCoordinates = new HashSet();
}
private void ProcessChunk(ReadOnlyChunk chunk, RenderState state)
{
- state.OpaqueVerticies.Clear();
+ state.Verticies.Clear();
state.OpaqueIndicies.Clear();
- state.TransparentVerticies.Clear();
state.TransparentIndicies.Clear();
state.DrawableCoordinates.Clear();
@@ -198,8 +139,8 @@ namespace TrueCraft.Client.Rendering
int[] i;
var v = BlockRenderer.RenderBlock(provider, descriptor,
new Vector3(chunk.X * Chunk.Width + coords.X, coords.Y, chunk.Z * Chunk.Depth + coords.Z),
- state.OpaqueVerticies.Count, out i);
- state.OpaqueVerticies.AddRange(v);
+ state.Verticies.Count, out i);
+ state.Verticies.AddRange(v);
state.OpaqueIndicies.AddRange(i);
}
else
@@ -207,18 +148,11 @@ namespace TrueCraft.Client.Rendering
int[] i;
var v = BlockRenderer.RenderBlock(provider, descriptor,
new Vector3(chunk.X * Chunk.Width + coords.X, coords.Y, chunk.Z * Chunk.Depth + coords.Z),
- state.TransparentVerticies.Count, out i);
- state.TransparentVerticies.AddRange(v);
+ state.Verticies.Count, out i);
+ state.Verticies.AddRange(v);
state.TransparentIndicies.AddRange(i);
}
}
- var opaque = new ChunkMesh(chunk, GraphicsDevice, state.OpaqueVerticies.ToArray(), state.OpaqueIndicies.ToArray());
- var transparent = new ChunkMesh(chunk, GraphicsDevice, state.TransparentVerticies.ToArray(), state.TransparentIndicies.ToArray());
- if (MeshGenerated != null)
- {
- MeshGenerated(this, new MeshGeneratedEventArgs(opaque, false));
- MeshGenerated(this, new MeshGeneratedEventArgs(transparent, true));
- }
}
}
}
diff --git a/TrueCraft.Client/Rendering/Renderer.cs b/TrueCraft.Client/Rendering/Renderer.cs
new file mode 100644
index 0000000..8591742
--- /dev/null
+++ b/TrueCraft.Client/Rendering/Renderer.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Threading;
+using System.Collections.Concurrent;
+
+namespace TrueCraft.Client.Rendering
+{
+ ///
+ /// Abstract base class for renderers of meshes.
+ ///
+ /// The object to render into a mesh.
+ public abstract class Renderer : IDisposable
+ {
+ private readonly object _syncLock =
+ new object();
+
+ ///
+ ///
+ ///
+ public event EventHandler> MeshCompleted;
+
+ private volatile bool _isRunning;
+ private Thread _rendererThread;
+ private ConcurrentQueue _items, _priorityItems;
+ private volatile bool _isDisposed;
+
+ ///
+ /// Gets whether this renderer is running.
+ ///
+ public bool IsRunning
+ {
+ get
+ {
+ if (_isDisposed)
+ throw new ObjectDisposedException(GetType().Name);
+ return _isRunning;
+ }
+ }
+
+ ///
+ /// Gets whether this renderer is disposed of.
+ ///
+ public bool IsDisposed
+ {
+ get { return _isDisposed; }
+ }
+
+ ///
+ ///
+ ///
+ protected Renderer()
+ {
+ lock (_syncLock)
+ {
+ _isRunning = false;
+ _rendererThread = new Thread(DoRendering);
+ _items = new ConcurrentQueue(); _priorityItems = new ConcurrentQueue();
+ _isDisposed = false;
+ }
+ }
+
+ ///
+ /// Starts this renderer.
+ ///
+ public void Start()
+ {
+ if (_isDisposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (_isRunning) return;
+ lock (_syncLock)
+ {
+ _isRunning = true;
+ _rendererThread.Start(null);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ private void DoRendering(object obj)
+ {
+ while (_isRunning)
+ {
+ var item = default(T);
+ var result = default(Mesh);
+
+ lock (_syncLock)
+ {
+ if (_priorityItems.TryDequeue(out item) && TryRender(item, out result))
+ {
+ var args = new RendererEventArgs(item, result, true);
+ if (MeshCompleted != null)
+ MeshCompleted(this, args);
+ }
+ else if (_items.TryDequeue(out item) && TryRender(item, out result))
+ {
+ var args = new RendererEventArgs(item, result, false);
+ if (MeshCompleted != null)
+ MeshCompleted(this, args);
+ }
+ }
+
+ if (item == null) // We don't have any work, so sleep for a bit.
+ Thread.Sleep(100);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected abstract bool TryRender(T item, out Mesh result);
+
+ ///
+ /// Stops this renderer.
+ ///
+ public void Stop()
+ {
+ if (_isDisposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!_isRunning) return;
+ lock (_syncLock)
+ {
+ _isRunning = false;
+ _rendererThread.Join();
+ }
+ }
+
+ ///
+ /// Enqueues an item to this renderer for rendering.
+ ///
+ ///
+ ///
+ public void Enqueue(T item, bool hasPriority = false)
+ {
+ if (_isDisposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!_isRunning) return;
+ lock (_syncLock)
+ {
+ if (hasPriority)
+ _priorityItems.Enqueue(item);
+ else
+ _items.Enqueue(item);
+ }
+ }
+
+ ///
+ /// Disposes of this renderer.
+ ///
+ public void Dispose()
+ {
+ if (_isDisposed)
+ return;
+
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Disposes of this renderer.
+ ///
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ Stop();
+ lock (_syncLock)
+ {
+ _rendererThread = null;
+ _items = null; _priorityItems = null;
+ _isDisposed = true;
+ }
+ }
+ else
+ throw new NotSupportedException(); // We should 'encourage' developers to dispose of renderers properly.
+ }
+
+ ///
+ /// Finalizes this renderer.
+ ///
+ ~Renderer()
+ {
+ Dispose(false);
+ }
+ }
+}
diff --git a/TrueCraft.Client/Rendering/RendererEventArgs.cs b/TrueCraft.Client/Rendering/RendererEventArgs.cs
new file mode 100644
index 0000000..f14ff60
--- /dev/null
+++ b/TrueCraft.Client/Rendering/RendererEventArgs.cs
@@ -0,0 +1,39 @@
+using System;
+
+namespace TrueCraft.Client.Rendering
+{
+ ///
+ ///
+ ///
+ ///
+ public sealed class RendererEventArgs : EventArgs
+ {
+ ///
+ ///
+ ///
+ public T Item { get; private set; }
+
+ ///
+ ///
+ ///
+ public Mesh Result { get; private set; }
+
+ ///
+ ///
+ ///
+ public bool IsPriority { get; private set; }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public RendererEventArgs(T item, Mesh result, bool isPriority)
+ {
+ Item = item;
+ Result = result;
+ IsPriority = isPriority;
+ }
+ }
+}
diff --git a/TrueCraft.Client/TrueCraft.Client.csproj b/TrueCraft.Client/TrueCraft.Client.csproj
index 0be89e5..44d881a 100644
--- a/TrueCraft.Client/TrueCraft.Client.csproj
+++ b/TrueCraft.Client/TrueCraft.Client.csproj
@@ -105,6 +105,8 @@
+
+
diff --git a/TrueCraft.Client/TrueCraftGame.cs b/TrueCraft.Client/TrueCraftGame.cs
index b747325..cb7fbb6 100644
--- a/TrueCraft.Client/TrueCraftGame.cs
+++ b/TrueCraft.Client/TrueCraftGame.cs
@@ -28,11 +28,9 @@ namespace TrueCraft.Client
private IPEndPoint EndPoint { get; set; }
private ChunkRenderer ChunkConverter { get; set; }
private DateTime NextPhysicsUpdate { get; set; }
- private List ChunkMeshes { get; set; }
+ private List ChunkMeshes { get; set; }
private ConcurrentBag PendingMainThreadActions { get; set; }
- private ConcurrentBag IncomingChunks { get; set; }
- private ConcurrentBag IncomingTransparentChunks { get; set; }
- private List TransparentChunkMeshes { get; set; }
+ private ConcurrentBag IncomingChunks { get; set; }
public ChatInterface ChatInterface { get; set; }
private RenderTarget2D RenderTarget;
private BoundingFrustum CameraView;
@@ -51,16 +49,15 @@ namespace TrueCraft.Client
Window.Title = "TrueCraft";
Content.RootDirectory = "Content";
Graphics = new GraphicsDeviceManager(this);
+ Graphics.SynchronizeWithVerticalRetrace = false;
Graphics.IsFullScreen = UserSettings.Local.IsFullscreen;
Graphics.PreferredBackBufferWidth = UserSettings.Local.WindowResolution.Width;
Graphics.PreferredBackBufferHeight = UserSettings.Local.WindowResolution.Height;
Client = client;
EndPoint = endPoint;
NextPhysicsUpdate = DateTime.MinValue;
- ChunkMeshes = new List();
- TransparentChunkMeshes = new List();
- IncomingChunks = new ConcurrentBag();
- IncomingTransparentChunks = new ConcurrentBag();
+ ChunkMeshes = new List();
+ IncomingChunks = new ConcurrentBag();
PendingMainThreadActions = new ConcurrentBag();
MouseCaptured = true;
@@ -79,9 +76,9 @@ namespace TrueCraft.Client
SpriteBatch = new SpriteBatch(GraphicsDevice);
base.Initialize(); // (calls LoadContent)
ChunkConverter = new ChunkRenderer(Graphics.GraphicsDevice, Client.World.World.BlockRepository);
- Client.ChunkLoaded += (sender, e) => ChunkConverter.QueueChunk(e.Chunk);
- Client.ChunkModified += (sender, e) => ChunkConverter.QueueHighPriorityChunk(e.Chunk);
- ChunkConverter.MeshGenerated += ChunkConverter_MeshGenerated;
+ Client.ChunkLoaded += (sender, e) => ChunkConverter.Enqueue(e.Chunk);
+ Client.ChunkModified += (sender, e) => ChunkConverter.Enqueue(e.Chunk, true);
+ ChunkConverter.MeshCompleted += ChunkConverter_MeshGenerated;
ChunkConverter.Start();
Client.PropertyChanged += HandleClientPropertyChanged;
Client.Connect(EndPoint);
@@ -103,12 +100,9 @@ namespace TrueCraft.Client
false, GraphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24);
}
- void ChunkConverter_MeshGenerated(object sender, ChunkRenderer.MeshGeneratedEventArgs e)
+ void ChunkConverter_MeshGenerated(object sender, RendererEventArgs e)
{
- if (e.Transparent)
- IncomingTransparentChunks.Add(e.Mesh);
- else
- IncomingChunks.Add(e.Mesh);
+ IncomingChunks.Add(e.Result);
}
void HandleClientPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -119,7 +113,7 @@ namespace TrueCraft.Client
UpdateCamera();
var sorter = new ChunkRenderer.ChunkSorter(new Coordinates3D(
(int)Client.Position.X, 0, (int)Client.Position.Z));
- PendingMainThreadActions.Add(() => TransparentChunkMeshes.Sort(sorter));
+ PendingMainThreadActions.Add(() => ChunkMeshes.Sort(sorter));
break;
}
}
@@ -287,16 +281,11 @@ namespace TrueCraft.Client
i.Update(gameTime);
}
- ChunkMesh mesh;
+ Mesh mesh;
if (IncomingChunks.TryTake(out mesh))
{
- var existing = ChunkMeshes.SingleOrDefault(m => m.Chunk.Chunk.Coordinates == mesh.Chunk.Chunk.Coordinates);
- if (existing != null)
- ChunkMeshes.Remove(existing);
ChunkMeshes.Add(mesh);
}
- if (IncomingTransparentChunks.TryTake(out mesh)) // TODO: re-render transparent meshes
- TransparentChunkMeshes.Add(mesh);
Action action;
if (PendingMainThreadActions.TryTake(out action))
action();
@@ -364,17 +353,17 @@ namespace TrueCraft.Client
{
verticies += ChunkMeshes[i].GetTotalVertices();
chunks++;
- ChunkMeshes[i].Draw(OpaqueEffect);
+ ChunkMeshes[i].Draw(OpaqueEffect, 0);
}
}
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
- for (int i = 0; i < TransparentChunkMeshes.Count; i++)
+ for (int i = 0; i < ChunkMeshes.Count; i++)
{
- if (CameraView.Intersects(TransparentChunkMeshes[i].BoundingBox))
+ if (CameraView.Intersects(ChunkMeshes[i].BoundingBox))
{
- if (!TransparentChunkMeshes[i].IsDisposed)
- verticies += TransparentChunkMeshes[i].GetTotalVertices();
- TransparentChunkMeshes[i].Draw(TransparentEffect);
+ if (!ChunkMeshes[i].IsDisposed)
+ verticies += ChunkMeshes[i].GetTotalVertices();
+ ChunkMeshes[i].Draw(TransparentEffect, 1);
}
}
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
diff --git a/TrueCraft.sln b/TrueCraft.sln
index 5449501..c09f6f1 100644
--- a/TrueCraft.sln
+++ b/TrueCraft.sln
@@ -1,6 +1,8 @@
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2013 for Windows Desktop
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCraft", "TrueCraft\TrueCraft.csproj", "{C1C47EF5-2D8A-4231-AAA8-F651F52F480E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCraft.API", "TrueCraft.API\TrueCraft.API.csproj", "{FEE55B54-91B0-4325-A2C3-D576C0B7A81F}"
@@ -19,44 +21,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCraft.Core.Test", "True
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x86 = Debug|x86
- Release|x86 = Release|x86
Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
Release|x64 = Release|x64
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {4488498D-976D-4DA3-BF72-109531AF0488}.Debug|x64.ActiveCfg = Debug|Any CPU
- {4488498D-976D-4DA3-BF72-109531AF0488}.Debug|x64.Build.0 = Debug|Any CPU
- {4488498D-976D-4DA3-BF72-109531AF0488}.Debug|x86.ActiveCfg = Debug|Any CPU
- {4488498D-976D-4DA3-BF72-109531AF0488}.Debug|x86.Build.0 = Debug|Any CPU
- {4488498D-976D-4DA3-BF72-109531AF0488}.Release|x64.ActiveCfg = Release|Any CPU
- {4488498D-976D-4DA3-BF72-109531AF0488}.Release|x64.Build.0 = Release|Any CPU
- {4488498D-976D-4DA3-BF72-109531AF0488}.Release|x86.ActiveCfg = Release|Any CPU
- {4488498D-976D-4DA3-BF72-109531AF0488}.Release|x86.Build.0 = Release|Any CPU
- {6604F17A-552E-405D-B327-37C8B1648C86}.Debug|x64.ActiveCfg = Debug|Any CPU
- {6604F17A-552E-405D-B327-37C8B1648C86}.Debug|x64.Build.0 = Debug|Any CPU
- {6604F17A-552E-405D-B327-37C8B1648C86}.Debug|x86.ActiveCfg = Debug|Any CPU
- {6604F17A-552E-405D-B327-37C8B1648C86}.Debug|x86.Build.0 = Debug|Any CPU
- {6604F17A-552E-405D-B327-37C8B1648C86}.Release|x64.ActiveCfg = Release|Any CPU
- {6604F17A-552E-405D-B327-37C8B1648C86}.Release|x64.Build.0 = Release|Any CPU
- {6604F17A-552E-405D-B327-37C8B1648C86}.Release|x86.ActiveCfg = Release|Any CPU
- {6604F17A-552E-405D-B327-37C8B1648C86}.Release|x86.Build.0 = Release|Any CPU
- {A6516869-A2FB-4E31-85C8-2285490CB32C}.Debug|x64.ActiveCfg = Debug|x86
- {A6516869-A2FB-4E31-85C8-2285490CB32C}.Debug|x64.Build.0 = Debug|x86
- {A6516869-A2FB-4E31-85C8-2285490CB32C}.Debug|x86.ActiveCfg = Debug|x86
- {A6516869-A2FB-4E31-85C8-2285490CB32C}.Debug|x86.Build.0 = Debug|x86
- {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|x64.ActiveCfg = Release|x86
- {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|x64.Build.0 = Release|x86
- {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|x86.ActiveCfg = Release|x86
- {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|x86.Build.0 = Release|x86
- {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|x64.ActiveCfg = Debug|Any CPU
- {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|x64.Build.0 = Debug|Any CPU
- {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|x86.ActiveCfg = Debug|Any CPU
- {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|x86.Build.0 = Debug|Any CPU
- {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Release|x64.ActiveCfg = Release|Any CPU
- {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Release|x64.Build.0 = Release|Any CPU
- {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Release|x86.ActiveCfg = Release|Any CPU
- {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Release|x86.Build.0 = Release|Any CPU
{C1C47EF5-2D8A-4231-AAA8-F651F52F480E}.Debug|x64.ActiveCfg = Debug|x86
{C1C47EF5-2D8A-4231-AAA8-F651F52F480E}.Debug|x64.Build.0 = Debug|x86
{C1C47EF5-2D8A-4231-AAA8-F651F52F480E}.Debug|x86.ActiveCfg = Debug|x86
@@ -65,14 +35,6 @@ Global
{C1C47EF5-2D8A-4231-AAA8-F651F52F480E}.Release|x64.Build.0 = Release|x86
{C1C47EF5-2D8A-4231-AAA8-F651F52F480E}.Release|x86.ActiveCfg = Release|x86
{C1C47EF5-2D8A-4231-AAA8-F651F52F480E}.Release|x86.Build.0 = Release|x86
- {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Debug|x64.ActiveCfg = Debug|Any CPU
- {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Debug|x64.Build.0 = Debug|Any CPU
- {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Debug|x86.ActiveCfg = Debug|Any CPU
- {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Debug|x86.Build.0 = Debug|Any CPU
- {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Release|x64.ActiveCfg = Release|Any CPU
- {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Release|x64.Build.0 = Release|Any CPU
- {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Release|x86.ActiveCfg = Release|Any CPU
- {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Release|x86.Build.0 = Release|Any CPU
{FEE55B54-91B0-4325-A2C3-D576C0B7A81F}.Debug|x64.ActiveCfg = Debug|Any CPU
{FEE55B54-91B0-4325-A2C3-D576C0B7A81F}.Debug|x64.Build.0 = Debug|Any CPU
{FEE55B54-91B0-4325-A2C3-D576C0B7A81F}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -81,6 +43,49 @@ Global
{FEE55B54-91B0-4325-A2C3-D576C0B7A81F}.Release|x64.Build.0 = Release|Any CPU
{FEE55B54-91B0-4325-A2C3-D576C0B7A81F}.Release|x86.ActiveCfg = Release|Any CPU
{FEE55B54-91B0-4325-A2C3-D576C0B7A81F}.Release|x86.Build.0 = Release|Any CPU
+ {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Release|x64.Build.0 = Release|Any CPU
+ {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}.Release|x86.Build.0 = Release|Any CPU
+ {4488498D-976D-4DA3-BF72-109531AF0488}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4488498D-976D-4DA3-BF72-109531AF0488}.Debug|x64.Build.0 = Debug|Any CPU
+ {4488498D-976D-4DA3-BF72-109531AF0488}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4488498D-976D-4DA3-BF72-109531AF0488}.Debug|x86.Build.0 = Debug|Any CPU
+ {4488498D-976D-4DA3-BF72-109531AF0488}.Release|x64.ActiveCfg = Release|Any CPU
+ {4488498D-976D-4DA3-BF72-109531AF0488}.Release|x64.Build.0 = Release|Any CPU
+ {4488498D-976D-4DA3-BF72-109531AF0488}.Release|x86.ActiveCfg = Release|Any CPU
+ {4488498D-976D-4DA3-BF72-109531AF0488}.Release|x86.Build.0 = Release|Any CPU
+ {A6516869-A2FB-4E31-85C8-2285490CB32C}.Debug|x64.ActiveCfg = Debug|x86
+ {A6516869-A2FB-4E31-85C8-2285490CB32C}.Debug|x64.Build.0 = Debug|x86
+ {A6516869-A2FB-4E31-85C8-2285490CB32C}.Debug|x86.ActiveCfg = Debug|x86
+ {A6516869-A2FB-4E31-85C8-2285490CB32C}.Debug|x86.Build.0 = Debug|x86
+ {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|x64.ActiveCfg = Release|x86
+ {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|x64.Build.0 = Release|x86
+ {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|x86.ActiveCfg = Release|x86
+ {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|x86.Build.0 = Release|x86
+ {6604F17A-552E-405D-B327-37C8B1648C86}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6604F17A-552E-405D-B327-37C8B1648C86}.Debug|x64.Build.0 = Debug|Any CPU
+ {6604F17A-552E-405D-B327-37C8B1648C86}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6604F17A-552E-405D-B327-37C8B1648C86}.Debug|x86.Build.0 = Debug|Any CPU
+ {6604F17A-552E-405D-B327-37C8B1648C86}.Release|x64.ActiveCfg = Release|Any CPU
+ {6604F17A-552E-405D-B327-37C8B1648C86}.Release|x64.Build.0 = Release|Any CPU
+ {6604F17A-552E-405D-B327-37C8B1648C86}.Release|x86.ActiveCfg = Release|Any CPU
+ {6604F17A-552E-405D-B327-37C8B1648C86}.Release|x86.Build.0 = Release|Any CPU
+ {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|x64.Build.0 = Debug|Any CPU
+ {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|x86.Build.0 = Debug|Any CPU
+ {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Release|x64.ActiveCfg = Release|Any CPU
+ {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Release|x64.Build.0 = Release|Any CPU
+ {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Release|x86.ActiveCfg = Release|Any CPU
+ {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{BCFDCD93-C23E-49E6-9767-A887B3C2A709} = {6756B61E-5856-4CA7-90B5-6053763FE7BA}