diff --git a/MonoGame.Framework/Android/AndroidGameWindow.cs b/MonoGame.Framework/Android/AndroidGameWindow.cs index adb82f1719b..55ab4ff5dae 100644 --- a/MonoGame.Framework/Android/AndroidGameWindow.cs +++ b/MonoGame.Framework/Android/AndroidGameWindow.cs @@ -1,490 +1,490 @@ -#region License -/* -Microsoft Public License (Ms-PL) -MonoGame - Copyright © 2009 The MonoGame Team - -All rights reserved. - -This license governs use of the accompanying software. If you use the software, you accept this license. If you do not -accept the license, do not use the software. - -1. Definitions -The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under -U.S. copyright law. - -A "contribution" is the original software, or any additions or changes to the software. -A "contributor" is any person that distributes its contribution under this license. -"Licensed patents" are a contributor's patent claims that read directly on its contribution. - -2. Grant of Rights -(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, -each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. -(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, -each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. - -3. Conditions and Limitations -(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. -(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, -your patent license from such contributor to the software ends automatically. -(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution -notices that are present in the software. -(D) If you distribute any portion of the software in source code form, you may do so only under this license by including -a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object -code form, you may only do so under a license that complies with this license. -(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees -or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent -permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular -purpose and non-infringement. -*/ -#endregion License - -#region Using Statements -using System; -using System.Drawing; -using System.Collections.Generic; -using System.ComponentModel; -using Android.Content; -using Android.Content.PM; -using Android.Content.Res; -using Android.Util; -using Android.Views; -using Microsoft.Xna.Framework.Audio; -using Microsoft.Xna.Framework.Graphics; -using OpenTK.Platform.Android; - -using OpenTK; -using OpenTK.Platform; -using OpenTK.Graphics; -using OpenTK.Graphics.ES20; - -using Microsoft.Xna.Framework.Input; -using Microsoft.Xna.Framework.Input.Touch; -#endregion Using Statements - -namespace Microsoft.Xna.Framework -{ - public class AndroidGameWindow : AndroidGameView , Android.Views.View.IOnTouchListener, ISurfaceHolderCallback - { - private Rectangle clientBounds; - private Game _game; - private DisplayOrientation supportedOrientations = DisplayOrientation.Default; - private DisplayOrientation _currentOrientation; - private AndroidTouchEventManager _touchManager = null; - private bool _contextWasLost = false; - - public bool TouchEnabled - { - get { return _touchManager.Enabled; } - set { _touchManager.Enabled = value; } - } - - public AndroidGameWindow(Context context, Game game) : base(context) - { - _game = game; - Initialize(); - } - - private void Initialize() - { - clientBounds = new Rectangle(0, 0, Context.Resources.DisplayMetrics.WidthPixels, Context.Resources.DisplayMetrics.HeightPixels); - - this.RequestFocus(); - this.FocusableInTouchMode = true; - - _touchManager = new AndroidTouchEventManager(_game); - -#if OUYA - GamePad.Initialize(); -#endif - } - - protected override void OnLoad (EventArgs e) - { - base.OnLoad (e); - MakeCurrent(); - } - - public override bool OnKeyDown(Keycode keyCode, KeyEvent e) - { -#if OUYA - if (GamePad.OnKeyDown(keyCode, e)) - return true; -#endif - - Keyboard.KeyDown(keyCode); - // we need to handle the Back key here because it doesnt work any other way -#if !OUYA - if (keyCode == Keycode.Back) - GamePad.Instance.SetBack(); -#endif - - if (keyCode == Keycode.VolumeUp) - Sound.IncreaseMediaVolume(); - - if (keyCode == Keycode.VolumeDown) - Sound.DecreaseMediaVolume(); - - return true; - } - - public override bool OnKeyUp(Keycode keyCode, KeyEvent e) - { -#if OUYA - if (GamePad.OnKeyUp(keyCode, e)) - return true; -#endif - Keyboard.KeyUp(keyCode); - return true; - } - -#if OUYA - public override bool OnGenericMotionEvent(MotionEvent e) - { - if (GamePad.OnGenericMotionEvent(e)) - return true; - - return base.OnGenericMotionEvent(e); - } -#endif - - protected override void CreateFrameBuffer() - { - Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.CreateFrameBuffer"); - try - { - GLContextVersion = GLContextVersion.Gles2_0; - try - { - base.CreateFrameBuffer(); - } - catch(Exception) - { - // try again using a more basic mode which hopefully the device will support - GraphicsMode = new AndroidGraphicsMode(0, 0, 0, 0, 0, false); - base.CreateFrameBuffer(); - } - All status = GL.CheckFramebufferStatus(All.Framebuffer); - Android.Util.Log.Debug("MonoGame", "Framebuffer Status: " + status.ToString()); - } - catch (Exception) - { - throw new NotSupportedException("Could not create OpenGLES 2.0 frame buffer"); - } - if (_game.GraphicsDevice != null && _contextWasLost) - { - _game.GraphicsDevice.Initialize(); - Android.Util.Log.Debug("MonoGame", "Begin reloading graphics content"); - Microsoft.Xna.Framework.Content.ContentManager.ReloadGraphicsContent(); - Android.Util.Log.Debug("MonoGame", "End reloading graphics content"); - - // DeviceReset events - _game.graphicsDeviceManager.OnDeviceReset(EventArgs.Empty); - _game.GraphicsDevice.OnDeviceReset(); - - _contextWasLost = false; - } - - MakeCurrent(); - } - - protected override void DestroyFrameBuffer() - { - // DeviceResetting events - _game.graphicsDeviceManager.OnDeviceResetting(EventArgs.Empty); - _game.GraphicsDevice.OnDeviceResetting(); - - Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.DestroyFrameBuffer"); - - base.DestroyFrameBuffer(); - - _contextWasLost = GraphicsContext == null || GraphicsContext.IsDisposed; - } - - #region AndroidGameView Methods - - protected override void OnRenderFrame(FrameEventArgs e) - { - base.OnRenderFrame(e); - - if (GraphicsContext == null || GraphicsContext.IsDisposed) - return; - - if (!GraphicsContext.IsCurrent) - MakeCurrent(); - - Threading.Run(); - } - - protected override void OnUpdateFrame(FrameEventArgs e) - { - base.OnUpdateFrame(e); - - if (_contextWasLost) - return; - - if (!GraphicsContext.IsCurrent) - MakeCurrent(); - - Threading.Run(); - - if (_game != null) - { - if ( _game.Platform.IsActive && !ScreenReceiver.ScreenLocked) //Only call draw if an update has occured - { - _game.Tick(); - } - else if (_game.GraphicsDevice != null) - { - _game.GraphicsDevice.Clear(Color.Black); - _game.Platform.Present(); - } - } - } - - #endregion - - - internal void SetSupportedOrientations(DisplayOrientation orientations) - { - supportedOrientations = orientations; - } - - /// - /// In Xna, setting SupportedOrientations = DisplayOrientation.Default (which is the default value) - /// has the effect of setting SupportedOrientations to landscape only or portrait only, based on the - /// aspect ratio of PreferredBackBufferWidth / PreferredBackBufferHeight - /// - /// - internal DisplayOrientation GetEffectiveSupportedOrientations() - { - if (supportedOrientations == DisplayOrientation.Default) - { - var deviceManager = (_game.Services.GetService(typeof(IGraphicsDeviceManager)) as GraphicsDeviceManager); - if (deviceManager == null) - return DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight; - - if (deviceManager.PreferredBackBufferWidth > deviceManager.PreferredBackBufferHeight) - { - return DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight; - } - else - { - return DisplayOrientation.Portrait | DisplayOrientation.PortraitUpsideDown; - } - } - else - { - return supportedOrientations; - } - } - - /// - /// Updates the screen orientation. Filters out requests for unsupported orientations. - /// - internal void SetOrientation(DisplayOrientation newOrientation, bool applyGraphicsChanges) - { - DisplayOrientation supported = GetEffectiveSupportedOrientations(); - - // If the new orientation is not supported, force a supported orientation - if ((supported & newOrientation) == 0) - { - if ((supported & DisplayOrientation.LandscapeLeft) != 0) - newOrientation = DisplayOrientation.LandscapeLeft; - else if ((supported & DisplayOrientation.LandscapeRight) != 0) - newOrientation = DisplayOrientation.LandscapeRight; - else if ((supported & DisplayOrientation.Portrait) != 0) - newOrientation = DisplayOrientation.Portrait; - else if ((supported & DisplayOrientation.PortraitUpsideDown) != 0) - newOrientation = DisplayOrientation.PortraitUpsideDown; - } - - DisplayOrientation oldOrientation = CurrentOrientation; - - CurrentOrientation = newOrientation; - TouchPanel.DisplayOrientation = newOrientation; - - if (applyGraphicsChanges && oldOrientation != CurrentOrientation && _game.graphicsDeviceManager != null) - _game.graphicsDeviceManager.ApplyChanges(); - } - - #region IOnTouchListener implementation - public bool OnTouch (View v, MotionEvent e) - { - return OnTouchEvent(e); - } - #endregion - - public override bool OnTouchEvent(MotionEvent e) - { - _touchManager.OnTouchEvent(e); - return true; - } - - public string ScreenDeviceName - { - get - { - throw new System.NotImplementedException (); - } - } - - - public Rectangle ClientBounds - { - get - { - return clientBounds; - } - internal set - { - clientBounds = value; - //if(ClientSizeChanged != null) - // ClientSizeChanged(this, EventArgs.Empty); - } - } - - public bool AllowUserResizing - { - get - { - return false; - } - set - { - // Do nothing; Ignore rather than raising and exception - } - } - - // A copy of ScreenOrientation from Android 2.3 - // This allows us to continue to support 2.2 whilst - // utilising the 2.3 improved orientation support. - enum ScreenOrientationAll - { - Unspecified = -1, - Landscape = 0, - Portrait = 1, - User = 2, - Behind = 3, - Sensor = 4, - Nosensor = 5, - SensorLandscape = 6, - SensorPortrait = 7, - ReverseLandscape = 8, - ReversePortrait = 9, - FullSensor = 10, - } - - public DisplayOrientation CurrentOrientation - { - get - { - return _currentOrientation; - } - private set - { - if (value != _currentOrientation) - { - DisplayOrientation supported = GetEffectiveSupportedOrientations(); - ScreenOrientation requestedOrientation = ScreenOrientation.Unspecified; - bool wasPortrait = _currentOrientation == DisplayOrientation.Portrait || _currentOrientation == DisplayOrientation.PortraitUpsideDown; - bool requestPortrait = false; - - bool didOrientationChange = false; - // Android 2.3 and above support reverse orientations - int sdkVer = (int)Android.OS.Build.VERSION.SdkInt; - if (sdkVer >= 10) - { - // Check if the requested orientation is supported. Default means all are supported. - if ((supported & value) != 0) - { - didOrientationChange = true; - _currentOrientation = value; - switch (value) - { - case DisplayOrientation.LandscapeLeft: - requestedOrientation = (ScreenOrientation)ScreenOrientationAll.Landscape; - requestPortrait = false; - break; - case DisplayOrientation.LandscapeRight: - requestedOrientation = (ScreenOrientation)ScreenOrientationAll.ReverseLandscape; - requestPortrait = false; - break; - case DisplayOrientation.Portrait: - requestedOrientation = (ScreenOrientation)ScreenOrientationAll.Portrait; - requestPortrait = true; - break; - case DisplayOrientation.PortraitUpsideDown: - requestedOrientation = (ScreenOrientation)ScreenOrientationAll.ReversePortrait; - requestPortrait = true; - break; - } - } - } - else - { - // Check if the requested orientation is either of the landscape orientations and any landscape orientation is supported. - if ((value == DisplayOrientation.LandscapeLeft || value == DisplayOrientation.LandscapeRight) && - ((supported & (DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight)) != 0)) - { - didOrientationChange = true; - _currentOrientation = DisplayOrientation.LandscapeLeft; - requestedOrientation = ScreenOrientation.Landscape; - requestPortrait = false; - } - // Check if the requested orientation is either of the portrain orientations and any portrait orientation is supported. - else if ((value == DisplayOrientation.Portrait || value == DisplayOrientation.PortraitUpsideDown) && - ((supported & (DisplayOrientation.Portrait | DisplayOrientation.PortraitUpsideDown)) != 0)) - { - didOrientationChange = true; - _currentOrientation = DisplayOrientation.Portrait; - requestedOrientation = ScreenOrientation.Portrait; - requestPortrait = true; - } - } - - if (didOrientationChange) - { - // Android doesn't fire Released events for existing touches - // so we need to clear them out. - if (wasPortrait != requestPortrait) - { - TouchPanel.ReleaseAllTouches(); - } - - Game.Activity.RequestedOrientation = requestedOrientation; - - if (OrientationChanged != null) - OrientationChanged(this, EventArgs.Empty); - } - } - } - } - - public event EventHandler OrientationChanged; - public event EventHandler ClientSizeChanged; - public event EventHandler ScreenDeviceNameChanged; - - - void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Android.Graphics.Format format, int width, int height) - { - base.SurfaceChanged(holder, format, width, height); - Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.SurfaceChanged: format = " + format + ", width = " + width + ", height = " + height); - - if (_game.GraphicsDevice != null) - _game.graphicsDeviceManager.ResetClientBounds(); - } - - void ISurfaceHolderCallback.SurfaceDestroyed(ISurfaceHolder holder) - { - base.SurfaceDestroyed(holder); - Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.SurfaceDestroyed"); - } - - void ISurfaceHolderCallback.SurfaceCreated(ISurfaceHolder holder) - { - base.SurfaceCreated(holder); - Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.SurfaceCreated: surfaceFrame = " + holder.SurfaceFrame.ToString()); - } - } -} - +#region License +/* +Microsoft Public License (Ms-PL) +MonoGame - Copyright © 2009 The MonoGame Team + +All rights reserved. + +This license governs use of the accompanying software. If you use the software, you accept this license. If you do not +accept the license, do not use the software. + +1. Definitions +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under +U.S. copyright law. + +A "contribution" is the original software, or any additions or changes to the software. +A "contributor" is any person that distributes its contribution under this license. +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, +each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, +each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, +your patent license from such contributor to the software ends automatically. +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution +notices that are present in the software. +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including +a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object +code form, you may only do so under a license that complies with this license. +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees +or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent +permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular +purpose and non-infringement. +*/ +#endregion License + +#region Using Statements +using System; +using System.Drawing; +using System.Collections.Generic; +using System.ComponentModel; +using Android.Content; +using Android.Content.PM; +using Android.Content.Res; +using Android.Util; +using Android.Views; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Graphics; +using OpenTK.Platform.Android; + +using OpenTK; +using OpenTK.Platform; +using OpenTK.Graphics; +using OpenTK.Graphics.ES20; + +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Input.Touch; +#endregion Using Statements + +namespace Microsoft.Xna.Framework +{ + public class AndroidGameWindow : AndroidGameView , Android.Views.View.IOnTouchListener, ISurfaceHolderCallback + { + private Rectangle clientBounds; + private Game _game; + private DisplayOrientation supportedOrientations = DisplayOrientation.Default; + private DisplayOrientation _currentOrientation; + private AndroidTouchEventManager _touchManager = null; + private bool _contextWasLost = false; + + public bool TouchEnabled + { + get { return _touchManager.Enabled; } + set { _touchManager.Enabled = value; } + } + + public AndroidGameWindow(Context context, Game game) : base(context) + { + _game = game; + Initialize(); + } + + private void Initialize() + { + clientBounds = new Rectangle(0, 0, Context.Resources.DisplayMetrics.WidthPixels, Context.Resources.DisplayMetrics.HeightPixels); + + this.RequestFocus(); + this.FocusableInTouchMode = true; + + _touchManager = new AndroidTouchEventManager(_game); + +#if OUYA + GamePad.Initialize(); +#endif + } + + protected override void OnLoad (EventArgs e) + { + base.OnLoad (e); + MakeCurrent(); + } + + public override bool OnKeyDown(Keycode keyCode, KeyEvent e) + { +#if OUYA + if (GamePad.OnKeyDown(keyCode, e)) + return true; +#endif + + Keyboard.KeyDown(keyCode); + // we need to handle the Back key here because it doesnt work any other way +#if !OUYA + if (keyCode == Keycode.Back) + GamePad.Instance.SetBack(); +#endif + + if (keyCode == Keycode.VolumeUp) + Sound.IncreaseMediaVolume(); + + if (keyCode == Keycode.VolumeDown) + Sound.DecreaseMediaVolume(); + + return true; + } + + public override bool OnKeyUp(Keycode keyCode, KeyEvent e) + { +#if OUYA + if (GamePad.OnKeyUp(keyCode, e)) + return true; +#endif + Keyboard.KeyUp(keyCode); + return true; + } + +#if OUYA + public override bool OnGenericMotionEvent(MotionEvent e) + { + if (GamePad.OnGenericMotionEvent(e)) + return true; + + return base.OnGenericMotionEvent(e); + } +#endif + + protected override void CreateFrameBuffer() + { + Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.CreateFrameBuffer"); + try + { + GLContextVersion = GLContextVersion.Gles2_0; + try + { + base.CreateFrameBuffer(); + } + catch(Exception) + { + // try again using a more basic mode which hopefully the device will support + GraphicsMode = new AndroidGraphicsMode(0, 0, 0, 0, 0, false); + base.CreateFrameBuffer(); + } + All status = GL.CheckFramebufferStatus(All.Framebuffer); + Android.Util.Log.Debug("MonoGame", "Framebuffer Status: " + status.ToString()); + } + catch (Exception) + { + throw new NotSupportedException("Could not create OpenGLES 2.0 frame buffer"); + } + if (_game.GraphicsDevice != null && _contextWasLost) + { + _game.GraphicsDevice.Initialize(); + Android.Util.Log.Debug("MonoGame", "Begin reloading graphics content"); + Microsoft.Xna.Framework.Content.ContentManager.ReloadGraphicsContent(); + Android.Util.Log.Debug("MonoGame", "End reloading graphics content"); + + // DeviceReset events + _game.graphicsDeviceManager.OnDeviceReset(EventArgs.Empty); + _game.GraphicsDevice.OnDeviceReset(); + + _contextWasLost = false; + } + + MakeCurrent(); + } + + protected override void DestroyFrameBuffer() + { + // DeviceResetting events + _game.graphicsDeviceManager.OnDeviceResetting(EventArgs.Empty); + _game.GraphicsDevice.OnDeviceResetting(); + + Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.DestroyFrameBuffer"); + + base.DestroyFrameBuffer(); + + _contextWasLost = GraphicsContext == null || GraphicsContext.IsDisposed; + } + + #region AndroidGameView Methods + + protected override void OnRenderFrame(FrameEventArgs e) + { + base.OnRenderFrame(e); + + if (GraphicsContext == null || GraphicsContext.IsDisposed) + return; + + if (!GraphicsContext.IsCurrent) + MakeCurrent(); + + Threading.Run(); + } + + protected override void OnUpdateFrame(FrameEventArgs e) + { + base.OnUpdateFrame(e); + + if (_contextWasLost) + return; + + if (!GraphicsContext.IsCurrent) + MakeCurrent(); + + Threading.Run(); + + if (_game != null) + { + if ( _game.Platform.IsActive && !ScreenReceiver.ScreenLocked) //Only call draw if an update has occured + { + _game.Tick(); + } + else if (_game.GraphicsDevice != null) + { + _game.GraphicsDevice.Clear(Color.Black); + _game.Platform.Present(); + } + } + } + + #endregion + + + internal void SetSupportedOrientations(DisplayOrientation orientations) + { + supportedOrientations = orientations; + } + + /// + /// In Xna, setting SupportedOrientations = DisplayOrientation.Default (which is the default value) + /// has the effect of setting SupportedOrientations to landscape only or portrait only, based on the + /// aspect ratio of PreferredBackBufferWidth / PreferredBackBufferHeight + /// + /// + internal DisplayOrientation GetEffectiveSupportedOrientations() + { + if (supportedOrientations == DisplayOrientation.Default) + { + var deviceManager = (_game.Services.GetService(typeof(IGraphicsDeviceManager)) as GraphicsDeviceManager); + if (deviceManager == null) + return DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight; + + if (deviceManager.PreferredBackBufferWidth > deviceManager.PreferredBackBufferHeight) + { + return DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight; + } + else + { + return DisplayOrientation.Portrait | DisplayOrientation.PortraitDown; + } + } + else + { + return supportedOrientations; + } + } + + /// + /// Updates the screen orientation. Filters out requests for unsupported orientations. + /// + internal void SetOrientation(DisplayOrientation newOrientation, bool applyGraphicsChanges) + { + DisplayOrientation supported = GetEffectiveSupportedOrientations(); + + // If the new orientation is not supported, force a supported orientation + if ((supported & newOrientation) == 0) + { + if ((supported & DisplayOrientation.LandscapeLeft) != 0) + newOrientation = DisplayOrientation.LandscapeLeft; + else if ((supported & DisplayOrientation.LandscapeRight) != 0) + newOrientation = DisplayOrientation.LandscapeRight; + else if ((supported & DisplayOrientation.Portrait) != 0) + newOrientation = DisplayOrientation.Portrait; + else if ((supported & DisplayOrientation.PortraitDown) != 0) + newOrientation = DisplayOrientation.PortraitDown; + } + + DisplayOrientation oldOrientation = CurrentOrientation; + + CurrentOrientation = newOrientation; + TouchPanel.DisplayOrientation = newOrientation; + + if (applyGraphicsChanges && oldOrientation != CurrentOrientation && _game.graphicsDeviceManager != null) + _game.graphicsDeviceManager.ApplyChanges(); + } + + #region IOnTouchListener implementation + public bool OnTouch (View v, MotionEvent e) + { + return OnTouchEvent(e); + } + #endregion + + public override bool OnTouchEvent(MotionEvent e) + { + _touchManager.OnTouchEvent(e); + return true; + } + + public string ScreenDeviceName + { + get + { + throw new System.NotImplementedException (); + } + } + + + public Rectangle ClientBounds + { + get + { + return clientBounds; + } + internal set + { + clientBounds = value; + //if(ClientSizeChanged != null) + // ClientSizeChanged(this, EventArgs.Empty); + } + } + + public bool AllowUserResizing + { + get + { + return false; + } + set + { + // Do nothing; Ignore rather than raising and exception + } + } + + // A copy of ScreenOrientation from Android 2.3 + // This allows us to continue to support 2.2 whilst + // utilising the 2.3 improved orientation support. + enum ScreenOrientationAll + { + Unspecified = -1, + Landscape = 0, + Portrait = 1, + User = 2, + Behind = 3, + Sensor = 4, + Nosensor = 5, + SensorLandscape = 6, + SensorPortrait = 7, + ReverseLandscape = 8, + ReversePortrait = 9, + FullSensor = 10, + } + + public DisplayOrientation CurrentOrientation + { + get + { + return _currentOrientation; + } + private set + { + if (value != _currentOrientation) + { + DisplayOrientation supported = GetEffectiveSupportedOrientations(); + ScreenOrientation requestedOrientation = ScreenOrientation.Unspecified; + bool wasPortrait = _currentOrientation == DisplayOrientation.Portrait || _currentOrientation == DisplayOrientation.PortraitDown; + bool requestPortrait = false; + + bool didOrientationChange = false; + // Android 2.3 and above support reverse orientations + int sdkVer = (int)Android.OS.Build.VERSION.SdkInt; + if (sdkVer >= 10) + { + // Check if the requested orientation is supported. Default means all are supported. + if ((supported & value) != 0) + { + didOrientationChange = true; + _currentOrientation = value; + switch (value) + { + case DisplayOrientation.LandscapeLeft: + requestedOrientation = (ScreenOrientation)ScreenOrientationAll.Landscape; + requestPortrait = false; + break; + case DisplayOrientation.LandscapeRight: + requestedOrientation = (ScreenOrientation)ScreenOrientationAll.ReverseLandscape; + requestPortrait = false; + break; + case DisplayOrientation.Portrait: + requestedOrientation = (ScreenOrientation)ScreenOrientationAll.Portrait; + requestPortrait = true; + break; + case DisplayOrientation.PortraitDown: + requestedOrientation = (ScreenOrientation)ScreenOrientationAll.ReversePortrait; + requestPortrait = true; + break; + } + } + } + else + { + // Check if the requested orientation is either of the landscape orientations and any landscape orientation is supported. + if ((value == DisplayOrientation.LandscapeLeft || value == DisplayOrientation.LandscapeRight) && + ((supported & (DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight)) != 0)) + { + didOrientationChange = true; + _currentOrientation = DisplayOrientation.LandscapeLeft; + requestedOrientation = ScreenOrientation.Landscape; + requestPortrait = false; + } + // Check if the requested orientation is either of the portrain orientations and any portrait orientation is supported. + else if ((value == DisplayOrientation.Portrait || value == DisplayOrientation.PortraitDown) && + ((supported & (DisplayOrientation.Portrait | DisplayOrientation.PortraitDown)) != 0)) + { + didOrientationChange = true; + _currentOrientation = DisplayOrientation.Portrait; + requestedOrientation = ScreenOrientation.Portrait; + requestPortrait = true; + } + } + + if (didOrientationChange) + { + // Android doesn't fire Released events for existing touches + // so we need to clear them out. + if (wasPortrait != requestPortrait) + { + TouchPanel.ReleaseAllTouches(); + } + + Game.Activity.RequestedOrientation = requestedOrientation; + + if (OrientationChanged != null) + OrientationChanged(this, EventArgs.Empty); + } + } + } + } + + public event EventHandler OrientationChanged; + public event EventHandler ClientSizeChanged; + public event EventHandler ScreenDeviceNameChanged; + + + void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Android.Graphics.Format format, int width, int height) + { + base.SurfaceChanged(holder, format, width, height); + Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.SurfaceChanged: format = " + format + ", width = " + width + ", height = " + height); + + if (_game.GraphicsDevice != null) + _game.graphicsDeviceManager.ResetClientBounds(); + } + + void ISurfaceHolderCallback.SurfaceDestroyed(ISurfaceHolder holder) + { + base.SurfaceDestroyed(holder); + Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.SurfaceDestroyed"); + } + + void ISurfaceHolderCallback.SurfaceCreated(ISurfaceHolder holder) + { + base.SurfaceCreated(holder); + Android.Util.Log.Debug("MonoGame", "AndroidGameWindow.SurfaceCreated: surfaceFrame = " + holder.SurfaceFrame.ToString()); + } + } +} + diff --git a/MonoGame.Framework/Android/OrientationListener.cs b/MonoGame.Framework/Android/OrientationListener.cs index 84b164534a7..fb59b863d05 100644 --- a/MonoGame.Framework/Android/OrientationListener.cs +++ b/MonoGame.Framework/Android/OrientationListener.cs @@ -55,7 +55,7 @@ public override void OnOrientationChanged(int orientation) break; case 0: disporientation = DisplayOrientation.Portrait; break; - case 180: disporientation = DisplayOrientation.PortraitUpsideDown; + case 180: disporientation = DisplayOrientation.PortraitDown; break; default: disporientation = DisplayOrientation.LandscapeLeft; diff --git a/MonoGame.Framework/MacOS/GameWindow.cs b/MonoGame.Framework/MacOS/GameWindow.cs index 8fa0d17447d..19a020ab90c 100644 --- a/MonoGame.Framework/MacOS/GameWindow.cs +++ b/MonoGame.Framework/MacOS/GameWindow.cs @@ -1,672 +1,672 @@ -#region License -/* -Microsoft Public License (Ms-PL) -XnaTouch - Copyright © 2009 The XnaTouch Team - -All rights reserved. - -This license governs use of the accompanying software. If you use the software, you accept this license. If you do not -accept the license, do not use the software. - -1. Definitions -The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under -U.S. copyright law. - -A "contribution" is the original software, or any additions or changes to the software. -A "contributor" is any person that distributes its contribution under this license. -"Licensed patents" are a contributor's patent claims that read directly on its contribution. - -2. Grant of Rights -(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, -each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. -(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, -each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. - -3. Conditions and Limitations -(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. -(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, -your patent license from such contributor to the software ends automatically. -(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution -notices that are present in the software. -(D) If you distribute any portion of the software in source code form, you may do so only under this license by including -a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object -code form, you may only do so under a license that complies with this license. -(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees -or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent -permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular -purpose and non-infringement. -*/ -#endregion License - -#region Using Statements -using System; -using System.Drawing; -using System.Collections.Generic; - -using MonoMac.CoreAnimation; -using MonoMac.Foundation; -using MonoMac.ObjCRuntime; -using MonoMac.OpenGL; -using MonoMac.AppKit; - -using Microsoft.Xna.Framework.Input; -using Microsoft.Xna.Framework.Input.Touch; - -#endregion Using Statements - -namespace Microsoft.Xna.Framework -{ - public class GameWindow : MonoMacGameView - { - //private readonly Rectangle clientBounds; - private Rectangle clientBounds; - private Game _game; - private MacGamePlatform _platform; - - private NSTrackingArea _trackingArea; - private bool _needsToResetElapsedTime = false; - - public static Func CreateWindowDelegate - { - get; - set; - } - - #region GameWindow Methods - public GameWindow(Game game, RectangleF frame) : base (frame) - { - if (game == null) - throw new ArgumentNullException("game"); - _game = game; - _platform = (MacGamePlatform)_game.Services.GetService(typeof(MacGamePlatform)); - - //LayerRetainsBacking = false; - //LayerColorFormat = EAGLColorFormat.RGBA8; - this.AutoresizingMask = MonoMac.AppKit.NSViewResizingMask.HeightSizable - | MonoMac.AppKit.NSViewResizingMask.MaxXMargin - | MonoMac.AppKit.NSViewResizingMask.MinYMargin - | MonoMac.AppKit.NSViewResizingMask.WidthSizable; - - RectangleF rect = NSScreen.MainScreen.Frame; - - clientBounds = new Rectangle (0,0,(int)rect.Width,(int)rect.Height); - - // Enable multi-touch - //MultipleTouchEnabled = true; - - Mouse.Window = this; - } - - public GameWindow(Game game, RectangleF frame, NSOpenGLContext context) : - this(game, frame) - { - } - - [Export("initWithFrame:")] - public GameWindow () : base (NSScreen.MainScreen.Frame) - { - this.AutoresizingMask = MonoMac.AppKit.NSViewResizingMask.HeightSizable - | MonoMac.AppKit.NSViewResizingMask.MaxXMargin - | MonoMac.AppKit.NSViewResizingMask.MinYMargin - | MonoMac.AppKit.NSViewResizingMask.WidthSizable; - - RectangleF rect = NSScreen.MainScreen.Frame; - clientBounds = new Rectangle (0,0,(int)rect.Width,(int)rect.Height); - - // Enable multi-touch - //MultipleTouchEnabled = true; - - } - - ~GameWindow () - { - // - } - - #endregion - - public void StartRunLoop(double updateRate) - { - Run(updateRate); - } - - public void ResetElapsedTime () - { - _needsToResetElapsedTime = true; - } - #region MonoMacGameView Methods - - protected override void OnClosed (EventArgs e) - { - base.OnClosed (e); - } - - protected override void OnDisposed (EventArgs e) - { - base.OnDisposed (e); - } - - protected override void OnLoad (EventArgs e) - { - base.OnLoad (e); - } - - protected override void OnRenderFrame (FrameEventArgs e) - { - base.OnRenderFrame (e); - - // FIXME: Since Game.Exit may be called during an Update loop (and - // in fact that is quite likely to happen), this code is now - // littered with checks to _platform.IsRunning. It would be - // nice if there weren't quite so many. The move to a - // Game.Tick-centric architecture may eliminate this problem - // automatically. - if (_game != null && _platform.IsRunning) { - _game.Tick(); - } - } -// protected override void OnUpdateFrame (FrameEventArgs e) -// { -// base.OnUpdateFrame (e); -// -// } - protected override void OnResize (EventArgs e) - { - var manager = (GraphicsDeviceManager)_game.Services.GetService(typeof(IGraphicsDeviceManager)); - if (_game.Initialized) - { - manager.OnDeviceResetting(EventArgs.Empty); - - Microsoft.Xna.Framework.Graphics.Viewport _vp = - new Microsoft.Xna.Framework.Graphics.Viewport(); - - _game.GraphicsDevice.PresentationParameters.BackBufferWidth = (int)Bounds.Width; - _game.GraphicsDevice.PresentationParameters.BackBufferHeight = (int)Bounds.Height; - - _vp.X = (int)Bounds.X; - _vp.Y = (int)Bounds.Y; - _vp.Width = (int)Bounds.Width; - _vp.Height = (int)Bounds.Height; - - _game.GraphicsDevice.Viewport = _vp; - } - - clientBounds = new Rectangle((int)Bounds.X,(int)Bounds.Y,(int)Bounds.Width,(int)Bounds.Height); - - base.OnResize(e); - OnClientSizeChanged(e); - - if (_game.Initialized) - manager.OnDeviceReset(EventArgs.Empty); - } - - protected virtual void OnClientSizeChanged (EventArgs e) - { - var h = ClientSizeChanged; - if (h != null) - h (this, e); - } - - protected override void OnTitleChanged (EventArgs e) - { - base.OnTitleChanged (e); - } - - protected override void OnUnload (EventArgs e) - { - base.OnUnload (e); - } - - protected override void OnVisibleChanged (EventArgs e) - { - base.OnVisibleChanged (e); - } - - protected override void OnWindowStateChanged (EventArgs e) - { - base.OnWindowStateChanged (e); - } - - #endregion - - #region UIVIew Methods - - /* TODO private readonly Dictionary previousTouches = new Dictionary(); - - private void FillTouchCollection(NSSet touches) - { - UITouch []touchesArray = touches.ToArray(); - - TouchPanel.Collection.Clear(); - TouchPanel.Collection.Capacity = touchesArray.Length; - - for (int i=0; i ClientSizeChanged; - public event EventHandler OrientationChanged; - public event EventHandler ScreenDeviceNameChanged; - - // make sure we get mouse move events. - public override bool AcceptsFirstResponder () - { - return true; - } - - public override bool BecomeFirstResponder () - { - return true; - } - public override void CursorUpdate (NSEvent theEvent) - { - base.CursorUpdate (theEvent); - } - - public override void ViewWillMoveToWindow (NSWindow newWindow) - { - //Console.WriteLine("View will move to window"); - if (_trackingArea != null) RemoveTrackingArea(_trackingArea); - _trackingArea = new NSTrackingArea(Frame, - NSTrackingAreaOptions.MouseMoved | - NSTrackingAreaOptions.MouseEnteredAndExited | - NSTrackingAreaOptions.EnabledDuringMouseDrag | - NSTrackingAreaOptions.ActiveWhenFirstResponder | - NSTrackingAreaOptions.InVisibleRect | - NSTrackingAreaOptions.CursorUpdate, - this, new NSDictionary()); - AddTrackingArea(_trackingArea); - - } - - // These variables are to handle our custom cursor for when IsMouseVisible is false. - // Hiding and unhiding the cursor was such a pain that I decided to let the system - // take care of this with Cursor Rectangles - NSImage cursorImage = null; // Will be set to our custom image - NSCursor cursor = null; // Our custom cursor - public override void ResetCursorRects () - { - - // If we do not have a cursor then we create an image size 1 x 1 - // and then create our custom cursor with clear colors - if (cursor == null) { - cursorImage = new NSImage(new SizeF(1,1)); - cursor = new NSCursor(cursorImage, NSColor.Clear, NSColor.Clear, new PointF(0,0)); - } - - // if the cursor is not to be visible then we us our custom cursor. - if (!_game.IsMouseVisible) - AddCursorRect(Frame, cursor); - else - AddCursorRect(Frame, NSCursor.ArrowCursor); - - } - - public override void DiscardCursorRects () - { - base.DiscardCursorRects (); - //Console.WriteLine("DiscardCursorRects"); - } - private void UpdateKeyboardState () - { - _keyStates.Clear (); - _keyStates.AddRange (_flags); - _keyStates.AddRange (_keys); - Keyboard.SetKeys(_keyStates); - } - - // This method should only be called when necessary like when the Guide is displayed - internal void ClearKeyCacheState() { - _keys.Clear(); - } - - List _keys = new List (); - List _keyStates = new List (); - - public override void KeyDown (NSEvent theEvent) - { - Keys kk = KeyUtil.GetKeys (theEvent); - - if (!_keys.Contains (kk)) - _keys.Add (kk); - - UpdateKeyboardState (); - } - - public override void KeyUp (NSEvent theEvent) - { - Keys kk = KeyUtil.GetKeys (theEvent); - - _keys.Remove (kk); - - UpdateKeyboardState (); - } - - List _flags = new List (); - - public override void FlagsChanged (NSEvent theEvent) - { - - _flags.Clear (); - var modInt = (uint)theEvent.ModifierFlags & 0xFFFF0000; - var modifier = ((NSEventModifierMask)Enum.ToObject (typeof(NSEventModifierMask), modInt)); - - switch (modifier) { - //case NSEventModifierMask.AlphaShiftKeyMask: - // return Keys.None; - case NSEventModifierMask.AlternateKeyMask: - _flags.Add (Keys.LeftAlt); - _flags.Add (Keys.RightAlt); - break; - - case NSEventModifierMask.CommandKeyMask: - _flags.Add (Keys.LeftWindows); - _flags.Add (Keys.RightWindows); - break; - case NSEventModifierMask.ControlKeyMask: - _flags.Add (Keys.LeftControl); - _flags.Add (Keys.RightControl); - break; - case NSEventModifierMask.HelpKeyMask: - _flags.Add (Keys.Help); - break; - case NSEventModifierMask.ShiftKeyMask: - _flags.Add (Keys.RightShift); - _flags.Add (Keys.LeftShift); - break; - } - - UpdateKeyboardState (); - } - - public override void MouseDown (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - switch (theEvent.Type) { - case NSEventType.LeftMouseDown: - Mouse.State.LeftButton = ButtonState.Pressed; - break; - } - } - - public override void MouseUp (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - switch (theEvent.Type) { - - case NSEventType.LeftMouseUp: - Mouse.State.LeftButton = ButtonState.Released; - break; - } - } - - public override void MouseDragged (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - } - - public override void RightMouseDown (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - switch (theEvent.Type) { - case NSEventType.RightMouseDown: - Mouse.State.RightButton = ButtonState.Pressed; - break; - } - } - - public override void RightMouseUp (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - switch (theEvent.Type) { - case NSEventType.RightMouseUp: - Mouse.State.RightButton = ButtonState.Released; - break; - } - } - - public override void RightMouseDragged (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - } - - public override void OtherMouseDown (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - switch (theEvent.Type) { - case NSEventType.OtherMouseDown: - Mouse.State.MiddleButton = ButtonState.Pressed; - break; - } - } - - public override void OtherMouseUp (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - switch (theEvent.Type) { - case NSEventType.OtherMouseUp: - Mouse.State.MiddleButton = ButtonState.Released; - break; - } - } - - public override void OtherMouseDragged (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - } - - public override void ScrollWheel (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition(loc); - - switch (theEvent.Type) { - case NSEventType.ScrollWheel: - if (theEvent.DeltaY > 0) { - Mouse.ScrollWheelValue += (theEvent.DeltaY*0.1f+0.09f)*1200; - } else { - Mouse.ScrollWheelValue += (theEvent.DeltaY*0.1f-0.09f)*1200; - } - break; - } - } - - public override void MouseMoved (NSEvent theEvent) - { - PointF loc = theEvent.LocationInWindow; - UpdateMousePosition (loc); - - switch (theEvent.Type) { - case NSEventType.MouseMoved: - //Mouse.Moved = true; - break; - } - } - - private void UpdateMousePosition (PointF location) - { - Mouse.State.X = (int)location.X; - Mouse.State.Y = (int)(ClientBounds.Height - location.Y); - } - - } -} - +#region License +/* +Microsoft Public License (Ms-PL) +XnaTouch - Copyright © 2009 The XnaTouch Team + +All rights reserved. + +This license governs use of the accompanying software. If you use the software, you accept this license. If you do not +accept the license, do not use the software. + +1. Definitions +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under +U.S. copyright law. + +A "contribution" is the original software, or any additions or changes to the software. +A "contributor" is any person that distributes its contribution under this license. +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, +each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, +each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, +your patent license from such contributor to the software ends automatically. +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution +notices that are present in the software. +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including +a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object +code form, you may only do so under a license that complies with this license. +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees +or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent +permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular +purpose and non-infringement. +*/ +#endregion License + +#region Using Statements +using System; +using System.Drawing; +using System.Collections.Generic; + +using MonoMac.CoreAnimation; +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +using MonoMac.OpenGL; +using MonoMac.AppKit; + +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Input.Touch; + +#endregion Using Statements + +namespace Microsoft.Xna.Framework +{ + public class GameWindow : MonoMacGameView + { + //private readonly Rectangle clientBounds; + private Rectangle clientBounds; + private Game _game; + private MacGamePlatform _platform; + + private NSTrackingArea _trackingArea; + private bool _needsToResetElapsedTime = false; + + public static Func CreateWindowDelegate + { + get; + set; + } + + #region GameWindow Methods + public GameWindow(Game game, RectangleF frame) : base (frame) + { + if (game == null) + throw new ArgumentNullException("game"); + _game = game; + _platform = (MacGamePlatform)_game.Services.GetService(typeof(MacGamePlatform)); + + //LayerRetainsBacking = false; + //LayerColorFormat = EAGLColorFormat.RGBA8; + this.AutoresizingMask = MonoMac.AppKit.NSViewResizingMask.HeightSizable + | MonoMac.AppKit.NSViewResizingMask.MaxXMargin + | MonoMac.AppKit.NSViewResizingMask.MinYMargin + | MonoMac.AppKit.NSViewResizingMask.WidthSizable; + + RectangleF rect = NSScreen.MainScreen.Frame; + + clientBounds = new Rectangle (0,0,(int)rect.Width,(int)rect.Height); + + // Enable multi-touch + //MultipleTouchEnabled = true; + + Mouse.Window = this; + } + + public GameWindow(Game game, RectangleF frame, NSOpenGLContext context) : + this(game, frame) + { + } + + [Export("initWithFrame:")] + public GameWindow () : base (NSScreen.MainScreen.Frame) + { + this.AutoresizingMask = MonoMac.AppKit.NSViewResizingMask.HeightSizable + | MonoMac.AppKit.NSViewResizingMask.MaxXMargin + | MonoMac.AppKit.NSViewResizingMask.MinYMargin + | MonoMac.AppKit.NSViewResizingMask.WidthSizable; + + RectangleF rect = NSScreen.MainScreen.Frame; + clientBounds = new Rectangle (0,0,(int)rect.Width,(int)rect.Height); + + // Enable multi-touch + //MultipleTouchEnabled = true; + + } + + ~GameWindow () + { + // + } + + #endregion + + public void StartRunLoop(double updateRate) + { + Run(updateRate); + } + + public void ResetElapsedTime () + { + _needsToResetElapsedTime = true; + } + #region MonoMacGameView Methods + + protected override void OnClosed (EventArgs e) + { + base.OnClosed (e); + } + + protected override void OnDisposed (EventArgs e) + { + base.OnDisposed (e); + } + + protected override void OnLoad (EventArgs e) + { + base.OnLoad (e); + } + + protected override void OnRenderFrame (FrameEventArgs e) + { + base.OnRenderFrame (e); + + // FIXME: Since Game.Exit may be called during an Update loop (and + // in fact that is quite likely to happen), this code is now + // littered with checks to _platform.IsRunning. It would be + // nice if there weren't quite so many. The move to a + // Game.Tick-centric architecture may eliminate this problem + // automatically. + if (_game != null && _platform.IsRunning) { + _game.Tick(); + } + } +// protected override void OnUpdateFrame (FrameEventArgs e) +// { +// base.OnUpdateFrame (e); +// +// } + protected override void OnResize (EventArgs e) + { + var manager = (GraphicsDeviceManager)_game.Services.GetService(typeof(IGraphicsDeviceManager)); + if (_game.Initialized) + { + manager.OnDeviceResetting(EventArgs.Empty); + + Microsoft.Xna.Framework.Graphics.Viewport _vp = + new Microsoft.Xna.Framework.Graphics.Viewport(); + + _game.GraphicsDevice.PresentationParameters.BackBufferWidth = (int)Bounds.Width; + _game.GraphicsDevice.PresentationParameters.BackBufferHeight = (int)Bounds.Height; + + _vp.X = (int)Bounds.X; + _vp.Y = (int)Bounds.Y; + _vp.Width = (int)Bounds.Width; + _vp.Height = (int)Bounds.Height; + + _game.GraphicsDevice.Viewport = _vp; + } + + clientBounds = new Rectangle((int)Bounds.X,(int)Bounds.Y,(int)Bounds.Width,(int)Bounds.Height); + + base.OnResize(e); + OnClientSizeChanged(e); + + if (_game.Initialized) + manager.OnDeviceReset(EventArgs.Empty); + } + + protected virtual void OnClientSizeChanged (EventArgs e) + { + var h = ClientSizeChanged; + if (h != null) + h (this, e); + } + + protected override void OnTitleChanged (EventArgs e) + { + base.OnTitleChanged (e); + } + + protected override void OnUnload (EventArgs e) + { + base.OnUnload (e); + } + + protected override void OnVisibleChanged (EventArgs e) + { + base.OnVisibleChanged (e); + } + + protected override void OnWindowStateChanged (EventArgs e) + { + base.OnWindowStateChanged (e); + } + + #endregion + + #region UIVIew Methods + + /* TODO private readonly Dictionary previousTouches = new Dictionary(); + + private void FillTouchCollection(NSSet touches) + { + UITouch []touchesArray = touches.ToArray(); + + TouchPanel.Collection.Clear(); + TouchPanel.Collection.Capacity = touchesArray.Length; + + for (int i=0; i ClientSizeChanged; + public event EventHandler OrientationChanged; + public event EventHandler ScreenDeviceNameChanged; + + // make sure we get mouse move events. + public override bool AcceptsFirstResponder () + { + return true; + } + + public override bool BecomeFirstResponder () + { + return true; + } + public override void CursorUpdate (NSEvent theEvent) + { + base.CursorUpdate (theEvent); + } + + public override void ViewWillMoveToWindow (NSWindow newWindow) + { + //Console.WriteLine("View will move to window"); + if (_trackingArea != null) RemoveTrackingArea(_trackingArea); + _trackingArea = new NSTrackingArea(Frame, + NSTrackingAreaOptions.MouseMoved | + NSTrackingAreaOptions.MouseEnteredAndExited | + NSTrackingAreaOptions.EnabledDuringMouseDrag | + NSTrackingAreaOptions.ActiveWhenFirstResponder | + NSTrackingAreaOptions.InVisibleRect | + NSTrackingAreaOptions.CursorUpdate, + this, new NSDictionary()); + AddTrackingArea(_trackingArea); + + } + + // These variables are to handle our custom cursor for when IsMouseVisible is false. + // Hiding and unhiding the cursor was such a pain that I decided to let the system + // take care of this with Cursor Rectangles + NSImage cursorImage = null; // Will be set to our custom image + NSCursor cursor = null; // Our custom cursor + public override void ResetCursorRects () + { + + // If we do not have a cursor then we create an image size 1 x 1 + // and then create our custom cursor with clear colors + if (cursor == null) { + cursorImage = new NSImage(new SizeF(1,1)); + cursor = new NSCursor(cursorImage, NSColor.Clear, NSColor.Clear, new PointF(0,0)); + } + + // if the cursor is not to be visible then we us our custom cursor. + if (!_game.IsMouseVisible) + AddCursorRect(Frame, cursor); + else + AddCursorRect(Frame, NSCursor.ArrowCursor); + + } + + public override void DiscardCursorRects () + { + base.DiscardCursorRects (); + //Console.WriteLine("DiscardCursorRects"); + } + private void UpdateKeyboardState () + { + _keyStates.Clear (); + _keyStates.AddRange (_flags); + _keyStates.AddRange (_keys); + Keyboard.SetKeys(_keyStates); + } + + // This method should only be called when necessary like when the Guide is displayed + internal void ClearKeyCacheState() { + _keys.Clear(); + } + + List _keys = new List (); + List _keyStates = new List (); + + public override void KeyDown (NSEvent theEvent) + { + Keys kk = KeyUtil.GetKeys (theEvent); + + if (!_keys.Contains (kk)) + _keys.Add (kk); + + UpdateKeyboardState (); + } + + public override void KeyUp (NSEvent theEvent) + { + Keys kk = KeyUtil.GetKeys (theEvent); + + _keys.Remove (kk); + + UpdateKeyboardState (); + } + + List _flags = new List (); + + public override void FlagsChanged (NSEvent theEvent) + { + + _flags.Clear (); + var modInt = (uint)theEvent.ModifierFlags & 0xFFFF0000; + var modifier = ((NSEventModifierMask)Enum.ToObject (typeof(NSEventModifierMask), modInt)); + + switch (modifier) { + //case NSEventModifierMask.AlphaShiftKeyMask: + // return Keys.None; + case NSEventModifierMask.AlternateKeyMask: + _flags.Add (Keys.LeftAlt); + _flags.Add (Keys.RightAlt); + break; + + case NSEventModifierMask.CommandKeyMask: + _flags.Add (Keys.LeftWindows); + _flags.Add (Keys.RightWindows); + break; + case NSEventModifierMask.ControlKeyMask: + _flags.Add (Keys.LeftControl); + _flags.Add (Keys.RightControl); + break; + case NSEventModifierMask.HelpKeyMask: + _flags.Add (Keys.Help); + break; + case NSEventModifierMask.ShiftKeyMask: + _flags.Add (Keys.RightShift); + _flags.Add (Keys.LeftShift); + break; + } + + UpdateKeyboardState (); + } + + public override void MouseDown (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + switch (theEvent.Type) { + case NSEventType.LeftMouseDown: + Mouse.State.LeftButton = ButtonState.Pressed; + break; + } + } + + public override void MouseUp (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + switch (theEvent.Type) { + + case NSEventType.LeftMouseUp: + Mouse.State.LeftButton = ButtonState.Released; + break; + } + } + + public override void MouseDragged (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + } + + public override void RightMouseDown (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + switch (theEvent.Type) { + case NSEventType.RightMouseDown: + Mouse.State.RightButton = ButtonState.Pressed; + break; + } + } + + public override void RightMouseUp (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + switch (theEvent.Type) { + case NSEventType.RightMouseUp: + Mouse.State.RightButton = ButtonState.Released; + break; + } + } + + public override void RightMouseDragged (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + } + + public override void OtherMouseDown (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + switch (theEvent.Type) { + case NSEventType.OtherMouseDown: + Mouse.State.MiddleButton = ButtonState.Pressed; + break; + } + } + + public override void OtherMouseUp (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + switch (theEvent.Type) { + case NSEventType.OtherMouseUp: + Mouse.State.MiddleButton = ButtonState.Released; + break; + } + } + + public override void OtherMouseDragged (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + } + + public override void ScrollWheel (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition(loc); + + switch (theEvent.Type) { + case NSEventType.ScrollWheel: + if (theEvent.DeltaY > 0) { + Mouse.ScrollWheelValue += (theEvent.DeltaY*0.1f+0.09f)*1200; + } else { + Mouse.ScrollWheelValue += (theEvent.DeltaY*0.1f-0.09f)*1200; + } + break; + } + } + + public override void MouseMoved (NSEvent theEvent) + { + PointF loc = theEvent.LocationInWindow; + UpdateMousePosition (loc); + + switch (theEvent.Type) { + case NSEventType.MouseMoved: + //Mouse.Moved = true; + break; + } + } + + private void UpdateMousePosition (PointF location) + { + Mouse.State.X = (int)location.X; + Mouse.State.Y = (int)(ClientBounds.Height - location.Y); + } + + } +} + diff --git a/MonoGame.Framework/iOS/OrientationConverter.cs b/MonoGame.Framework/iOS/OrientationConverter.cs index a9f22a4fc80..9ad316f8fea 100644 --- a/MonoGame.Framework/iOS/OrientationConverter.cs +++ b/MonoGame.Framework/iOS/OrientationConverter.cs @@ -77,15 +77,15 @@ public static DisplayOrientation UIDeviceOrientationToDisplayOrientation(UIDevic { switch (orientation) { - case UIDeviceOrientation.FaceDown: return DisplayOrientation.FaceDown; - case UIDeviceOrientation.FaceUp: return DisplayOrientation.FaceUp; + case UIDeviceOrientation.FaceDown: return DisplayOrientation.Unknown; + case UIDeviceOrientation.FaceUp: return DisplayOrientation.Unknown; default: // NOTE: in XNA, Orientation Left is a 90 degree rotation counterclockwise, while on iOS // it is a 90 degree rotation CLOCKWISE. They are BACKWARDS! case UIDeviceOrientation.LandscapeLeft: return DisplayOrientation.LandscapeRight; case UIDeviceOrientation.LandscapeRight: return DisplayOrientation.LandscapeLeft; case UIDeviceOrientation.Portrait: return DisplayOrientation.Portrait; - case UIDeviceOrientation.PortraitUpsideDown: return DisplayOrientation.PortraitUpsideDown; + case UIDeviceOrientation.PortraitUpsideDown: return DisplayOrientation.PortraitDown; } } @@ -99,7 +99,7 @@ public static DisplayOrientation ToDisplayOrientation(UIInterfaceOrientation ori case UIInterfaceOrientation.LandscapeLeft: return DisplayOrientation.LandscapeRight; case UIInterfaceOrientation.LandscapeRight: return DisplayOrientation.LandscapeLeft; case UIInterfaceOrientation.Portrait: return DisplayOrientation.Portrait; - case UIInterfaceOrientation.PortraitUpsideDown: return DisplayOrientation.PortraitUpsideDown; + case UIInterfaceOrientation.PortraitUpsideDown: return DisplayOrientation.PortraitDown; } } @@ -107,18 +107,18 @@ public static UIInterfaceOrientationMask ToUIInterfaceOrientationMask (DisplayOr { switch (Normalize(orientation)) { - case((DisplayOrientation)1): - case((DisplayOrientation)6): + case((DisplayOrientation)0): + case((DisplayOrientation)3): return UIInterfaceOrientationMask.Landscape; - case((DisplayOrientation)2): + case((DisplayOrientation)1): return UIInterfaceOrientationMask.LandscapeLeft; - case((DisplayOrientation)4): + case((DisplayOrientation)2): return UIInterfaceOrientationMask.LandscapeRight; - case((DisplayOrientation)16): + case((DisplayOrientation)4): return UIInterfaceOrientationMask.Portrait; - case((DisplayOrientation)32): + case((DisplayOrientation)8): return UIInterfaceOrientationMask.PortraitUpsideDown; - case((DisplayOrientation)14): + case((DisplayOrientation)7): return UIInterfaceOrientationMask.AllButUpsideDown; default: return UIInterfaceOrientationMask.All;