using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using FSO.Common.Rendering.Framework.Model; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input.Touch; namespace FSO.Common.Rendering.Framework { /// /// A screen used for drawing. /// public class GameScreen { public List Layers = new List(); public GraphicsDevice Device; public UpdateState State; public static Color ClearColor = new Color(0x72, 0x72, 0x72); private int touchedFrames; private int lastTouchCount; private MouseState lastMouseState; private Vector2? prevTouchAvg; private const int TOUCH_ACCEPT_TIME = 5; public GameScreen(GraphicsDevice device) { this.Device = device; State = new UpdateState(); } private static List TextCharacters = new List(); public static void TextInput(object sender, TextInputEventArgs e) { TextCharacters.Add(e.Character); } /// /// Adds a graphical element to this scene. /// /// Element inheriting from IGraphicsLayer. public void Add(IGraphicsLayer layer) { layer.Initialize(Device); Layers.Add(layer); } public void Update(GameTime time, bool hasFocus) { State.Time = time; State.PreviousKeyboardState = State.KeyboardState; State.FrameTextInput = TextCharacters; var touchMode = FSOEnvironment.SoftwareKeyboard; if (touchMode) { if (FSOEnvironment.SoftwareDepth) State.KeyboardState = new KeyboardState(); TouchCollection touches = TouchPanel.GetState(); var missing = new HashSet(State.MouseStates); //relate touches to their last virtual mouse foreach (var touch in touches) { var mouse = State.MouseStates.FirstOrDefault(x => x.ID == touch.Id); if (mouse == null) { mouse = new MultiMouse { ID = touch.Id }; State.MouseStates.Add(mouse); } missing.Remove(mouse); mouse.MouseState = new MouseState( (int)touch.Position.X, (int)touch.Position.Y, 0, ButtonState.Pressed, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released ); } //if virtual mouses no longer have their touch, they are performing a "mouse up" //if the state has mouseovers, we should record the mouse state as being lifted. foreach (var miss in missing) { if (miss.LastMouseOver == null && miss.LastMouseDown == null) { State.MouseStates.Remove(miss); } else { miss.MouseState = new MouseState(miss.MouseState.X, miss.MouseState.Y, 0, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released); miss.Dead = true; } } } else { //single mouse state if (hasFocus) { State.MouseState = Mouse.GetState(); State.KeyboardState = Keyboard.GetState(); } else { State.MouseState = new MouseState(); State.KeyboardState = new KeyboardState(); } if (State.KeyboardState.IsKeyDown(Keys.LeftAlt) && State.MouseState.LeftButton == ButtonState.Pressed) { //emulated middle click with alt var ms = State.MouseState; State.MouseState = new MouseState(ms.X, ms.Y, ms.ScrollWheelValue, ButtonState.Released, ButtonState.Pressed, ms.RightButton, ms.XButton1, ms.XButton2); } if (State.MouseStates.Count == 0) { State.MouseStates.Add(new MultiMouse { ID = 1 }); } State.MouseStates[0].MouseState = State.MouseState; } State.SharedData.Clear(); State.Update(); foreach (var layer in Layers){ layer.Update(State); } TextCharacters.Clear(); } private void TouchStub(UpdateState state) { var test = TouchPanel.EnableMouseTouchPoint; TouchCollection touches = TouchPanel.GetState(); if (touches.Count != lastTouchCount) touchedFrames = 0; lastTouchCount = touches.Count; if (touches.Count > 0) { Vector2 avg = new Vector2(); for (int i = 0; i < touches.Count; i++) { avg += touches[i].Position; } avg /= touches.Count; if (touchedFrames < TOUCH_ACCEPT_TIME) { avg = prevTouchAvg ?? avg; state.MouseState = new MouseState( (int)avg.X, (int)avg.Y, state.MouseState.ScrollWheelValue, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released ); touchedFrames++; } else { state.MouseState = new MouseState( (int)avg.X, (int)avg.Y, state.MouseState.ScrollWheelValue, (touches.Count > 1) ? ButtonState.Released : ButtonState.Pressed, (touches.Count > 1) ? ButtonState.Pressed : ButtonState.Released, (touches.Count > 1) ? ButtonState.Pressed : ButtonState.Released, ButtonState.Released, ButtonState.Released ); prevTouchAvg = avg; state.TouchMode = true; } } else { prevTouchAvg = null; touchedFrames = 0; if (state.TouchMode) state.MouseState = new MouseState( lastMouseState.X, lastMouseState.Y, state.MouseState.ScrollWheelValue, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released ); //state.TouchMode = false; } lastMouseState = state.MouseState; } public void Draw(GameTime time) { lock (Device) { foreach (var layer in Layers.Reverse()) { layer.PreDraw(Device); } } Device.SetRenderTarget(null); Device.BlendState = BlendState.AlphaBlend; Device.Clear(ClearColor); //Device.RasterizerState.AlphaBlendEnable = true; //Device.DepthStencilState.DepthBufferEnable = true; lock (Device) { foreach (var layer in Layers) { layer.Draw(Device); } } } } }