-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b42d228
Showing
6 changed files
with
474 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/// <summary> | ||
/// Helper class responsible for creating and managing the GraphicsDevice. | ||
/// All GraphicsDeviceControl instances share the same GraphicsDeviceService, | ||
/// so even though there can be many controls, there will only ever be a | ||
/// single underlying GraphicsDevice. This implements the standard | ||
/// IGraphicsDeviceService interface, which provides notification events for | ||
/// when the device is reset or disposed. | ||
/// </summary> | ||
public class GraphicsDeviceService : IGraphicsDeviceService | ||
{ | ||
// Singleton device service instance. | ||
private static GraphicsDeviceService singletonInstance; | ||
|
||
// Keep track of how many controls are sharing the singletonInstance. | ||
private static int referenceCount; | ||
|
||
/// <summary> | ||
/// Gets the single instance of the service class for the application. | ||
/// </summary> | ||
public static GraphicsDeviceService Instance | ||
{ | ||
get | ||
{ | ||
if (singletonInstance == null) | ||
singletonInstance = new GraphicsDeviceService(); | ||
return singletonInstance; | ||
} | ||
} | ||
|
||
// Store the current device settings. | ||
private PresentationParameters parameters; | ||
|
||
/// <summary> | ||
/// Gets the current graphics device. | ||
/// </summary> | ||
public GraphicsDevice GraphicsDevice { get; private set; } | ||
|
||
// IGraphicsDeviceService events. | ||
public event EventHandler<EventArgs> DeviceCreated; | ||
public event EventHandler<EventArgs> DeviceDisposing; | ||
public event EventHandler<EventArgs> DeviceReset; | ||
public event EventHandler<EventArgs> DeviceResetting; | ||
|
||
/// <summary> | ||
/// Constructor is private, because this is a singleton class: | ||
/// client controls should use the public AddRef method instead. | ||
/// </summary> | ||
GraphicsDeviceService() { } | ||
|
||
/// <summary> | ||
/// Creates the GraphicsDevice for the service. | ||
/// </summary> | ||
private void CreateDevice(IntPtr windowHandle) | ||
{ | ||
parameters = new PresentationParameters(); | ||
|
||
// since we're using render targets anyway, the | ||
// backbuffer size is somewhat irrelevant | ||
parameters.BackBufferWidth = 480; | ||
parameters.BackBufferHeight = 320; | ||
parameters.BackBufferFormat = SurfaceFormat.Color; | ||
parameters.DeviceWindowHandle = windowHandle; | ||
parameters.DepthStencilFormat = DepthFormat.Depth24Stencil8; | ||
parameters.IsFullScreen = false; | ||
|
||
GraphicsDevice = new GraphicsDevice( | ||
GraphicsAdapter.DefaultAdapter, | ||
GraphicsProfile.HiDef, | ||
parameters); | ||
|
||
if (DeviceCreated != null) | ||
DeviceCreated(this, EventArgs.Empty); | ||
} | ||
|
||
/// <summary> | ||
/// Gets a reference to the singleton instance. | ||
/// </summary> | ||
public static GraphicsDeviceService AddRef(IntPtr windowHandle) | ||
{ | ||
// Increment the "how many controls sharing the device" | ||
// reference count. | ||
if (Interlocked.Increment(ref referenceCount) == 1) | ||
{ | ||
// If this is the first control to start using the | ||
// device, we must create the device. | ||
Instance.CreateDevice(windowHandle); | ||
} | ||
|
||
return singletonInstance; | ||
} | ||
|
||
/// <summary> | ||
/// Releases a reference to the singleton instance. | ||
/// </summary> | ||
public void Release() | ||
{ | ||
// Decrement the "how many controls sharing the device" | ||
// reference count. | ||
if (Interlocked.Decrement(ref referenceCount) == 0) | ||
{ | ||
// If this is the last control to finish using the | ||
// device, we should dispose the singleton instance. | ||
if (DeviceDisposing != null) | ||
DeviceDisposing(this, EventArgs.Empty); | ||
|
||
GraphicsDevice.Dispose(); | ||
|
||
GraphicsDevice = null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Copyright (c) 2010 Nick Gravelyn, Microsoft | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
# Overview | ||
|
||
This is a repository preserving example code by [Nick Gravelyn](https://www.nickgravelyn.com/) did some blog post on XNA in the Microsoft Docs. As long as it's there, the original post can be found in the [Microsoft Docs Blog Archive](https://docs.microsoft.com/en-us/archive/blogs/nicgrave/rendering-with-xna-framework-4-0-inside-of-a-wpf-application). Originally there was no license included. By mail and in [this issue at MerjTek's WPF integration](https://github.com/MerjTek/MerjTek.WpfIntegration/issues/1#issuecomment-902622749) he kindly answered the code may be considered MIT or Microsoft Public License, so I put it here under MIT. | ||
|
||
This repository allows for using the code without legal concerns which may occur with the missing license in the blog post. | ||
|
||
|
||
# Example Code | ||
|
||
There was more example code included in the blogpost, which is preserved here. | ||
|
||
|
||
## Example 1 | ||
|
||
```csharp | ||
// What importers or processors should we load? | ||
private const string xnaVersion = | ||
", Version=4.0.0.0, PublicKeyToken=6d5c3888ef60e27d"; | ||
private static readonly string[] pipelineAssemblies = | ||
{ | ||
"Microsoft.Xna.Framework.Content.Pipeline.AudioImporters" + xnaVersion, | ||
"Microsoft.Xna.Framework.Content.Pipeline.EffectImporter" + xnaVersion, | ||
"Microsoft.Xna.Framework.Content.Pipeline.FBXImporter" + xnaVersion, | ||
"Microsoft.Xna.Framework.Content.Pipeline.TextureImporter" + xnaVersion, | ||
"Microsoft.Xna.Framework.Content.Pipeline.VideoImporters" + xnaVersion, | ||
"Microsoft.Xna.Framework.Content.Pipeline.XImporter" + xnaVersion, | ||
}; | ||
``` | ||
|
||
|
||
## Example 2 | ||
|
||
```csharp | ||
using Microsoft.Build.Evaluation; | ||
``` | ||
|
||
|
||
## Example 3 | ||
|
||
```csharp | ||
// MSBuild objects used to dynamically build content. | ||
private ProjectCollection projectCollection; | ||
private Project msBuildProject; | ||
``` | ||
|
||
## Example 4 | ||
|
||
```csharp | ||
/// <summary> | ||
/// Creates a temporary MSBuild content project in memory. | ||
/// </summary> | ||
void CreateBuildProject() | ||
{ | ||
string projectPath = | ||
Path.Combine(buildDirectory, "content.contentproj"); | ||
string outputPath = Path.Combine(buildDirectory, "bin"); | ||
|
||
// Create the project collection | ||
projectCollection = new ProjectCollection(); | ||
|
||
// Hook up our custom error logger. | ||
errorLogger = new ErrorLogger(); | ||
projectCollection.RegisterLogger(errorLogger); | ||
|
||
// Create the build project. | ||
msBuildProject = new Project(projectCollection); | ||
msBuildProject.FullPath = projectPath; | ||
|
||
// set up the properties we care about | ||
msBuildProject.SetProperty("XnaPlatform", "Windows"); | ||
msBuildProject.SetProperty("XnaFrameworkVersion", "v4.0"); | ||
msBuildProject.SetProperty("XnaProfile", "HiDef"); | ||
msBuildProject.SetProperty("Configuration", "Release"); | ||
msBuildProject.SetProperty("OutputPath", outputPath); | ||
|
||
// Register any custom importers or processors. | ||
foreach (string pipelineAssembly in pipelineAssemblies) | ||
{ | ||
msBuildProject.AddItem("Reference", pipelineAssembly); | ||
} | ||
|
||
// Include the standard targets file that defines | ||
// how to build XNA Framework content. | ||
msBuildProject.Xml.AddImport( | ||
"$(MSBuildExtensionsPath)\\Microsoft\\XNA Game Studio\\v4.0\\" + | ||
"Microsoft.Xna.GameStudio.ContentPipeline.targets"); | ||
} | ||
``` | ||
|
||
|
||
## Example 5 | ||
|
||
```csharp | ||
/// <summary> | ||
/// Adds a new content file to the MSBuild project. The importer and | ||
/// processor are optional: if you leave the importer null, it will | ||
/// be autodetected based on the file extension, and if you leave the | ||
/// processor null, data will be passed through without any processing. | ||
/// </summary> | ||
public void Add( | ||
string filename, string name, | ||
string importer, string processor) | ||
{ | ||
// set up the metadata for this item | ||
var metadata = new SortedList<string,string>(); | ||
metadata.Add("Link", Path.GetFileName(filename)); | ||
metadata.Add("Name", name); | ||
|
||
if (!string.IsNullOrEmpty(importer)) | ||
metadata.Add("Importer", importer); | ||
|
||
if (!string.IsNullOrEmpty(processor)) | ||
metadata.Add("Processor", processor); | ||
|
||
// add the item | ||
msBuildProject.AddItem("Compile", filename, metadata); | ||
} | ||
``` | ||
|
||
|
||
## Example 6 | ||
|
||
```csharp | ||
/// <summary> | ||
/// Removes all content files from the MSBuild project. | ||
/// </summary> | ||
public void Clear() | ||
{ | ||
// select all compiled objects in the project and remove them | ||
var compileObjects = from i in project.Items | ||
where i.ItemType == "Compile" | ||
select i; | ||
project.RemoveItems(compileObjects); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
public partial class XnaControl : UserControl | ||
{ | ||
private GraphicsDeviceService graphicsService; | ||
private XnaImageSource imageSource; | ||
|
||
/// <summary> | ||
/// Gets the GraphicsDevice behind the control. | ||
/// </summary> | ||
public GraphicsDevice GraphicsDevice | ||
{ | ||
get { return graphicsService.GraphicsDevice; } | ||
} | ||
|
||
/// <summary> | ||
/// Invoked when the XnaControl needs to be redrawn. | ||
/// </summary> | ||
public Action<GraphicsDevice> DrawFunction; | ||
|
||
public XnaControl() | ||
{ | ||
InitializeComponent(); | ||
|
||
// hook up an event to fire when the control has finished loading | ||
Loaded += new RoutedEventHandler(XnaControl_Loaded); | ||
} | ||
|
||
~XnaControl() | ||
{ | ||
imageSource.Dispose(); | ||
|
||
// release on finalizer to clean up the graphics device | ||
if (graphicsService != null) | ||
graphicsService.Release(); | ||
} | ||
|
||
void XnaControl_Loaded(object sender, RoutedEventArgs e) | ||
{ | ||
// if we're not in design mode, initialize the graphics device | ||
if (DesignerProperties.GetIsInDesignMode(this) == false) | ||
{ | ||
InitializeGraphicsDevice(); | ||
} | ||
} | ||
|
||
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) | ||
{ | ||
// if we're not in design mode, recreate the | ||
// image source for the new size | ||
if (DesignerProperties.GetIsInDesignMode(this) == false && | ||
graphicsService != null) | ||
{ | ||
// recreate the image source | ||
imageSource.Dispose(); | ||
imageSource = new XnaImageSource( | ||
GraphicsDevice, (int)ActualWidth, (int)ActualHeight); | ||
rootImage.Source = imageSource.WriteableBitmap; | ||
} | ||
|
||
base.OnRenderSizeChanged(sizeInfo); | ||
} | ||
|
||
private void InitializeGraphicsDevice() | ||
{ | ||
if (graphicsService == null) | ||
{ | ||
// add a reference to the graphics device | ||
graphicsService = GraphicsDeviceService.AddRef( | ||
(PresentationSource.FromVisual(this) as HwndSource).Handle); | ||
|
||
// create the image source | ||
imageSource = new XnaImageSource( | ||
GraphicsDevice, (int)ActualWidth, (int)ActualHeight); | ||
rootImage.Source = imageSource.WriteableBitmap; | ||
|
||
// hook the rendering event | ||
CompositionTarget.Rendering += CompositionTarget_Rendering; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Draws the control and allows subclasses to override | ||
/// the default behavior of delegating the rendering. | ||
/// </summary> | ||
protected virtual void Render() | ||
{ | ||
// invoke the draw delegate so someone will draw something pretty | ||
if (DrawFunction != null) | ||
DrawFunction(GraphicsDevice); | ||
} | ||
|
||
void CompositionTarget_Rendering(object sender, EventArgs e) | ||
{ | ||
// set the image source render target | ||
GraphicsDevice.SetRenderTarget(imageSource.RenderTarget); | ||
|
||
// allow the control to draw | ||
Render(); | ||
|
||
// unset the render target | ||
GraphicsDevice.SetRenderTarget(null); | ||
|
||
// commit the changes to the image source | ||
imageSource.Commit(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<UserControl x:Class="MyApp.XnaControl" | ||
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" | ||
MinHeight="50" MinWidth="50" Background="CornflowerBlue"> | ||
<Image x:Name="rootImage" /> | ||
</UserControl> |
Oops, something went wrong.