├── .gitignore ├── DotNetUpdates ├── PureAttribute.cs ├── StringBuilderExtensions.cs ├── TimeSpanExtensions.cs └── Tuple.cs ├── HackClasses └── DataContractAttribute.cs ├── LICENSE ├── MonoGame.Framework ├── Audio │ └── SoundEffect.cs ├── Content │ └── ContentManager.cs ├── Game.cs ├── Graphics │ ├── Effect │ │ └── Effect.cs │ ├── GraphicsDevice.cs │ ├── SpriteBatch.cs │ ├── States │ │ ├── BlendState.cs │ │ ├── DepthStencilState.cs │ │ ├── RasterizerState.cs │ │ └── SamplerState.cs │ └── Texture2D.cs ├── GraphicsDeviceManager.cs ├── Media │ ├── MediaPlayer.cs │ └── Song.cs └── UnityGameWindow.cs ├── README.md └── XnaUnitySpriteBatch.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | obj 2 | *.DotSettings 3 | *.user 4 | bin 5 | -------------------------------------------------------------------------------- /DotNetUpdates/PureAttribute.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace System.Diagnostics.Contracts 3 | { 4 | public class PureAttribute : Attribute 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /DotNetUpdates/StringBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | public static class StringBuilderExtensions 4 | { 5 | public static void Clear(this StringBuilder stringBuilder) 6 | { 7 | stringBuilder.Length = 0; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DotNetUpdates/TimeSpanExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | public static class TimeSpanExtensions 4 | { 5 | public static string ToString(this TimeSpan timeSpan, string format) 6 | { 7 | if (format == "mm\\:ss") 8 | return string.Concat(timeSpan.Minutes.ToString().PadLeft(2, '0'), ":", timeSpan.Seconds.ToString().PadLeft(2, '0')); 9 | 10 | throw new NotImplementedException(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DotNetUpdates/Tuple.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace System 3 | { 4 | public class Tuple 5 | { 6 | public T Item1; 7 | public T2 Item2; 8 | 9 | public Tuple(T item1, T2 item2) 10 | { 11 | Item1 = item1; 12 | Item2 = item2; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /HackClasses/DataContractAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace System.Runtime.Serialization 3 | { 4 | class DataContractAttribute : Attribute 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Microsoft Public License (Ms-PL) 2 | MonoGame - Copyright © 2009-2012 The MonoGame Team 3 | 4 | All rights reserved. 5 | 6 | This license governs use of the accompanying software. If you use the software, 7 | you accept this license. If you do not accept the license, do not use the 8 | software. 9 | 10 | 1. Definitions 11 | 12 | The terms "reproduce," "reproduction," "derivative works," and "distribution" 13 | have the same meaning here as under U.S. copyright law. 14 | 15 | A "contribution" is the original software, or any additions or changes to the 16 | software. 17 | 18 | A "contributor" is any person that distributes its contribution under this 19 | license. 20 | 21 | "Licensed patents" are a contributor's patent claims that read directly on its 22 | contribution. 23 | 24 | 2. Grant of Rights 25 | 26 | (A) Copyright Grant- Subject to the terms of this license, including the 27 | license conditions and limitations in section 3, each contributor grants you a 28 | non-exclusive, worldwide, royalty-free copyright license to reproduce its 29 | contribution, prepare derivative works of its contribution, and distribute its 30 | contribution or any derivative works that you create. 31 | 32 | (B) Patent Grant- Subject to the terms of this license, including the license 33 | conditions and limitations in section 3, each contributor grants you a 34 | non-exclusive, worldwide, royalty-free license under its licensed patents to 35 | make, have made, use, sell, offer for sale, import, and/or otherwise dispose of 36 | its contribution in the software or derivative works of the contribution in the 37 | software. 38 | 39 | 3. Conditions and Limitations 40 | 41 | (A) No Trademark License- This license does not grant you rights to use any 42 | contributors' name, logo, or trademarks. 43 | 44 | (B) If you bring a patent claim against any contributor over patents that you 45 | claim are infringed by the software, your patent license from such contributor 46 | to the software ends automatically. 47 | 48 | (C) If you distribute any portion of the software, you must retain all 49 | copyright, patent, trademark, and attribution notices that are present in the 50 | software. 51 | 52 | (D) If you distribute any portion of the software in source code form, you may 53 | do so only under this license by including a complete copy of this license with 54 | your distribution. If you distribute any portion of the software in compiled or 55 | object code form, you may only do so under a license that complies with this 56 | license. 57 | 58 | (E) The software is licensed "as-is." You bear the risk of using it. The 59 | contributors give no express warranties, guarantees or conditions. You may have 60 | additional consumer rights under your local laws which this license cannot 61 | change. To the extent permitted under your local laws, the contributors exclude 62 | the implied warranties of merchantability, fitness for a particular purpose and 63 | non-infringement. 64 | -------------------------------------------------------------------------------- /MonoGame.Framework/Audio/SoundEffect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Microsoft.Xna.Framework.Audio 5 | { 6 | public class SoundEffect 7 | { 8 | private readonly AudioClip _audioClip; 9 | private AudioSource _audioSource; 10 | 11 | internal static readonly GameObject GameObject = new GameObject(); 12 | 13 | public SoundEffect(AudioClip audioClip) 14 | { 15 | if (audioClip == null) 16 | throw new Exception("AudioClip is null"); 17 | 18 | _audioClip = audioClip; 19 | _audioSource = GameObject.AddComponent(); 20 | _audioSource.clip = _audioClip; 21 | } 22 | 23 | public void Play() 24 | { 25 | Play(1, 0, 0); 26 | } 27 | 28 | public void Play(float volume, float pitch, float pan) 29 | { 30 | //todo: we need to pool our audio source objects like MonoGame does 31 | 32 | //ref http://answers.unity3d.com/questions/55023/how-does-audiosourcepitch-changes-pitch.html 33 | 34 | _audioSource.volume = volume; 35 | _audioSource.pan = pan; 36 | _audioSource.pitch = Mathf.Pow(2, pitch); 37 | _audioSource.Play(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MonoGame.Framework/Content/ContentManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Xna.Framework.Audio; 3 | using Microsoft.Xna.Framework.Media; 4 | using UnityTexture = UnityEngine.Texture2D; 5 | using UnityAudioClip = UnityEngine.AudioClip; 6 | using UnityResources = UnityEngine.Resources; 7 | using TextAsset = UnityEngine.TextAsset; 8 | using Microsoft.Xna.Framework.Graphics; 9 | 10 | namespace Microsoft.Xna.Framework.Content 11 | { 12 | public class ContentManager 13 | { 14 | public string RootDirectory { get; set; } 15 | 16 | public T Load(string fileName) where T : class 17 | { 18 | if (typeof(T) == typeof(Texture2D)) 19 | { 20 | return new Texture2D(NativeLoad(fileName)) as T; 21 | } 22 | if (typeof(T) == typeof(SoundEffect)) 23 | { 24 | return new SoundEffect(NativeLoad(fileName)) as T; 25 | } 26 | if (typeof(T) == typeof(Song)) 27 | { 28 | return new Song(NativeLoad(fileName)) as T; 29 | } 30 | if (typeof(T) == typeof(string)) 31 | { 32 | return (NativeLoad(fileName)).text as T; 33 | } 34 | //throw new Exception(); 35 | return default(T); 36 | } 37 | 38 | private T NativeLoad(string fileName) where T : class 39 | { 40 | var res = UnityResources.Load(fileName, typeof(T)) as T; 41 | if (res == null) 42 | { 43 | throw new Exception("Failed to load " + fileName + " as " + typeof(T)); 44 | } 45 | return res; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /MonoGame.Framework/Game.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Microsoft.Xna.Framework.Content; 4 | using Microsoft.Xna.Framework.Graphics; 5 | using Microsoft.Xna.Framework.Input.Touch; 6 | using Microsoft.Xna.Framework.Media; 7 | using UnityEngine; 8 | 9 | namespace Microsoft.Xna.Framework 10 | { 11 | public class Game : IDisposable 12 | { 13 | public bool IsMouseVisible { get; set; } 14 | public GraphicsDevice GraphicsDevice { get; private set; } 15 | 16 | internal static Game Instance { get; private set; } 17 | public GameWindow Window { get { return _window; } } 18 | public ContentManager Content { get; private set; } 19 | 20 | private readonly GameTime _gameTime = new GameTime(new TimeSpan(), TimeSpan.FromSeconds(Time.fixedDeltaTime)); 21 | private readonly TimeSpan _fixedDeltaTime = TimeSpan.FromSeconds(Time.fixedDeltaTime); 22 | 23 | public Game() 24 | { 25 | GraphicsDevice = new GraphicsDevice(new Viewport(0, 0, Screen.width, Screen.height)); 26 | Content = new ContentManager(); 27 | 28 | _window = new UnityGameWindow(GraphicsDevice); 29 | 30 | UnityEngine.Input.simulateMouseWithTouches = false; 31 | UnityEngine.Input.multiTouchEnabled = true; 32 | } 33 | 34 | /// 35 | /// Must be called by Unity in a Update call 36 | /// 37 | public void UnityUpdate() 38 | { 39 | PreUpdate(); 40 | 41 | RunUpdates(); 42 | 43 | GraphicsDevice.ResetPools(); 44 | Draw(_gameTime); 45 | } 46 | 47 | private readonly TimeSpan _targetElapsedTime = TimeSpan.FromTicks((long)10000000 / (long)60); 48 | private readonly TimeSpan _maxElapsedTime = TimeSpan.FromTicks((long)30000000 / (long)60); 49 | 50 | private readonly Stopwatch _gameTimer = Stopwatch.StartNew(); 51 | private TimeSpan _accumulatedElapsedTime; 52 | 53 | //Taken from MonoGame.Game.Tick 54 | private void RunUpdates() 55 | { 56 | _gameTime.ElapsedGameTime = _targetElapsedTime; 57 | var stepCount = 0; 58 | 59 | // Advance the accumulated elapsed time. 60 | var elapsed = _gameTimer.Elapsed; 61 | if (elapsed > _maxElapsedTime) 62 | elapsed = _maxElapsedTime; 63 | _accumulatedElapsedTime += elapsed; 64 | _gameTimer.Reset(); 65 | _gameTimer.Start(); 66 | // Perform as many full fixed length time steps as we can. 67 | while (_accumulatedElapsedTime >= _targetElapsedTime) 68 | { 69 | _gameTime.TotalGameTime += _targetElapsedTime; 70 | _accumulatedElapsedTime -= _targetElapsedTime; 71 | ++stepCount; 72 | 73 | MediaPlayer.Update((float)_targetElapsedTime.TotalSeconds); 74 | Update(_gameTime); 75 | } 76 | // Draw needs to know the total elapsed time 77 | // that occured for the fixed length updates. 78 | _gameTime.ElapsedGameTime = TimeSpan.FromTicks(_targetElapsedTime.Ticks * stepCount); 79 | } 80 | 81 | private void PreUpdate() 82 | { 83 | _window.Update(); 84 | UpdateInput(); 85 | } 86 | 87 | public void UnityInitialize() 88 | { 89 | Initialize(); 90 | LoadContent(); 91 | } 92 | 93 | private bool _mouseIsDown = false; 94 | private UnityGameWindow _window; 95 | 96 | private const int MouseId = int.MinValue; 97 | 98 | private void UpdateInput() 99 | { 100 | if (UnityEngine.Input.mousePresent) 101 | { 102 | bool mouseIsDown = UnityEngine.Input.GetMouseButton(0); 103 | if (!_mouseIsDown && mouseIsDown) 104 | TouchPanel.AddEvent(MouseId, TouchLocationState.Pressed, ToMonoGame(UnityEngine.Input.mousePosition)); 105 | else if (_mouseIsDown && !mouseIsDown) 106 | TouchPanel.AddEvent(MouseId, TouchLocationState.Released, ToMonoGame(UnityEngine.Input.mousePosition)); 107 | else if (_mouseIsDown) 108 | TouchPanel.AddEvent(MouseId, TouchLocationState.Moved, ToMonoGame(UnityEngine.Input.mousePosition)); 109 | _mouseIsDown = mouseIsDown; 110 | } 111 | 112 | for (var i = 0; i < UnityEngine.Input.touchCount; i++) 113 | { 114 | var touch = UnityEngine.Input.touches[i]; 115 | switch (touch.phase) 116 | { 117 | case TouchPhase.Began: 118 | TouchPanel.AddEvent(touch.fingerId, TouchLocationState.Pressed, ToMonoGame(touch.position)); 119 | break; 120 | case TouchPhase.Moved: 121 | TouchPanel.AddEvent(touch.fingerId, TouchLocationState.Moved, ToMonoGame(touch.position)); 122 | break; 123 | case TouchPhase.Canceled: 124 | case TouchPhase.Ended: 125 | TouchPanel.AddEvent(touch.fingerId, TouchLocationState.Released, ToMonoGame(touch.position)); 126 | break; 127 | case TouchPhase.Stationary: 128 | //do nothing 129 | break; 130 | } 131 | } 132 | } 133 | 134 | private Vector2 ToMonoGame(UnityEngine.Vector3 vec) 135 | { 136 | return new Vector2(vec.x, Screen.height - vec.y); 137 | } 138 | 139 | public void Exit() 140 | { 141 | Application.Quit(); 142 | } 143 | 144 | public void Dispose() 145 | { 146 | } 147 | 148 | protected virtual void Initialize() 149 | { 150 | } 151 | 152 | protected virtual void LoadContent() 153 | { 154 | } 155 | 156 | protected virtual void Update(GameTime gameTime) 157 | { 158 | } 159 | 160 | protected virtual void Draw(GameTime gameTime) 161 | { 162 | } 163 | 164 | //TODO: work out when to call these from unity 165 | protected virtual void OnDeactivated(object sender, EventArgs args) 166 | { 167 | } 168 | 169 | protected virtual void OnActivated(object sender, EventArgs args) 170 | { 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /MonoGame.Framework/Graphics/Effect/Effect.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Xna.Framework.Graphics 2 | { 3 | public class Effect 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MonoGame.Framework/Graphics/GraphicsDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using Debug = System.Diagnostics.Debug; 5 | using UnityGraphics = UnityEngine.Graphics; 6 | 7 | namespace Microsoft.Xna.Framework.Graphics 8 | { 9 | public class GraphicsDevice : IDisposable 10 | { 11 | public Texture2D[] Textures = new Texture2D[1]; 12 | private Matrix4x4 _matrix; 13 | private Matrix4x4 _baseMatrix; 14 | 15 | internal GraphicsDevice(Viewport viewport) 16 | { 17 | Viewport = viewport; 18 | } 19 | 20 | private Viewport _viewport; 21 | public Viewport Viewport { 22 | get { return _viewport; } 23 | internal set 24 | { 25 | _viewport = value; 26 | _baseMatrix = Matrix4x4.TRS(new UnityEngine.Vector3(-_viewport.Width / 2, _viewport.Height / 2, 0), UnityEngine.Quaternion.identity, new UnityEngine.Vector3(1, -1, 1)); 27 | } 28 | } 29 | public Matrix Matrix 30 | { 31 | set 32 | { 33 | for (var i = 0; i < 4 * 4; i++) 34 | { 35 | _matrix[i] = value[i]; 36 | } 37 | _matrix = _baseMatrix * _matrix; 38 | } 39 | } 40 | 41 | private readonly MaterialPool _materialPool = new MaterialPool(); 42 | private readonly MeshPool _meshPool = new MeshPool(); 43 | 44 | public void DrawUserIndexedPrimitives(PrimitiveType primitiveType, VertexPositionColorTexture[] vertexData, int vertexOffset, int numVertices, short[] indexData, int indexOffset, int primitiveCount, VertexDeclaration vertexDeclaration) 45 | { 46 | Debug.Assert(vertexData != null && vertexData.Length > 0, "The vertexData must not be null or zero length!"); 47 | Debug.Assert(indexData != null && indexData.Length > 0, "The indexData must not be null or zero length!"); 48 | 49 | var material = _materialPool.Get(Textures[0]); 50 | 51 | var mesh = _meshPool.Get(primitiveCount / 2); 52 | mesh.Populate(vertexData, numVertices); 53 | 54 | UnityGraphics.DrawMesh(mesh.Mesh, _matrix, material, 0); 55 | } 56 | 57 | public void ResetPools() 58 | { 59 | _materialPool.Reset(); 60 | _meshPool.Reset(); 61 | } 62 | 63 | public void Clear(Color color) 64 | { 65 | } 66 | 67 | public void Dispose() 68 | { 69 | throw new NotImplementedException(); 70 | } 71 | 72 | private class MaterialPool 73 | { 74 | private class MaterialHolder 75 | { 76 | public readonly Material Material; 77 | public readonly Texture2D Texture2D; 78 | 79 | public MaterialHolder(Material material, Texture2D texture2D) 80 | { 81 | Material = material; 82 | Texture2D = texture2D; 83 | } 84 | } 85 | 86 | private readonly List _materials = new List(); 87 | private int _index; 88 | private readonly Shader _shader = Shader.Find("Custom/SpriteShader"); 89 | 90 | private MaterialHolder Create(Texture2D texture) 91 | { 92 | var mat = new Material(_shader); 93 | mat.mainTexture = texture.Texture; 94 | mat.renderQueue += _materials.Count; 95 | return new MaterialHolder(mat, texture); 96 | } 97 | 98 | public Material Get(Texture2D texture) 99 | { 100 | while (_index < _materials.Count) 101 | { 102 | if (_materials[_index].Texture2D == texture) 103 | { 104 | _index++; 105 | return _materials[_index - 1].Material; 106 | } 107 | 108 | _index++; 109 | } 110 | 111 | var material = Create(texture); 112 | _materials.Add(material); 113 | _index++; 114 | return _materials[_index - 1].Material; 115 | } 116 | 117 | public void Reset() 118 | { 119 | _index = 0; 120 | } 121 | } 122 | 123 | private class MeshHolder 124 | { 125 | public readonly int SpriteCount; 126 | public readonly Mesh Mesh; 127 | 128 | public readonly UnityEngine.Vector3[] Vertices; 129 | public readonly UnityEngine.Vector2[] UVs; 130 | public readonly Color32[] Colors; 131 | 132 | public MeshHolder(int spriteCount) 133 | { 134 | Mesh = new Mesh(); 135 | //Mesh.MarkDynamic(); //Seems to be a win on wp8 136 | 137 | SpriteCount = NextPowerOf2(spriteCount); 138 | int vCount = SpriteCount * 4; 139 | 140 | Vertices = new UnityEngine.Vector3[vCount]; 141 | UVs = new UnityEngine.Vector2[vCount]; 142 | Colors = new Color32[vCount]; 143 | 144 | //Put some random crap in this so we can just set the triangles once 145 | //if these are not populated then unity totally fucks up our mesh and never draws it 146 | for (var i = 0; i < vCount; i++) 147 | { 148 | Vertices[i] = new UnityEngine.Vector3(1, i); 149 | UVs[i] = new UnityEngine.Vector2(0, i); 150 | Colors[i] = new Color32(255, 255, 255, 255); 151 | } 152 | 153 | var triangles = new int[SpriteCount * 6]; 154 | for (var i = 0; i < SpriteCount; i++) 155 | { 156 | /* 157 | * TL TR 158 | * 0----1 0,1,2,3 = index offsets for vertex indices 159 | * | /| TL,TR,BL,BR are vertex references in SpriteBatchItem. 160 | * | / | 161 | * | / | 162 | * |/ | 163 | * 2----3 164 | * BL BR 165 | */ 166 | // Triangle 1 167 | triangles[i * 6 + 0] = i * 4; 168 | triangles[i * 6 + 1] = i * 4 + 1; 169 | triangles[i * 6 + 2] = i * 4 + 2; 170 | // Triangle 2 171 | triangles[i * 6 + 3] = i * 4 + 1; 172 | triangles[i * 6 + 4] = i * 4 + 3; 173 | triangles[i * 6 + 5] = i * 4 + 2; 174 | } 175 | 176 | Mesh.vertices = Vertices; 177 | Mesh.uv = UVs; 178 | Mesh.colors32 = Colors; 179 | Mesh.triangles = triangles; 180 | } 181 | 182 | public void Populate(VertexPositionColorTexture[] vertexData, int numVertices) 183 | { 184 | for (int i = 0; i < numVertices; i++) 185 | { 186 | var p = vertexData[i].Position; 187 | Vertices[i] = new UnityEngine.Vector3(p.X, p.Y, p.Z); 188 | 189 | var uv = vertexData[i].TextureCoordinate; 190 | UVs[i] = new UnityEngine.Vector2(uv.X, 1 - uv.Y); 191 | 192 | var c = vertexData[i].Color; 193 | Colors[i] = new Color32(c.R, c.G, c.B, c.A); 194 | } 195 | //we could clearly less if we remembered how many we used last time 196 | Array.Clear(Vertices, numVertices, Vertices.Length - numVertices); 197 | 198 | Mesh.vertices = Vertices; 199 | Mesh.uv = UVs; 200 | Mesh.colors32 = Colors; 201 | } 202 | 203 | public int NextPowerOf2(int minimum) 204 | { 205 | int result = 1; 206 | 207 | while (result < minimum) 208 | result *= 2; 209 | 210 | return result; 211 | } 212 | } 213 | 214 | 215 | private class MeshPool 216 | { 217 | private List _unusedMeshes = new List(); 218 | private List _usedMeshes = new List(); 219 | 220 | private List _otherMeshes = new List(); 221 | //private int _index; 222 | 223 | /// 224 | /// get a mesh with at least this many triangles 225 | /// 226 | public MeshHolder Get(int spriteCount) 227 | { 228 | MeshHolder best = null; 229 | int bestIndex = -1; 230 | for (int i = 0; i < _unusedMeshes.Count; i++) 231 | { 232 | var unusedMesh = _unusedMeshes[i]; 233 | if ((best == null || best.SpriteCount > unusedMesh.SpriteCount) && unusedMesh.SpriteCount >= spriteCount) 234 | { 235 | best = unusedMesh; 236 | bestIndex = i; 237 | } 238 | } 239 | if (best == null) 240 | { 241 | best = new MeshHolder(spriteCount); 242 | } 243 | else 244 | { 245 | _unusedMeshes.RemoveAt(bestIndex); 246 | } 247 | _usedMeshes.Add(best); 248 | 249 | return best; 250 | } 251 | 252 | public void Reset() 253 | { 254 | //Double Buffer our Meshes (Doesnt seem to be a win on wp8) 255 | //Ref http://forum.unity3d.com/threads/118723-Huge-performance-loss-in-Mesh-CreateVBO-for-dynamic-meshes-IOS 256 | 257 | //meshes from last frame are now unused 258 | _unusedMeshes.AddRange(_otherMeshes); 259 | _otherMeshes.Clear(); 260 | 261 | //swap our use meshes and the now empty other meshes 262 | var temp = _otherMeshes; 263 | _otherMeshes = _usedMeshes; 264 | _usedMeshes = temp; 265 | } 266 | } 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /MonoGame.Framework/Graphics/SpriteBatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using UnityEngine; 4 | 5 | namespace Microsoft.Xna.Framework.Graphics 6 | { 7 | public class SpriteBatch : GraphicsResource 8 | { 9 | readonly SpriteBatcher _batcher; 10 | 11 | SpriteSortMode _sortMode; 12 | //BlendState _blendState; 13 | //SamplerState _samplerState; 14 | //DepthStencilState _depthStencilState; 15 | //RasterizerState _rasterizerState; 16 | //Effect _effect; 17 | bool _beginCalled; 18 | 19 | //Effect _spriteEffect; 20 | //readonly EffectParameter _matrixTransform; 21 | //readonly EffectPass _spritePass; 22 | 23 | Matrix _matrix; 24 | Rectangle _tempRect = new Rectangle (0,0,0,0); 25 | Vector2 _texCoordTL = new Vector2 (0,0); 26 | Vector2 _texCoordBR = new Vector2 (0,0); 27 | 28 | public SpriteBatch (GraphicsDevice graphicsDevice) 29 | { 30 | if (graphicsDevice == null) { 31 | throw new ArgumentException ("graphicsDevice"); 32 | } 33 | 34 | this.GraphicsDevice = graphicsDevice; 35 | 36 | // Use a custom SpriteEffect so we can control the transformation matrix 37 | //_spriteEffect = new Effect(graphicsDevice, SpriteEffect.Bytecode); 38 | //_matrixTransform = _spriteEffect.Parameters["MatrixTransform"]; 39 | //_spritePass = _spriteEffect.CurrentTechnique.Passes[0]; 40 | 41 | _batcher = new SpriteBatcher(graphicsDevice); 42 | 43 | _beginCalled = false; 44 | } 45 | 46 | public void Begin () 47 | { 48 | Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, RasterizerState.CullCounterClockwise, null, Matrix.Identity); 49 | } 50 | 51 | public void Begin (SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix transformMatrix) 52 | { 53 | if (_beginCalled) 54 | throw new InvalidOperationException("Begin cannot be called again until End has been successfully called."); 55 | 56 | // defaults 57 | _sortMode = sortMode; 58 | //_blendState = blendState ?? BlendState.AlphaBlend; 59 | //_samplerState = samplerState ?? SamplerState.LinearClamp; 60 | //_depthStencilState = depthStencilState ?? DepthStencilState.None; 61 | //_rasterizerState = rasterizerState ?? RasterizerState.CullCounterClockwise; 62 | // 63 | //_effect = effect; 64 | 65 | _matrix = transformMatrix; 66 | 67 | // Setup things now so a user can chage them. 68 | if (sortMode == SpriteSortMode.Immediate) 69 | Setup(); 70 | 71 | _beginCalled = true; 72 | } 73 | 74 | public void Begin (SpriteSortMode sortMode, BlendState blendState) 75 | { 76 | Begin (sortMode, blendState, SamplerState.LinearClamp, DepthStencilState.None, RasterizerState.CullCounterClockwise, null, Matrix.Identity); 77 | } 78 | 79 | public void Begin (SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState) 80 | { 81 | Begin (sortMode, blendState, samplerState, depthStencilState, rasterizerState, null, Matrix.Identity); 82 | } 83 | 84 | public void Begin (SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect) 85 | { 86 | Begin (sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, Matrix.Identity); 87 | } 88 | 89 | public void End () 90 | { 91 | _beginCalled = false; 92 | 93 | if (_sortMode != SpriteSortMode.Immediate) 94 | Setup(); 95 | #if PSM 96 | GraphicsDevice.BlendState = _blendState; 97 | _blendState.ApplyState(GraphicsDevice); 98 | #endif 99 | 100 | _batcher.DrawBatch(_sortMode); 101 | } 102 | 103 | void Setup() 104 | { 105 | var gd = GraphicsDevice; 106 | //gd.BlendState = _blendState; 107 | //gd.DepthStencilState = _depthStencilState; 108 | //gd.RasterizerState = _rasterizerState; 109 | //gd.SamplerStates[0] = _samplerState; 110 | 111 | // Setup the default sprite effect. 112 | var vp = gd.Viewport; 113 | 114 | //Matrix projection; 115 | #if PSM || DIRECTX 116 | Matrix.CreateOrthographicOffCenter(0, vp.Width, vp.Height, 0, -1, 0, out projection); 117 | #else 118 | // GL requires a half pixel offset to match DX. 119 | //Matrix.CreateOrthographicOffCenter(0, vp.Width, vp.Height, 0, 0, 1, out projection); 120 | if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor) 121 | { 122 | _matrix.M41 += -0.5f * _matrix.M11; 123 | _matrix.M42 += -0.5f * _matrix.M22; 124 | } 125 | #endif 126 | //Matrix.Multiply(ref _matrix, ref projection, out projection); 127 | 128 | //_matrixTransform.SetValue(projection); 129 | //_spritePass.Apply(); 130 | 131 | gd.Matrix = _matrix; 132 | 133 | // If the user supplied a custom effect then apply 134 | // it now to override the sprite effect. 135 | //if (_effect != null) 136 | // _effect.CurrentTechnique.Passes[0].Apply(); 137 | } 138 | 139 | void CheckValid(Texture2D texture) 140 | { 141 | if (texture == null) 142 | throw new ArgumentNullException("texture"); 143 | if (!_beginCalled) 144 | throw new InvalidOperationException("Draw was called, but Begin has not yet been called. Begin must be called successfully before you can call Draw."); 145 | } 146 | /* 147 | void CheckValid(SpriteFont spriteFont, string text) 148 | { 149 | if (spriteFont == null) 150 | throw new ArgumentNullException("spriteFont"); 151 | if (text == null) 152 | throw new ArgumentNullException("text"); 153 | if (!_beginCalled) 154 | throw new InvalidOperationException("DrawString was called, but Begin has not yet been called. Begin must be called successfully before you can call DrawString."); 155 | } 156 | 157 | void CheckValid(SpriteFont spriteFont, StringBuilder text) 158 | { 159 | if (spriteFont == null) 160 | throw new ArgumentNullException("spriteFont"); 161 | if (text == null) 162 | throw new ArgumentNullException("text"); 163 | if (!_beginCalled) 164 | throw new InvalidOperationException("DrawString was called, but Begin has not yet been called. Begin must be called successfully before you can call DrawString."); 165 | }*/ 166 | 167 | // Overload for calling Draw() with named parameters 168 | /// 169 | /// This is a MonoGame Extension method for calling Draw() using named parameters. It is not available in the standard XNA Framework. 170 | /// 171 | /// 172 | /// The Texture2D to draw. Required. 173 | /// 174 | /// 175 | /// The position to draw at. If left empty, the method will draw at drawRectangle instead. 176 | /// 177 | /// 178 | /// The rectangle to draw at. If left empty, the method will draw at position instead. 179 | /// 180 | /// 181 | /// The source rectangle of the texture. Default is null 182 | /// 183 | /// 184 | /// Origin of the texture. Default is Vector2.Zero 185 | /// 186 | /// 187 | /// Rotation of the texture. Default is 0f 188 | /// 189 | /// 190 | /// The scale of the texture as a Vector2. Default is Vector2.One 191 | /// 192 | /// 193 | /// Color of the texture. Default is Color.White 194 | /// 195 | /// 196 | /// SpriteEffect to draw with. Default is SpriteEffects.None 197 | /// 198 | /// 199 | /// Draw depth. Default is 0f. 200 | /// 201 | public void Draw (Texture2D texture, 202 | Vector2? position = null, 203 | Rectangle? drawRectangle = null, 204 | Rectangle? sourceRectangle = null, 205 | Vector2? origin = null, 206 | float rotation = 0f, 207 | Vector2? scale = null, 208 | Color? color = null, 209 | SpriteEffects effect = SpriteEffects.None, 210 | float depth = 0f) 211 | { 212 | 213 | // Assign default values to null parameters here, as they are not compile-time constants 214 | if(!color.HasValue) 215 | color = Color.White; 216 | if(!origin.HasValue) 217 | origin = Vector2.Zero; 218 | if(!scale.HasValue) 219 | scale = Vector2.One; 220 | 221 | // If both drawRectangle and position are null, or if both have been assigned a value, raise an error 222 | if((drawRectangle.HasValue) == (position.HasValue)) 223 | { 224 | throw new InvalidOperationException("Expected drawRectangle or position, but received neither or both."); 225 | } 226 | else if(position != null) 227 | { 228 | // Call Draw() using position 229 | Draw(texture, (Vector2)position, sourceRectangle, (Color)color, rotation, (Vector2)origin, (Vector2)scale, effect, depth); 230 | } 231 | else 232 | { 233 | // Call Draw() using drawRectangle 234 | Draw(texture, (Rectangle)drawRectangle, sourceRectangle, (Color)color, rotation, (Vector2)origin, effect, depth); 235 | } 236 | } 237 | 238 | 239 | public void Draw (Texture2D texture, 240 | Vector2 position, 241 | Rectangle? sourceRectangle, 242 | Color color, 243 | float rotation, 244 | Vector2 origin, 245 | Vector2 scale, 246 | SpriteEffects effect, 247 | float depth) 248 | { 249 | CheckValid(texture); 250 | 251 | var w = texture.Width * scale.X; 252 | var h = texture.Height * scale.Y; 253 | if (sourceRectangle.HasValue) 254 | { 255 | w = sourceRectangle.Value.Width*scale.X; 256 | h = sourceRectangle.Value.Height*scale.Y; 257 | } 258 | 259 | DrawInternal(texture, 260 | new Vector4(position.X, position.Y, w, h), 261 | sourceRectangle, 262 | color, 263 | rotation, 264 | origin * scale, 265 | effect, 266 | depth); 267 | } 268 | 269 | public void Draw (Texture2D texture, 270 | Vector2 position, 271 | Rectangle? sourceRectangle, 272 | Color color, 273 | float rotation, 274 | Vector2 origin, 275 | float scale, 276 | SpriteEffects effect, 277 | float depth) 278 | { 279 | CheckValid(texture); 280 | 281 | var w = texture.Width * scale; 282 | var h = texture.Height * scale; 283 | if (sourceRectangle.HasValue) 284 | { 285 | w = sourceRectangle.Value.Width * scale; 286 | h = sourceRectangle.Value.Height * scale; 287 | } 288 | 289 | DrawInternal(texture, 290 | new Vector4(position.X, position.Y, w, h), 291 | sourceRectangle, 292 | color, 293 | rotation, 294 | origin * scale, 295 | effect, 296 | depth); 297 | } 298 | 299 | public void Draw (Texture2D texture, 300 | Rectangle destinationRectangle, 301 | Rectangle? sourceRectangle, 302 | Color color, 303 | float rotation, 304 | Vector2 origin, 305 | SpriteEffects effect, 306 | float depth) 307 | { 308 | CheckValid(texture); 309 | 310 | DrawInternal(texture, 311 | new Vector4(destinationRectangle.X, 312 | destinationRectangle.Y, 313 | destinationRectangle.Width, 314 | destinationRectangle.Height), 315 | sourceRectangle, 316 | color, 317 | rotation, 318 | new Vector2(origin.X * ((float)destinationRectangle.Width / (float)( (sourceRectangle.HasValue && sourceRectangle.Value.Width != 0) ? sourceRectangle.Value.Width : texture.Width)), 319 | origin.Y * ((float)destinationRectangle.Height) / (float)( (sourceRectangle.HasValue && sourceRectangle.Value.Height != 0) ? sourceRectangle.Value.Height : texture.Height)), 320 | effect, 321 | depth); 322 | } 323 | 324 | internal void DrawInternal (Texture2D texture, 325 | Vector4 destinationRectangle, 326 | Rectangle? sourceRectangle, 327 | Color color, 328 | float rotation, 329 | Vector2 origin, 330 | SpriteEffects effect, 331 | float depth) 332 | { 333 | var item = _batcher.CreateBatchItem(); 334 | 335 | item.Depth = depth; 336 | item.Texture = texture; 337 | 338 | if (sourceRectangle.HasValue) { 339 | _tempRect = sourceRectangle.Value; 340 | } else { 341 | _tempRect.X = 0; 342 | _tempRect.Y = 0; 343 | _tempRect.Width = texture.Width; 344 | _tempRect.Height = texture.Height; 345 | } 346 | 347 | _texCoordTL.X = _tempRect.X / (float)texture.Width; 348 | _texCoordTL.Y = _tempRect.Y / (float)texture.Height; 349 | _texCoordBR.X = (_tempRect.X + _tempRect.Width) / (float)texture.Width; 350 | _texCoordBR.Y = (_tempRect.Y + _tempRect.Height) / (float)texture.Height; 351 | 352 | if ((effect & SpriteEffects.FlipVertically) != 0) { 353 | var temp = _texCoordBR.Y; 354 | _texCoordBR.Y = _texCoordTL.Y; 355 | _texCoordTL.Y = temp; 356 | } 357 | if ((effect & SpriteEffects.FlipHorizontally) != 0) { 358 | var temp = _texCoordBR.X; 359 | _texCoordBR.X = _texCoordTL.X; 360 | _texCoordTL.X = temp; 361 | } 362 | 363 | item.Set (destinationRectangle.X, 364 | destinationRectangle.Y, 365 | -origin.X, 366 | -origin.Y, 367 | destinationRectangle.Z, 368 | destinationRectangle.W, 369 | (float)Math.Sin (rotation), 370 | (float)Math.Cos (rotation), 371 | color, 372 | _texCoordTL, 373 | _texCoordBR); 374 | 375 | if (_sortMode == SpriteSortMode.Immediate) 376 | _batcher.DrawBatch(_sortMode); 377 | } 378 | 379 | public void Draw (Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color) 380 | { 381 | Draw (texture, position, sourceRectangle, color, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0f); 382 | } 383 | 384 | public void Draw (Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color) 385 | { 386 | Draw (texture, destinationRectangle, sourceRectangle, color, 0, Vector2.Zero, SpriteEffects.None, 0f); 387 | } 388 | 389 | public void Draw (Texture2D texture, Vector2 position, Color color) 390 | { 391 | Draw (texture, position, null, color); 392 | } 393 | 394 | public void Draw (Texture2D texture, Rectangle rectangle, Color color) 395 | { 396 | Draw (texture, rectangle, null, color); 397 | } 398 | /* 399 | public void DrawString (SpriteFont spriteFont, string text, Vector2 position, Color color) 400 | { 401 | CheckValid(spriteFont, text); 402 | 403 | var source = new SpriteFont.CharacterSource(text); 404 | spriteFont.DrawInto ( 405 | this, ref source, position, color, 0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0f); 406 | } 407 | 408 | public void DrawString ( 409 | SpriteFont spriteFont, string text, Vector2 position, Color color, 410 | float rotation, Vector2 origin, float scale, SpriteEffects effects, float depth) 411 | { 412 | CheckValid(spriteFont, text); 413 | 414 | var scaleVec = new Vector2(scale, scale); 415 | var source = new SpriteFont.CharacterSource(text); 416 | spriteFont.DrawInto(this, ref source, position, color, rotation, origin, scaleVec, effects, depth); 417 | } 418 | 419 | public void DrawString ( 420 | SpriteFont spriteFont, string text, Vector2 position, Color color, 421 | float rotation, Vector2 origin, Vector2 scale, SpriteEffects effect, float depth) 422 | { 423 | CheckValid(spriteFont, text); 424 | 425 | var source = new SpriteFont.CharacterSource(text); 426 | spriteFont.DrawInto(this, ref source, position, color, rotation, origin, scale, effect, depth); 427 | } 428 | 429 | public void DrawString (SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color) 430 | { 431 | CheckValid(spriteFont, text); 432 | 433 | var source = new SpriteFont.CharacterSource(text); 434 | spriteFont.DrawInto(this, ref source, position, color, 0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0f); 435 | } 436 | 437 | public void DrawString ( 438 | SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color, 439 | float rotation, Vector2 origin, float scale, SpriteEffects effects, float depth) 440 | { 441 | CheckValid(spriteFont, text); 442 | 443 | var scaleVec = new Vector2 (scale, scale); 444 | var source = new SpriteFont.CharacterSource(text); 445 | spriteFont.DrawInto(this, ref source, position, color, rotation, origin, scaleVec, effects, depth); 446 | } 447 | 448 | public void DrawString ( 449 | SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color, 450 | float rotation, Vector2 origin, Vector2 scale, SpriteEffects effect, float depth) 451 | { 452 | CheckValid(spriteFont, text); 453 | 454 | var source = new SpriteFont.CharacterSource(text); 455 | spriteFont.DrawInto(this, ref source, position, color, rotation, origin, scale, effect, depth); 456 | }*/ 457 | 458 | protected override void Dispose(bool disposing) 459 | { 460 | if (!IsDisposed) 461 | { 462 | if (disposing) 463 | { 464 | //if (_spriteEffect != null) 465 | //{ 466 | // _spriteEffect.Dispose(); 467 | // _spriteEffect = null; 468 | //} 469 | } 470 | } 471 | base.Dispose(disposing); 472 | } 473 | } 474 | } 475 | 476 | -------------------------------------------------------------------------------- /MonoGame.Framework/Graphics/States/BlendState.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Xna.Framework.Graphics 2 | { 3 | public enum BlendState 4 | { 5 | AlphaBlend 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MonoGame.Framework/Graphics/States/DepthStencilState.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Xna.Framework.Graphics 2 | { 3 | public enum DepthStencilState 4 | { 5 | Default, 6 | None 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /MonoGame.Framework/Graphics/States/RasterizerState.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Xna.Framework.Graphics 2 | { 3 | public enum RasterizerState 4 | { 5 | CullNone, 6 | CullCounterClockwise 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /MonoGame.Framework/Graphics/States/SamplerState.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Xna.Framework.Graphics 2 | { 3 | public enum SamplerState 4 | { 5 | LinearClamp 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MonoGame.Framework/Graphics/Texture2D.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityTexture = UnityEngine.Texture2D; 3 | 4 | namespace Microsoft.Xna.Framework.Graphics 5 | { 6 | public class Texture2D 7 | { 8 | internal readonly UnityTexture Texture; 9 | 10 | public Texture2D(UnityTexture texture) 11 | { 12 | if (texture == null) 13 | throw new ArgumentNullException("texture"); 14 | Texture = texture; 15 | } 16 | 17 | public int Width { get { return Texture.width; } } 18 | public int Height { get { return Texture.height; } } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MonoGame.Framework/GraphicsDeviceManager.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Graphics; 3 | 4 | namespace Microsoft.Xna.Framework 5 | { 6 | public class GraphicsDeviceManager 7 | { 8 | public GraphicsDeviceManager(Game game) 9 | { 10 | GraphicsDevice = game.GraphicsDevice; 11 | } 12 | 13 | public DisplayOrientation SupportedOrientations { get; set; } 14 | public bool IsFullScreen { get; set; } 15 | public GraphicsDevice GraphicsDevice { get; private set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MonoGame.Framework/Media/MediaPlayer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Xna.Framework.Audio; 3 | using UnityEngine; 4 | 5 | namespace Microsoft.Xna.Framework.Media 6 | { 7 | public static class MediaPlayer 8 | { 9 | private static readonly AudioSource AudioSource = SoundEffect.GameObject.AddComponent(); 10 | 11 | private static MediaState _mediaState; 12 | public static MediaState State 13 | { 14 | get { return _mediaState; } 15 | private set 16 | { 17 | _mediaState = value; 18 | FireMediaStateChanged(); 19 | } 20 | } 21 | 22 | private static float _currentSongRemainingSeconds; 23 | 24 | public static event EventHandler MediaStateChanged; 25 | 26 | public static void Play(Song song) 27 | { 28 | AudioSource.Stop(); 29 | AudioSource.clip = song.AudioClip; 30 | AudioSource.Play(); 31 | _currentSongRemainingSeconds = song.AudioClip.length * 0.95f; // fudge it a bit as music stops when we lose focus 32 | State = MediaState.Playing; 33 | } 34 | 35 | public static float Volume 36 | { 37 | get 38 | { 39 | return AudioSource.volume; 40 | } 41 | set 42 | { 43 | AudioSource.volume = value; 44 | } 45 | } 46 | 47 | public static void Stop() 48 | { 49 | AudioSource.Stop(); 50 | State = MediaState.Stopped; 51 | } 52 | 53 | public static void Resume() 54 | { 55 | AudioSource.Play(); 56 | State = MediaState.Playing; 57 | } 58 | 59 | public static void Pause() 60 | { 61 | AudioSource.Pause(); 62 | State = MediaState.Paused; 63 | } 64 | 65 | private static void FireMediaStateChanged() 66 | { 67 | if (MediaStateChanged != null) 68 | MediaStateChanged(null, EventArgs.Empty); 69 | } 70 | 71 | internal static void Update(float dt) 72 | { 73 | if (State == MediaState.Playing) 74 | { 75 | _currentSongRemainingSeconds -= dt; 76 | if (_currentSongRemainingSeconds <= 0 && !AudioSource.isPlaying) 77 | { 78 | State = MediaState.Stopped; 79 | } 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /MonoGame.Framework/Media/Song.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Microsoft.Xna.Framework.Media 5 | { 6 | public class Song 7 | { 8 | internal readonly AudioClip AudioClip; 9 | 10 | public Song(AudioClip audioClip) 11 | { 12 | AudioClip = audioClip; 13 | } 14 | 15 | public TimeSpan Duration 16 | { 17 | get { return TimeSpan.FromSeconds(AudioClip.length); } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MonoGame.Framework/UnityGameWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using UnityEngine; 5 | 6 | namespace Microsoft.Xna.Framework 7 | { 8 | internal class UnityGameWindow : GameWindow 9 | { 10 | private readonly GraphicsDevice _graphicsDevice; 11 | private int _width; 12 | private int _height; 13 | 14 | public override bool AllowUserResizing { get; set; } 15 | 16 | public override Rectangle ClientBounds 17 | { 18 | get { return new Rectangle(0, 0, Screen.width, Screen.height); } 19 | } 20 | 21 | public override DisplayOrientation CurrentOrientation 22 | { 23 | get 24 | { 25 | if (Screen.width > Screen.height) 26 | return DisplayOrientation.LandscapeLeft; 27 | return DisplayOrientation.Portrait; 28 | } 29 | } 30 | 31 | public override IntPtr Handle 32 | { 33 | get { throw new NotImplementedException(); } 34 | } 35 | 36 | public override string ScreenDeviceName 37 | { 38 | get { throw new NotImplementedException(); } 39 | } 40 | 41 | public override void BeginScreenDeviceChange(bool willBeFullScreen) 42 | { 43 | throw new NotImplementedException(); 44 | } 45 | 46 | public override void EndScreenDeviceChange(string screenDeviceName, int clientWidth, int clientHeight) 47 | { 48 | throw new NotImplementedException(); 49 | } 50 | 51 | protected internal override void SetSupportedOrientations(DisplayOrientation orientations) 52 | { 53 | //throw new NotImplementedException(); 54 | } 55 | 56 | protected override void SetTitle(string title) 57 | { 58 | throw new NotImplementedException(); 59 | } 60 | 61 | internal UnityGameWindow(GraphicsDevice graphicsDevice) 62 | { 63 | _graphicsDevice = graphicsDevice; 64 | _width = Screen.width; 65 | _height = Screen.height; 66 | } 67 | 68 | internal void Update() 69 | { 70 | var width = Screen.width; 71 | var height = Screen.height; 72 | 73 | if (_width != width || _height != height) 74 | { 75 | _width = width; 76 | _height = height; 77 | 78 | _graphicsDevice.Viewport = new Viewport(0, 0, width, height); 79 | 80 | OnOrientationChanged(); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | XnaUnitySpriteBatch 2 | =================== 3 | 4 | Provides a Xna SpriteBatch implementation for Unity use, allowing for quick and rough porting of Xna projects to Unity. 5 | 6 | Related reading: 7 | - http://shadowmint.blogspot.com/2012/11/display-textured-2d-quad-in-unity-using.html 8 | - http://docs.unity3d.com/Documentation/Manual/UsingDLL.html 9 | 10 | Most of the code is based on MonoGame, we reuse classes where possible and replace them when necessary. 11 | Some classes are cludged around for features that we do not support. 12 | The csproj expects that MonoGame is checked out adjacent to it, and references the MonoGame files via links. 13 | 14 | To use this with unity: create a new solution file with your game code, reference this, build and then place the DLLs in the unity assets folder. 15 | See the unity documentation linked above for more details. 16 | 17 | List of classes that we have replaced: 18 | ``` 19 | Audio/SoundEffect 20 | Content/ContentManager 21 | Graphics/Effect/Effect 22 | Graphics/GraphicsDevice 23 | Graphics/States/* 24 | Graphics/SpriteBatch (this is based on a copy/paste of the MonoGame implementation) 25 | Graphics/Texture2D 26 | Media/Song 27 | Game 28 | GraphicsDeviceManager 29 | ``` 30 | 31 | To use: 32 | - Set up a unity GameObject 33 | - In the constructor create your game object and call UnityInitialise 34 | - Add a FixedUpdate function and call UnityFixedUpdate 35 | - Add a Update function and call UnityUpdate 36 | -------------------------------------------------------------------------------- /XnaUnitySpriteBatch.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {85A5727F-E2BD-4652-9FF6-9AD710F696E2} 8 | Library 9 | Properties 10 | Microsoft.Xna.Framework 11 | XnaUnitySpriteBatch 12 | v3.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | TRACE;DEBUG;UNITY 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE;UNITY 29 | prompt 30 | 4 31 | 32 | 33 | bin\Unity-WinRt\ 34 | TRACE;WINRT1 35 | true 36 | pdbonly 37 | AnyCPU 38 | prompt 39 | MinimumRecommendedRules.ruleset 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll 51 | 52 | 53 | 54 | 55 | MonoGame.Framework\BoundingBox.cs 56 | 57 | 58 | MonoGame.Framework\BoundingFrustum.cs 59 | 60 | 61 | MonoGame.Framework\BoundingSphere.cs 62 | 63 | 64 | MonoGame.Framework\Color.cs 65 | 66 | 67 | MonoGame.Framework\ContainmentType.cs 68 | 69 | 70 | MonoGame.Framework\DisplayOrientation.cs 71 | 72 | 73 | MonoGame.Framework\GameTime.cs 74 | 75 | 76 | MonoGame.Framework\GameWindow.cs 77 | 78 | 79 | MonoGame.Framework\Graphics\GraphicsExtensions.cs 80 | 81 | 82 | MonoGame.Framework\Graphics\GraphicsResource.cs 83 | 84 | 85 | MonoGame.Framework\Graphics\PresentInterval.cs 86 | 87 | 88 | MonoGame.Framework\Graphics\SpriteBatcher.cs 89 | 90 | 91 | MonoGame.Framework\Graphics\SpriteBatchItem.cs 92 | 93 | 94 | MonoGame.Framework\Graphics\SpriteEffects.cs 95 | 96 | 97 | MonoGame.Framework\Graphics\SpriteSortMode.cs 98 | 99 | 100 | MonoGame.Framework\Graphics\SurfaceFormat.cs 101 | 102 | 103 | MonoGame.Framework\Graphics\Vertices\IVertexType.cs 104 | 105 | 106 | MonoGame.Framework\Graphics\Vertices\PrimitiveType.cs 107 | 108 | 109 | MonoGame.Framework\Graphics\Vertices\VertexDeclaration.cs 110 | 111 | 112 | MonoGame.Framework\Graphics\Vertices\VertexElement.cs 113 | 114 | 115 | MonoGame.Framework\Graphics\Vertices\VertexElementFormat.cs 116 | 117 | 118 | MonoGame.Framework\Graphics\Vertices\VertexElementUsage.cs 119 | 120 | 121 | MonoGame.Framework\Graphics\Vertices\VertexPositionColorTexture.cs 122 | 123 | 124 | MonoGame.Framework\Graphics\Viewport.cs 125 | 126 | 127 | MonoGame.Framework\Input\ButtonState.cs 128 | 129 | 130 | MonoGame.Framework\Input\MouseState.cs 131 | 132 | 133 | MonoGame.Framework\Input\Touch\GestureSample.cs 134 | 135 | 136 | MonoGame.Framework\Input\Touch\GestureType.cs 137 | 138 | 139 | MonoGame.Framework\Input\Touch\TouchCollection.cs 140 | 141 | 142 | MonoGame.Framework\Input\Touch\TouchLocation.cs 143 | 144 | 145 | MonoGame.Framework\Input\Touch\TouchLocationState.cs 146 | 147 | 148 | MonoGame.Framework\Input\Touch\TouchPanel.cs 149 | 150 | 151 | MonoGame.Framework\Input\Touch\TouchPanelCapabilities.cs 152 | 153 | 154 | MonoGame.Framework\MathHelper.cs 155 | 156 | 157 | MonoGame.Framework\Matrix.cs 158 | 159 | 160 | MonoGame.Framework\Media\MediaState.cs 161 | 162 | 163 | MonoGame.Framework\Plane.cs 164 | 165 | 166 | MonoGame.Framework\PlaneIntersectionType.cs 167 | 168 | 169 | MonoGame.Framework\Point.cs 170 | 171 | 172 | MonoGame.Framework\Quaternion.cs 173 | 174 | 175 | MonoGame.Framework\Ray.cs 176 | 177 | 178 | MonoGame.Framework\Rectangle.cs 179 | 180 | 181 | MonoGame.Framework\Utilities\Hash.cs 182 | 183 | 184 | MonoGame.Framework\Vector2.cs 185 | 186 | 187 | MonoGame.Framework\Vector3.cs 188 | 189 | 190 | MonoGame.Framework\Vector4.cs 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 | 223 | --------------------------------------------------------------------------------