diff --git a/MonoGame.Framework/Audio/SoundEffect.cs b/MonoGame.Framework/Audio/SoundEffect.cs index b55cdc9f794..9795d98740a 100644 --- a/MonoGame.Framework/Audio/SoundEffect.cs +++ b/MonoGame.Framework/Audio/SoundEffect.cs @@ -306,10 +306,12 @@ public string Name public SoundEffectInstance CreateInstance() { - var instance = new SoundEffectInstance(); #if WINRT - instance._effect = this; - instance._voice = new SourceVoice(SoundEffect.Device, _format, VoiceFlags.None, XAudio2.MaximumFrequencyRatio); + SourceVoice voice = null; + if (Device != null) + voice = new SourceVoice(Device, _format, VoiceFlags.None, XAudio2.MaximumFrequencyRatio); + + var instance = new SoundEffectInstance(this, voice); #else instance.Sound = _sound; #endif @@ -391,8 +393,8 @@ public static float MasterVolume } #if WINRT - public static XAudio2 Device; - public static MasteringVoice MasterVoice; + internal static XAudio2 Device { get; private set; } + internal static MasteringVoice MasterVoice { get; private set; } private static bool _device3DDirty = true; private static Speakers _speakers = Speakers.Stereo; @@ -417,7 +419,7 @@ public static Speakers Speakers private static X3DAudio _device3D; - public static X3DAudio Device3D + internal static X3DAudio Device3D { get { @@ -433,15 +435,29 @@ public static X3DAudio Device3D static SoundEffect() { + // This cannot fail. Device = new XAudio2(); - Device.StartEngine(); - // Let windows autodetect number of channels and sample rate. - MasterVoice = new MasteringVoice(Device, XAudio2.DefaultChannels, XAudio2.DefaultSampleRate); - MasterVoice.SetVolume(_masterVolume, 0); + try + { + Device.StartEngine(); + + // Let windows autodetect number of channels and sample rate. + MasterVoice = new MasteringVoice(Device, XAudio2.DefaultChannels, XAudio2.DefaultSampleRate); + MasterVoice.SetVolume(_masterVolume, 0); + + // The autodetected value of MasterVoice.ChannelMask corresponds to the speaker layout. + Speakers = (Speakers)MasterVoice.ChannelMask; + } + catch + { + // Release the device and null it as + // we have no audio support. + Device.Dispose(); + Device = null; + MasterVoice = null; + } - // The autodetected value of MasterVoice.ChannelMask corresponds to the speaker layout. - Speakers = (Speakers)MasterVoice.ChannelMask; } // Does someone actually need to call this if it only happens when the whole diff --git a/MonoGame.Framework/Audio/SoundEffectInstance.cs b/MonoGame.Framework/Audio/SoundEffectInstance.cs index 74804b23600..b1f65f687a2 100644 --- a/MonoGame.Framework/Audio/SoundEffectInstance.cs +++ b/MonoGame.Framework/Audio/SoundEffectInstance.cs @@ -60,8 +60,8 @@ public sealed class SoundEffectInstance : IDisposable #endif #if WINRT - internal SourceVoice _voice { get; set; } - internal SoundEffect _effect { get; set; } + private SourceVoice _voice { get; set; } + private SoundEffect _effect { get; set; } private bool _paused; private bool _loop; @@ -81,17 +81,24 @@ internal Sound Sound } #endif - internal SoundEffectInstance() - { - } - +#if WINRT + internal SoundEffectInstance(SoundEffect effect, SourceVoice voice) + { + _effect = effect; + _voice = voice; + } +#endif + public void Dispose() { #if WINRT - _voice.DestroyVoice(); - _voice.Dispose(); - _voice = null; - _effect = null; + if (_voice != null) + { + _voice.DestroyVoice(); + _voice.Dispose(); + _voice = null; + } + _effect = null; #elif ANDROID if (_streamId >= 0) _sound.Stop(_streamId); @@ -105,7 +112,11 @@ public void Dispose() public void Apply3D (AudioListener listener, AudioEmitter emitter) { -#if WINRT +#if WINRT + // If we have no voice then nothing to do. + if (_voice == null) + return; + // Convert from XNA Emitter to a SharpDX Emitter var e = emitter.ToEmitter(); e.CurveDistanceScaler = SoundEffect.DistanceScale; @@ -141,8 +152,9 @@ public void Apply3D (AudioListener[] listeners,AudioEmitter emitter) public void Pause () { -#if WINRT - _voice.Stop(); +#if WINRT + if (_voice != null) + _voice.Stop(); _paused = true; #else if ( _sound != null ) @@ -159,20 +171,23 @@ public void Pause () public void Play () { -#if WINRT - // Choose the correct buffer depending on if we are looped. - var buffer = _loop ? _effect._loopedBuffer : _effect._buffer; - - if (_voice.State.BuffersQueued > 0) +#if WINRT + if (_voice != null) { - _voice.Stop(); - _voice.FlushSourceBuffers(); - } + // Choose the correct buffer depending on if we are looped. + var buffer = _loop ? _effect._loopedBuffer : _effect._buffer; - _voice.SubmitSourceBuffer(buffer, null); - _voice.Start(); + if (_voice.State.BuffersQueued > 0) + { + _voice.Stop(); + _voice.FlushSourceBuffers(); + } - _paused = false; + _voice.SubmitSourceBuffer(buffer, null); + _voice.Start(); + } + + _paused = false; #else if ( _sound != null ) { @@ -195,7 +210,8 @@ public void Play () public void Resume() { #if WINRT - _voice.Start(); + if (_voice != null) + _voice.Start(); _paused = false; #else if ( _sound != null ) @@ -216,9 +232,13 @@ public void Resume() public void Stop() { #if WINRT - _voice.Stop(0); - _voice.FlushSourceBuffers(); - _paused = false; + if (_voice != null) + { + _voice.Stop(0); + _voice.FlushSourceBuffers(); + } + + _paused = false; #else if ( _sound != null ) { @@ -236,7 +256,9 @@ public void Stop() public void Stop(bool immediate) { #if WINRT - _voice.Stop( immediate ? 0 : (int)PlayFlags.Tails ); + if (_voice != null) + _voice.Stop(immediate ? 0 : (int)PlayFlags.Tails); + _paused = false; #else if ( _sound != null ) @@ -319,10 +341,14 @@ public float Pan set { -#if WINRT +#if WINRT // According to XNA documentation: // "Panning, ranging from -1.0f (full left) to 1.0f (full right). 0.0f is centered." _pan = MathHelper.Clamp(value, -1.0f, 1.0f); + + // If we have no voice then nothing more to do. + if (_voice == null) + return; var srcChannelCount = _effect._format.Channels; var dstChannelCount = SoundEffect.MasterVoice.VoiceDetails.InputChannelCount; @@ -420,6 +446,9 @@ public float Pitch get { #if WINRT + if (_voice == null) + return 0.0f; + // NOTE: This is copy of what XAudio2.FrequencyRatioToSemitones() does // which avoids the native call and is actually more accurate. var pitch = 39.86313713864835 * Math.Log10(_voice.FrequencyRatio); @@ -439,6 +468,9 @@ public float Pitch set { #if WINRT + if (_voice == null) + return; + // NOTE: This is copy of what XAudio2.SemitonesToFrequencyRatio() does // which avoids the native call and is actually more accurate. var ratio = Math.Pow(2.0, value); @@ -457,11 +489,9 @@ public SoundState State get { #if WINRT - // If no buffers queued the sound is stopped. - if (_voice.State.BuffersQueued == 0) - { + // If no voice or no buffers queued the sound is stopped. + if (_voice == null || _voice.State.BuffersQueued == 0) return SoundState.Stopped; - } // Because XAudio2 does not actually provide if a SourceVoice is Started / Stopped // we have to save the "paused" state ourself. @@ -498,7 +528,10 @@ public float Volume get { #if WINRT - return _voice.Volume; + if (_voice == null) + return 0.0f; + else + return _voice.Volume; #else if (_sound != null) { @@ -514,7 +547,8 @@ public float Volume set { #if WINRT - _voice.SetVolume(value, XAudio2.CommitNow); + if (_voice != null) + _voice.SetVolume(value, XAudio2.CommitNow); #else if ( _sound != null ) { diff --git a/MonoGame.Framework/Content/ContentManager.cs b/MonoGame.Framework/Content/ContentManager.cs index f9c42f02125..2918dac47ef 100644 --- a/MonoGame.Framework/Content/ContentManager.cs +++ b/MonoGame.Framework/Content/ContentManager.cs @@ -260,10 +260,7 @@ protected T ReadAsset(string assetName, Action recordDisposableO { throw new ObjectDisposedException("ContentManager"); } - - var lastPathSeparatorIndex = Math.Max(assetName.LastIndexOf('\\'), assetName.LastIndexOf('/')); - CurrentAssetDirectory = lastPathSeparatorIndex == -1 ? RootDirectory : assetName.Substring(0, lastPathSeparatorIndex); - + string originalAssetName = assetName; object result = null; @@ -333,8 +330,6 @@ protected T ReadAsset(string assetName, Action recordDisposableO if (result == null) throw new ContentLoadException("Could not load " + originalAssetName + " asset!"); - CurrentAssetDirectory = null; - return (T)result; } @@ -676,8 +671,6 @@ internal string RootDirectoryFullPath } } - public string CurrentAssetDirectory { get; set; } - public IServiceProvider ServiceProvider { get diff --git a/MonoGame.Framework/Content/ContentReaders/EffectMaterialReader.cs b/MonoGame.Framework/Content/ContentReaders/EffectMaterialReader.cs index 706aeee7390..895832b9755 100644 --- a/MonoGame.Framework/Content/ContentReaders/EffectMaterialReader.cs +++ b/MonoGame.Framework/Content/ContentReaders/EffectMaterialReader.cs @@ -40,7 +40,8 @@ 1. Definitions using System; using System.Collections.Generic; - +using System.Diagnostics; +using System.Reflection; using Microsoft.Xna.Framework.Graphics; namespace Microsoft.Xna.Framework.Content @@ -57,15 +58,18 @@ protected internal override EffectMaterial Read (ContentReader input, EffectMate foreach (KeyValuePair item in dict) { var parameter = effectMaterial.Parameters [item.Key]; if (parameter != null) { - if (typeof(Texture).IsAssignableFrom (item.Value.GetType ())) { +#if WINRT + if (typeof(Texture).GetTypeInfo().IsAssignableFrom(item.Value.GetType().GetTypeInfo())) +#else + if (typeof(Texture).IsAssignableFrom(item.Value.GetType())) +#endif + { parameter.SetValue ((Texture)item.Value); } else { throw new NotImplementedException (); } } else { -#if DEBUG - Console.WriteLine ("No parameter " + item.Key); -#endif + Debug.WriteLine ("No parameter " + item.Key); } } diff --git a/MonoGame.Framework/Content/ContentReaders/SongReader.cs b/MonoGame.Framework/Content/ContentReaders/SongReader.cs index febce1208e9..7b7aee55ddd 100644 --- a/MonoGame.Framework/Content/ContentReaders/SongReader.cs +++ b/MonoGame.Framework/Content/ContentReaders/SongReader.cs @@ -37,16 +37,16 @@ // purpose and non-infringement. // */ // #endregion License -// - +// + using System; using System.IO; -using Microsoft.Xna.Framework.Media; - -namespace Microsoft.Xna.Framework.Content -{ - internal class SongReader : ContentTypeReader +using Microsoft.Xna.Framework.Media; + +namespace Microsoft.Xna.Framework.Content +{ + internal class SongReader : ContentTypeReader { #if ANDROID static string[] supportedExtensions = new string[] { ".mp3", ".ogg", ".mid" }; @@ -63,13 +63,34 @@ protected internal override Song Read(ContentReader input, Song existingInstance { string path = input.ReadString(); - // Songs don't have the full directory path in their .xnb. Build it. - path = Path.Combine (input.ContentManager.RootDirectory, input.ContentManager.CurrentAssetDirectory, path); - path = TitleContainer.GetFilename(path); - + if (!String.IsNullOrEmpty(path)) + { +#if WINRT + const char notSeparator = '/'; + const char separator = '\\'; +#else + const char notSeparator = '\\'; + var separator = Path.DirectorySeparatorChar; +#endif + path = path.Replace(notSeparator, separator); + + // Get a uri for the asset path using the file:// schema and no host + var src = new Uri("file:///" + input.AssetName.Replace(notSeparator, separator)); + + // Add the relative path to the external reference + var dst = new Uri(src, path); + + // The uri now contains the path to the external reference within the content manager + // Get the local path and skip the first character (the path separator) + path = dst.LocalPath.Substring(1); + + // Adds the ContentManager's RootDirectory + path = input.ContentManager.RootDirectory + separator + path; + } + /*int durationMS =*/ input.ReadObject(); return new Song(path); - } - } -} + } + } +} diff --git a/MonoGame.Framework/Content/ContentTypeReaderManager.cs b/MonoGame.Framework/Content/ContentTypeReaderManager.cs index ae3698692a3..552aabfad49 100644 --- a/MonoGame.Framework/Content/ContentTypeReaderManager.cs +++ b/MonoGame.Framework/Content/ContentTypeReaderManager.cs @@ -108,6 +108,8 @@ internal ContentTypeReader[] LoadAssetReaders() var hArrayMatrixReader = new ArrayReader(); var hEnumBlendReader = new EnumReader(); var hNullableRectReader = new NullableReader(); + var hEffectMaterialReader = new EffectMaterialReader(); + var hExternalReferenceReader = new ExternalReferenceReader(); } #pragma warning restore 0219, 0649 diff --git a/MonoGame.Framework/DrawableGameComponent.cs b/MonoGame.Framework/DrawableGameComponent.cs index 94c6c873ddc..d763d8b63fe 100644 --- a/MonoGame.Framework/DrawableGameComponent.cs +++ b/MonoGame.Framework/DrawableGameComponent.cs @@ -46,7 +46,7 @@ public class DrawableGameComponent : GameComponent, IDrawable { private bool _initialized; private int _drawOrder; - private bool _visible; + private bool _visible = true; public int DrawOrder { @@ -84,7 +84,6 @@ public bool Visible public DrawableGameComponent(Game game) : base(game) { - Visible = true; } public override void Initialize() diff --git a/MonoGame.Framework/Game.cs b/MonoGame.Framework/Game.cs index 1ba3841680f..f0a7e7c73e5 100644 --- a/MonoGame.Framework/Game.cs +++ b/MonoGame.Framework/Game.cs @@ -123,6 +123,7 @@ public class Game : IDisposable private bool _isFixedTimeStep = true; private TimeSpan _targetElapsedTime = TimeSpan.FromSeconds(1 / DefaultTargetFramesPerSecond); + private TimeSpan _inactiveSleepTime = TimeSpan.FromSeconds(1); private readonly TimeSpan _maxElapsedTime = TimeSpan.FromMilliseconds(500); @@ -244,8 +245,14 @@ public GameComponentCollection Components public TimeSpan InactiveSleepTime { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } + get { return _inactiveSleepTime; } + set + { + if (_inactiveSleepTime != value) + { + _inactiveSleepTime = value; + } + } } public bool IsActive diff --git a/MonoGame.Framework/GameComponent.cs b/MonoGame.Framework/GameComponent.cs index b6482660b92..164dc814dee 100644 --- a/MonoGame.Framework/GameComponent.cs +++ b/MonoGame.Framework/GameComponent.cs @@ -44,7 +44,7 @@ namespace Microsoft.Xna.Framework { public class GameComponent : IGameComponent, IUpdateable, IComparable, IDisposable { - bool _enabled; + bool _enabled = true; int _updateOrder; public Game Game { get; private set; } @@ -90,7 +90,6 @@ public int UpdateOrder public GameComponent(Game game) { this.Game = game; - this.Enabled = true; } ~GameComponent() diff --git a/MonoGame.Framework/Graphics/Effect/EffectParameter.cs b/MonoGame.Framework/Graphics/Effect/EffectParameter.cs index 367b40918d4..62eef11d023 100644 --- a/MonoGame.Framework/Graphics/Effect/EffectParameter.cs +++ b/MonoGame.Framework/Graphics/Effect/EffectParameter.cs @@ -267,6 +267,18 @@ public void SetValue (Matrix value) StateKey = unchecked(NextStateKey++); } + public void SetValueTranspose(Matrix value) + { + var matrixData = Matrix.ToFloatArray(value); + for (var y = 0; y < RowCount; y++) + { + for (var x = 0; x < ColumnCount; x++) + ((float[])Data)[y * ColumnCount + x] = matrixData[y * 4 + x]; + } + + StateKey = unchecked(NextStateKey++); + } + public void SetValue (Matrix[] value) { for (var i = 0; i < value.Length; i++) diff --git a/MonoGame.Framework/Graphics/Shader/Shader.cs b/MonoGame.Framework/Graphics/Shader/Shader.cs index 3c22c8f1112..8bf78bb0947 100644 --- a/MonoGame.Framework/Graphics/Shader/Shader.cs +++ b/MonoGame.Framework/Graphics/Shader/Shader.cs @@ -224,8 +224,8 @@ internal int GetAttribLocation(VertexElementUsage usage, int index) { for (int i = 0; i < _attributes.Length; ++i) { - if (_attributes[i].usage == usage) - return _attributes[i].location + index; + if ((_attributes[i].usage == usage) && (_attributes[i].index == index)) + return _attributes[i].location; } return -1; } diff --git a/MonoGame.Framework/Graphics/Texture2D.cs b/MonoGame.Framework/Graphics/Texture2D.cs index 1acff3a5ab5..0702d87c5de 100644 --- a/MonoGame.Framework/Graphics/Texture2D.cs +++ b/MonoGame.Framework/Graphics/Texture2D.cs @@ -633,48 +633,52 @@ public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream) return texture; } #elif ANDROID - // Work-around for "The program 'Mono' has exited with code 255 (0xff)." - // Based on http://stackoverflow.com/questions/7535503/mono-for-android-exit-code-255-on-bitmapfactory-decodestream - //Bitmap image = BitmapFactory.DecodeStream(stream); - Bitmap image = null; - using (MemoryStream memStream = new MemoryStream()) - { - stream.CopyTo(memStream); - image = BitmapFactory.DecodeByteArray(memStream.GetBuffer(), 0, (int)memStream.Length); - } - var width = image.Width; - var height = image.Height; - - int[] pixels = new int[width * height]; - if ((width != image.Width) || (height != image.Height)) + using (Bitmap image = BitmapFactory.DecodeStream(stream, null, new BitmapFactory.Options { - Bitmap imagePadded = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888); - Canvas canvas = new Canvas(imagePadded); - canvas.DrawARGB(0, 0, 0, 0); - canvas.DrawBitmap(image, 0, 0, null); - imagePadded.GetPixels(pixels, 0, width, 0, 0, width, height); - } - else + InScaled = false, + InDither = false, + InJustDecodeBounds = false, + InPurgeable = true, + InInputShareable = true, + })) { - image.GetPixels(pixels, 0, width, 0, 0, width, height); - } + var width = image.Width; + var height = image.Height; - // Convert from ARGB to ABGR - for (int i = 0; i < width * height; ++i) - { - uint pixel = (uint)pixels[i]; - pixels[i] = (int)((pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16)); - } + int[] pixels = new int[width * height]; + if ((width != image.Width) || (height != image.Height)) + { + using (Bitmap imagePadded = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888)) + { + Canvas canvas = new Canvas(imagePadded); + canvas.DrawARGB(0, 0, 0, 0); + canvas.DrawBitmap(image, 0, 0, null); + imagePadded.GetPixels(pixels, 0, width, 0, 0, width, height); + imagePadded.Recycle(); + } + } + else + { + image.GetPixels(pixels, 0, width, 0, 0, width, height); + } + image.Recycle(); - Texture2D texture = null; - Threading.BlockOnUIThread(() => - { - texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color); - texture.SetData(pixels); - }); + // Convert from ARGB to ABGR + for (int i = 0; i < width * height; ++i) + { + uint pixel = (uint)pixels[i]; + pixels[i] = (int)((pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16)); + } - return texture; - + Texture2D texture = null; + Threading.BlockOnUIThread(() => + { + texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color); + texture.SetData(pixels); + }); + + return texture; + } #elif WINRT // For reference this implementation was ultimately found through this post: // http://stackoverflow.com/questions/9602102/loading-textures-with-sharpdx-in-metro @@ -721,29 +725,31 @@ public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream) private void FillTextureFromStream(Stream stream) { #if ANDROID - // Work-around for "The program 'Mono' has exited with code 255 (0xff)." - // Based on http://stackoverflow.com/questions/7535503/mono-for-android-exit-code-255-on-bitmapfactory-decodestream - //Bitmap image = BitmapFactory.DecodeStream(stream); - Bitmap image = null; - using (MemoryStream memStream = new MemoryStream()) + using (Bitmap image = BitmapFactory.DecodeStream(stream, null, new BitmapFactory.Options { - stream.CopyTo(memStream); - image = BitmapFactory.DecodeByteArray(memStream.GetBuffer(), 0, (int)memStream.Length); - } - var width = image.Width; - var height = image.Height; + InScaled = false, + InDither = false, + InJustDecodeBounds = false, + InPurgeable = true, + InInputShareable = true, + })) + { + var width = image.Width; + var height = image.Height; - int[] pixels = new int[width * height]; - image.GetPixels(pixels, 0, width, 0, 0, width, height); + int[] pixels = new int[width * height]; + image.GetPixels(pixels, 0, width, 0, 0, width, height); - // Convert from ARGB to ABGR - for (int i = 0; i < width * height; ++i) - { - uint pixel = (uint)pixels[i]; - pixels[i] = (int)((pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16)); + // Convert from ARGB to ABGR + for (int i = 0; i < width * height; ++i) + { + uint pixel = (uint)pixels[i]; + pixels[i] = (int)((pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16)); + } + + this.SetData(pixels); + image.Recycle(); } - - this.SetData(pixels); #endif } diff --git a/MonoGame.Framework/Graphics/Vertices/VertexBuffer.cs b/MonoGame.Framework/Graphics/Vertices/VertexBuffer.cs index a8fb193201d..c05c9dbd9e4 100644 --- a/MonoGame.Framework/Graphics/Vertices/VertexBuffer.cs +++ b/MonoGame.Framework/Graphics/Vertices/VertexBuffer.cs @@ -117,8 +117,8 @@ protected VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDe throw new InvalidOperationException ("The array specified in the data parameter is not the correct size for the amount of data requested."); if (BufferUsage == BufferUsage.WriteOnly) throw new NotSupportedException ("This VertexBuffer was created with a usage type of BufferUsage.WriteOnly. Calling GetData on a resource that was created with BufferUsage.WriteOnly is not supported."); - if ((vertexStride > (VertexCount * VertexDeclaration.VertexStride)) || (vertexStride < VertexDeclaration.VertexStride)) - throw new ArgumentOutOfRangeException ("One of the following conditions is true:\nThe vertex stride is larger than the vertex buffer.\nThe vertex stride is too small for the type of data requested."); + if ((elementCount * vertexStride) > (VertexCount * VertexDeclaration.VertexStride)) + throw new ArgumentOutOfRangeException ("The vertex stride is larger than the vertex buffer."); #if DIRECTX throw new NotImplementedException(); @@ -146,15 +146,27 @@ protected VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDe Marshal.Copy (ptr, buffer, 0, buffer.Length); } else { // Temporary buffer to store the copied section of data - byte[] buffer = new byte[elementCount * vertexStride]; + byte[] buffer = new byte[elementCount * vertexStride - offsetInBytes]; // Copy from the vertex buffer to the temporary buffer - Marshal.Copy (ptr, buffer, 0, buffer.Length); - // Copy from the temporary buffer to the destination array + Marshal.Copy(ptr, buffer, 0, buffer.Length); - var dataHandle = GCHandle.Alloc (data, GCHandleType.Pinned); + var dataHandle = GCHandle.Alloc (data, GCHandleType.Pinned); var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject ().ToInt64 () + startIndex * elementSizeInByte); - Marshal.Copy (buffer, 0, dataPtr, buffer.Length); + // Copy from the temporary buffer to the destination array + + int dataSize = Marshal.SizeOf(typeof(T)); + if (dataSize == vertexStride) + Marshal.Copy(buffer, 0, dataPtr, buffer.Length); + else + { + // If the user is asking for a specific element within the vertex buffer, copy them one by one... + for (int i = 0; i < elementCount; i++) + { + Marshal.Copy(buffer, i * vertexStride, dataPtr, dataSize); + dataPtr = (IntPtr)(dataPtr.ToInt64() + dataSize); + } + } dataHandle.Free (); diff --git a/MonoGame.Framework/MacOS/GameWindow.cs b/MonoGame.Framework/MacOS/GameWindow.cs index 1cfd7399cbd..f7da7f17f32 100644 --- a/MonoGame.Framework/MacOS/GameWindow.cs +++ b/MonoGame.Framework/MacOS/GameWindow.cs @@ -383,10 +383,12 @@ public override void TouchesCancelled (NSSet touches, UIEvent evt) set { if (value) - Window.StyleMask |= NSWindowStyle.Resizable; + Window.StyleMask |= NSWindowStyle.Resizable; else Window.StyleMask &= ~NSWindowStyle.Resizable; - } + + Window.StandardWindowButton(NSWindowButton.ZoomButton).Enabled = value; + } } private DisplayOrientation _currentOrientation; diff --git a/MonoGame.Framework/MacOS/MacGamePlatform.cs b/MonoGame.Framework/MacOS/MacGamePlatform.cs index 5c83d10d890..9e2e38de4db 100644 --- a/MonoGame.Framework/MacOS/MacGamePlatform.cs +++ b/MonoGame.Framework/MacOS/MacGamePlatform.cs @@ -122,7 +122,7 @@ private void InitializeMainWindow() GraphicsDeviceManager.DefaultBackBufferHeight); _mainWindow = new MacGameNSWindow( - frame, NSWindowStyle.Titled | NSWindowStyle.Closable, + frame, NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable, NSBackingStore.Buffered, true); _mainWindow.WindowController = new NSWindowController(_mainWindow); @@ -330,7 +330,7 @@ public override void ExitFullScreen() string oldTitle = _gameWindow.Title; NSMenu.MenuBarVisible = true; - _mainWindow.StyleMask = NSWindowStyle.Titled | NSWindowStyle.Closable; + _mainWindow.StyleMask = NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable; if (_wasResizeable) _mainWindow.StyleMask |= NSWindowStyle.Resizable; @@ -494,6 +494,11 @@ public override void WillClose(NSNotification notification) NSApplication.SharedApplication.BeginInvokeOnMainThread(() => _owner.State = MacGamePlatform.RunState.Exited); } + + public override bool ShouldZoom (NSWindow window, RectangleF newFrame) + { + return _owner.AllowUserResizing; + } } } } diff --git a/MonoGame.Framework/MonoGame.Framework.Android.csproj b/MonoGame.Framework/MonoGame.Framework.Android.csproj index 778719695eb..4dc269907d0 100644 --- a/MonoGame.Framework/MonoGame.Framework.Android.csproj +++ b/MonoGame.Framework/MonoGame.Framework.Android.csproj @@ -404,6 +404,9 @@ + + + diff --git a/MonoGame.Framework/MonoGame.Framework.Windows8.csproj b/MonoGame.Framework/MonoGame.Framework.Windows8.csproj index 4864277662b..436c6441784 100644 --- a/MonoGame.Framework/MonoGame.Framework.Windows8.csproj +++ b/MonoGame.Framework/MonoGame.Framework.Windows8.csproj @@ -48,8 +48,10 @@ + + @@ -80,6 +82,7 @@ + diff --git a/MonoGame.Framework/PSSuite/Graphics/SpriteBatcher.cs b/MonoGame.Framework/PSSuite/Graphics/SpriteBatcher.cs index 3aa8a07a5fb..d0bc407473a 100644 --- a/MonoGame.Framework/PSSuite/Graphics/SpriteBatcher.cs +++ b/MonoGame.Framework/PSSuite/Graphics/SpriteBatcher.cs @@ -51,8 +51,10 @@ namespace Microsoft.Xna.Framework.Graphics { internal class SpriteBatcher { - private const int InitialBatchSize = 256; - private const int InitialVertexArraySize = 256; +#warning Magic numbers? How i set this on my game? + private const int InitialBatchSize = 10000; + private const int InitialVertexArraySize = 10000; + List _batchItemList; Queue _freeBatchItemQueue; @@ -157,8 +159,7 @@ public void DrawBatch ( SpriteSortMode sortMode ) vertexBuffer.SetIndices(_index, 0, 0, 6 * InitialVertexArraySize); _device._graphics.SetVertexBuffer(0, vertexBuffer); vertexBuffer.SetVertices(_vertexArray, 0, 0, index); - - + startIndex = index = 0; //Draw each batch in the sprite batch (based on texture changes) @@ -173,6 +174,16 @@ public void DrawBatch ( SpriteSortMode sortMode ) startIndex = index; tex = item.Texture; +#warning is the correct place? +#warning im not sure about this equivalence + + // Set the SpriteSamplerState + if (_device.SamplerStates[0]==SamplerState.PointClamp) + tex._texture2D.SetFilter(TextureFilterMode.Disabled); + else if (_device.SamplerStates[0]==SamplerState.LinearClamp) + tex._texture2D.SetFilter(TextureFilterMode.Linear); + else if (_device.SamplerStates[0]==SamplerState.AnisotropicClamp) + tex._texture2D.SetFilter(TextureFilterMode.Nearest); _device._graphics.SetTexture(0, tex._texture2D); } index += 4; @@ -214,9 +225,8 @@ void DrawVertexArray ( int start, int end ) var vertexCount = end - start; #warning this should be applied somewhere else - _device._graphics.Enable(EnableMode.Blend); - _device._graphics.SetBlendFunc(BlendFuncMode.Add, BlendFuncFactor.SrcAlpha, BlendFuncFactor.OneMinusSrcAlpha); - + _device._graphics.Enable(EnableMode.Blend); + _device._graphics.SetBlendFunc(BlendFuncMode.Add, BlendFuncFactor.One, BlendFuncFactor.OneMinusSrcAlpha); _device._graphics.DrawArrays(DrawMode.Triangles, start / 2 * 3, vertexCount / 2 * 3); } } diff --git a/MonoGame.Framework/iOS/GamerServices/SignedInGamer.cs b/MonoGame.Framework/iOS/GamerServices/SignedInGamer.cs index 51bdcdfe2fc..be90efe2528 100644 --- a/MonoGame.Framework/iOS/GamerServices/SignedInGamer.cs +++ b/MonoGame.Framework/iOS/GamerServices/SignedInGamer.cs @@ -95,26 +95,12 @@ private void DoAuthentication() if (lp != null) { - Guide.IsVisible = true; lp.Authenticate( delegate(NSError error) - { - try - { - if ( error != null ) - { -#if DEBUG - Console.WriteLine(error); + { +#if DEBUG + if ( error != null ) + Console.WriteLine(error); #endif - } - else - { - - } - } - finally - { - Guide.IsVisible = false; - } } ); } diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.Linux.csproj b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.Linux.csproj index caf673f1068..dfb967e2a73 100644 --- a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.Linux.csproj +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.Linux.csproj @@ -82,6 +82,9 @@ Always + + Always + @@ -165,4 +168,8 @@ Always + + + + \ No newline at end of file diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.MacOS.csproj b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.MacOS.csproj index 71cfab93d8e..b00c2cc1be8 100644 --- a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.MacOS.csproj +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.MacOS.csproj @@ -39,7 +39,7 @@ - ..\..\..\..\..\..\..\..\..\Applications\MonoDevelop.app\Contents\MacOS\lib\monodevelop\bin\MonoDevelop.Core.dll + References\MonoDevelop.Core.dll diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.addin.xml b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.addin.xml index 64da58b073e..a0fb632299b 100644 --- a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.addin.xml +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/MonoDevelop.MonoGame.addin.xml @@ -10,10 +10,10 @@ + - - + @@ -31,12 +31,17 @@ + + + + + @@ -63,10 +68,32 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacGame.cs b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacGame.cs index a816e8a28a6..ac58bee51bd 100644 --- a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacGame.cs +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacGame.cs @@ -26,7 +26,7 @@ namespace ${Namespace} /// /// Default Project Template /// - public class ${Namespace}Game : Game + public class Game1 : Game { #region Fields @@ -37,7 +37,7 @@ public class ${Namespace}Game : Game #region Initialization - public ${Namespace}Game() + public Game1() { graphics = new GraphicsDeviceManager(this); diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacGame.fs b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacGame.fs new file mode 100644 index 00000000000..2acc5981c8c --- /dev/null +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacGame.fs @@ -0,0 +1,51 @@ +namespace ${Namespace} +open System +open Microsoft.Xna.Framework +open Microsoft.Xna.Framework.Audio +open Microsoft.Xna.Framework.Graphics +open Microsoft.Xna.Framework.Input +open Microsoft.Xna.Framework.Input.Touch +open Microsoft.Xna.Framework.Storage +open Microsoft.Xna.Framework.Content +open Microsoft.Xna.Framework.Media + + /// Default Project Template + type ${Namespace}Game() as x = + inherit Game() + let graphics = new GraphicsDeviceManager(x) + let mutable spriteBatch = Unchecked.defaultof<_> + let mutable logoTexture = Unchecked.defaultof<_> + do x.Content.RootDirectory <- "Content" + graphics.IsFullScreen <- false + + /// Overridden from the base Game.Initialize. Once the GraphicsDevice is setup, + /// we'll use the viewport to initialize some values. + override x.Initialize() = base.Initialize() + + /// Load your graphics content. + override x.LoadContent() = + // Create a new SpriteBatch, which can be use to draw textures. + spriteBatch <- new SpriteBatch (graphics.GraphicsDevice) + + // TODO: use this.Content to load your game content here eg. + logoTexture <- x.Content.Load<_>("logo") + + /// Allows the game to run logic such as updating the world, + /// checking for collisions, gathering input, and playing audio. + override x.Update ( gameTime:GameTime) = + // TODO: Add your update logic here + base.Update (gameTime) + + /// This is called when the game should draw itself. + override x.Draw (gameTime:GameTime) = + // Clear the backbuffer + graphics.GraphicsDevice.Clear (Color.CornflowerBlue) + + spriteBatch.Begin() + + // draw the logo + spriteBatch.Draw (logoTexture, new Vector2 (130.f, 200.f), Color.White); + spriteBatch.End() + + //TODO: Add your drawing code here + base.Draw (gameTime) \ No newline at end of file diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacMain.fs b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacMain.fs new file mode 100644 index 00000000000..6609363b4ad --- /dev/null +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/MacMain.fs @@ -0,0 +1,22 @@ +namespace ${Namespace} +open MonoMac.AppKit +open MonoMac.Foundation + +type AppDelegate() = + inherit NSApplicationDelegate() + + override x.FinishedLaunching(notification) = + let game = new ${ProjectName}Game() + game.Run() + + override x.ApplicationShouldTerminateAfterLastWindowClosed(sender) = + true + +module main = + [] + let main args = + NSApplication.Init () + using (new NSAutoreleasePool()) (fun n -> + NSApplication.SharedApplication.Delegate <- new AppDelegate() + NSApplication.Main(args) ) + 0 \ No newline at end of file diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/iOSGame.cs b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/iOSGame.cs index c9d188c3c5c..db6b40d779f 100644 --- a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/iOSGame.cs +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameApplication/iOSGame.cs @@ -26,7 +26,7 @@ namespace ${Namespace} /// /// Default Project Template /// - public class ${Namespace}Game : Game + public class Game1 : Game { #region Fields @@ -37,7 +37,7 @@ public class ${Namespace}Game : Game #region Initialization - public ${Namespace}Game() + public Game1() { graphics = new GraphicsDeviceManager(this); diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameMacFsharpProject.xpt.xml b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameMacFsharpProject.xpt.xml new file mode 100644 index 00000000000..1600e29bb37 --- /dev/null +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameMacFsharpProject.xpt.xml @@ -0,0 +1,47 @@ + + diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameMacProject.xpt.xml b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameMacProject.xpt.xml index b975255065e..f31535dafef 100644 --- a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameMacProject.xpt.xml +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameMacProject.xpt.xml @@ -26,9 +26,8 @@ - - - + + diff --git a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameiOSProject.xpt.xml b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameiOSProject.xpt.xml index 8af17e5865b..7511484b717 100644 --- a/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameiOSProject.xpt.xml +++ b/ProjectTemplates/MonoDevelop/MonoDevelop.MonoGame/MonoDevelop.MonoGame/templates/MonoGameiOSProject.xpt.xml @@ -25,9 +25,8 @@ - - - + +