diff --git a/Makefile b/Makefile index cc5a312360..678ef430f9 100644 --- a/Makefile +++ b/Makefile @@ -110,34 +110,34 @@ rsdl_SRCS := $(shell find OpenRA.Renderer.SdlCommon/ -iname '*.cs') rsdl_TARGET = OpenRA.Renderer.SdlCommon.dll rsdl_KIND = library rsdl_DEPS = $(fileformats_TARGET) $(game_TARGET) -rsdl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \ - thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \ +rsdl_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \ $(rsdl_DEPS) rcg_SRCS := $(shell find OpenRA.Renderer.Cg/ -iname '*.cs') rcg_TARGET = OpenRA.Renderer.Cg.dll rcg_KIND = library rcg_DEPS = $(fileformats_TARGET) $(game_TARGET) $(rsdl_TARGET) -rcg_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \ - thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \ - $(rcg_DEPS) +rcg_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll $(rcg_DEPS) rgl_SRCS := $(shell find OpenRA.Renderer.Gl/ -iname '*.cs') rgl_TARGET = OpenRA.Renderer.Gl.dll rgl_KIND = library rgl_DEPS = $(fileformats_TARGET) $(game_TARGET) $(rsdl_TARGET) -rgl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \ - thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \ - $(rgl_DEPS) +rgl_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.OpenGl.dll $(rgl_DEPS) + +rsdl2_SRCS := $(shell find OpenRA.Renderer.Sdl2/ -iname '*.cs') +rsdl2_TARGET = OpenRA.Renderer.Sdl2.dll +rsdl2_KIND = library +rsdl2_DEPS = $(fileformats_TARGET) $(game_TARGET) $(rsdl_TARGET) $(rgl_TARGET) +rsdl2_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.OpenGl.dll thirdparty/SDL2\#.dll $(rsdl2_DEPS) rnull_SRCS := $(shell find OpenRA.Renderer.Null/ -iname '*.cs') -rnull_TARGET = OpenRA.Renderer.Null.dll +rnull_TARGET = OpenRA.Renderer.Null.dll rnull_KIND = library rnull_DEPS = $(fileformats_TARGET) $(game_TARGET) -rnull_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \ - $(rnull_DEPS) -PROGRAMS += rcg rgl rnull rsdl -renderers: $(rcg_TARGET) $(rgl_TARGET) $(rnull_TARGET) $(rsdl_TARGET) +rnull_LIBS = $(COMMON_LIBS) $(rnull_DEPS) +PROGRAMS += rcg rgl rsdl2 rnull rsdl +renderers: $(rcg_TARGET) $(rgl_TARGET) $(rsdl2_TARGET) $(rnull_TARGET) $(rsdl_TARGET) ##### Official Mods ##### diff --git a/OpenRA.FileFormats/Graphics/IInputHandler.cs b/OpenRA.FileFormats/Graphics/IInputHandler.cs index b4ab513100..37ef56259b 100755 --- a/OpenRA.FileFormats/Graphics/IInputHandler.cs +++ b/OpenRA.FileFormats/Graphics/IInputHandler.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -16,11 +16,13 @@ namespace OpenRA { public interface IInputHandler { - void ModifierKeys( Modifiers mods ); - void OnKeyInput( KeyInput input ); - void OnMouseInput( MouseInput input ); + void ModifierKeys(Modifiers mods); + void OnKeyInput(KeyInput input); + void OnMouseInput(MouseInput input); + void OnTextInput(string text); } + public enum MouseInputEvent { Down, Move, Up } public struct MouseInput { public MouseInputEvent Event; @@ -29,18 +31,16 @@ namespace OpenRA public Modifiers Modifiers; public int MultiTapCount; - public MouseInput( MouseInputEvent ev, MouseButton button, int2 location, Modifiers mods, int multiTapCount ) + public MouseInput(MouseInputEvent ev, MouseButton button, int2 location, Modifiers mods, int multiTapCount) { - this.Event = ev; - this.Button = button; - this.Location = location; - this.Modifiers = mods; - this.MultiTapCount = multiTapCount; + Event = ev; + Button = button; + Location = location; + Modifiers = mods; + MultiTapCount = multiTapCount; } } - public enum MouseInputEvent { Down, Move, Up }; - [Flags] public enum MouseButton { @@ -62,7 +62,7 @@ namespace OpenRA Meta = 8, } - public enum KeyInputEvent { Down, Up }; + public enum KeyInputEvent { Down, Up } public struct KeyInput { public KeyInputEvent Event; diff --git a/OpenRA.Game/InputHandler.cs b/OpenRA.Game/InputHandler.cs index fc76273f2c..a16b9a1c5f 100755 --- a/OpenRA.Game/InputHandler.cs +++ b/OpenRA.Game/InputHandler.cs @@ -17,6 +17,7 @@ namespace OpenRA // ignore all input public void ModifierKeys(Modifiers mods) { } public void OnKeyInput(KeyInput input) { } + public void OnTextInput(string text) { } public void OnMouseInput(MouseInput input) { } } @@ -38,6 +39,11 @@ namespace OpenRA Sync.CheckSyncUnchanged(world, () => Ui.HandleKeyPress(input)); } + public void OnTextInput(string text) + { + Sync.CheckSyncUnchanged(world, () => Ui.HandleTextInput(text)); + } + public void OnMouseInput(MouseInput input) { Sync.CheckSyncUnchanged(world, () => Ui.HandleInput(input)); diff --git a/OpenRA.Game/Widgets/TextFieldWidget.cs b/OpenRA.Game/Widgets/TextFieldWidget.cs index b4e8bb5d5e..b9dc51cd05 100644 --- a/OpenRA.Game/Widgets/TextFieldWidget.cs +++ b/OpenRA.Game/Widgets/TextFieldWidget.cs @@ -154,27 +154,24 @@ namespace OpenRA.Widgets return true; } - TypeChar(e); - return true; - } - - public void TypeChar(KeyInput key) - { - if (key.Key == Keycode.BACKSPACE && CursorPosition > 0) + if (e.Key == Keycode.BACKSPACE && CursorPosition > 0) { CursorPosition--; Text = Text.Remove(CursorPosition, 1); } - else if (key.IsValidInput()) - { - if (MaxLength > 0 && Text.Length >= MaxLength) - return; + return true; + } - Text = Text.Insert(CursorPosition, key.UnicodeChar.ToString()); + public override bool HandleTextInput(string text) + { + if (MaxLength > 0 && Text.Length >= MaxLength) + return true; - CursorPosition++; - } + Text = Text.Insert(CursorPosition, text); + CursorPosition++; + + return true; } protected int blinkCycle = 10; diff --git a/OpenRA.Game/Widgets/Widget.cs b/OpenRA.Game/Widgets/Widget.cs index beb4756679..2d662087f0 100644 --- a/OpenRA.Game/Widgets/Widget.cs +++ b/OpenRA.Game/Widgets/Widget.cs @@ -104,9 +104,15 @@ namespace OpenRA.Widgets if (KeyboardFocusWidget != null) return KeyboardFocusWidget.HandleKeyPressOuter(e); - if (Root.HandleKeyPressOuter(e)) - return true; - return false; + return Root.HandleKeyPressOuter(e); + } + + public static bool HandleTextInput(string text) + { + if (KeyboardFocusWidget != null) + return KeyboardFocusWidget.HandleTextInputOuter(text); + + return Root.HandleTextInputOuter(text); } public static void ResetAll() @@ -334,12 +340,30 @@ namespace OpenRA.Widgets if (child.HandleKeyPressOuter(e)) return true; - // Do any widgety behavior (enter text etc) + // Do any widgety behavior var handled = HandleKeyPress(e); return handled; } + public virtual bool HandleTextInput(string text) { return false; } + + public virtual bool HandleTextInputOuter(string text) + { + if (!IsVisible()) + return false; + + // Can any of our children handle this? + foreach (var child in Children.OfType().Reverse()) + if (child.HandleTextInputOuter(text)) + return true; + + // Do any widgety behavior (enter text etc) + var handled = HandleTextInput(text); + + return handled; + } + public virtual void Draw() {} public virtual void DrawOuter() diff --git a/OpenRA.Renderer.Cg/OpenRA.Renderer.Cg.csproj b/OpenRA.Renderer.Cg/OpenRA.Renderer.Cg.csproj index 7186e7810f..fd95732782 100644 --- a/OpenRA.Renderer.Cg/OpenRA.Renderer.Cg.csproj +++ b/OpenRA.Renderer.Cg/OpenRA.Renderer.Cg.csproj @@ -55,13 +55,7 @@ - - 3.5 - - - - False ..\thirdparty\Tao\Tao.Cg.dll diff --git a/OpenRA.Renderer.Gl/GraphicsDevice.cs b/OpenRA.Renderer.Gl/GraphicsDevice.cs index 46d32f1e58..844f0d2fd4 100755 --- a/OpenRA.Renderer.Gl/GraphicsDevice.cs +++ b/OpenRA.Renderer.Gl/GraphicsDevice.cs @@ -39,6 +39,6 @@ namespace OpenRA.Renderer.Glsl public GraphicsDevice(Size size, WindowMode window) : base(size, window, requiredExtensions) { } - public override IShader CreateShader(string name) { return new Shader(this, name); } + public override IShader CreateShader(string name) { return new Shader(name); } } } diff --git a/OpenRA.Renderer.Gl/OpenRA.Renderer.Gl.csproj b/OpenRA.Renderer.Gl/OpenRA.Renderer.Gl.csproj index eeb08b83f7..5c2079d64c 100644 --- a/OpenRA.Renderer.Gl/OpenRA.Renderer.Gl.csproj +++ b/OpenRA.Renderer.Gl/OpenRA.Renderer.Gl.csproj @@ -62,13 +62,7 @@ False ..\thirdparty\Tao\Tao.Sdl.dll - - 3.5 - - - - False ..\thirdparty\Tao\Tao.Cg.dll diff --git a/OpenRA.Renderer.Gl/Shader.cs b/OpenRA.Renderer.Gl/Shader.cs index 3465f18c64..e4b62793f1 100644 --- a/OpenRA.Renderer.Gl/Shader.cs +++ b/OpenRA.Renderer.Gl/Shader.cs @@ -25,7 +25,7 @@ namespace OpenRA.Renderer.Glsl readonly Dictionary textures = new Dictionary(); int program; - public Shader(GraphicsDevice dev, string name) + public Shader(string name) { // Vertex shader string vertexCode; diff --git a/OpenRA.Renderer.Null/OpenRA.Renderer.Null.csproj b/OpenRA.Renderer.Null/OpenRA.Renderer.Null.csproj index e6cf42a74f..7383d4c86e 100644 --- a/OpenRA.Renderer.Null/OpenRA.Renderer.Null.csproj +++ b/OpenRA.Renderer.Null/OpenRA.Renderer.Null.csproj @@ -53,19 +53,7 @@ - - 3.5 - - - - 3.5 - - - 3.5 - - - diff --git a/OpenRA.Renderer.Sdl2/OpenRA.Renderer.Sdl2.csproj b/OpenRA.Renderer.Sdl2/OpenRA.Renderer.Sdl2.csproj new file mode 100644 index 0000000000..4a36941eed --- /dev/null +++ b/OpenRA.Renderer.Sdl2/OpenRA.Renderer.Sdl2.csproj @@ -0,0 +1,68 @@ + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {33D03738-C154-4028-8EA8-63A3C488A651} + Library + OpenRA.Renderer.Sdl2 + OpenRA.Renderer.Sdl2 + v3.5 + + + True + full + False + ..\ + DEBUG; + prompt + 4 + False + True + AllRules.ruleset + + + none + false + bin\Release + prompt + 4 + True + False + + + + + ..\thirdparty\Tao\Tao.OpenGl.dll + + + + ..\thirdparty\SDL2#.dll + + + + + + + + + + {BDAEAB25-991E-46A7-AF1E-4F0E03358DAA} + OpenRA.FileFormats + + + {0DFB103F-2962-400F-8C6D-E2C28CCBA633} + OpenRA.Game + + + {52FD9F0B-B209-4ED7-8A32-AC8033363263} + OpenRA.Renderer.SdlCommon + + + {E9C01A96-C3E2-4772-825B-A740AC513D31} + OpenRA.Renderer.Gl + + + \ No newline at end of file diff --git a/OpenRA.Renderer.Sdl2/Sdl2GraphicsDevice.cs b/OpenRA.Renderer.Sdl2/Sdl2GraphicsDevice.cs new file mode 100755 index 0000000000..df2820afb0 --- /dev/null +++ b/OpenRA.Renderer.Sdl2/Sdl2GraphicsDevice.cs @@ -0,0 +1,219 @@ +#region Copyright & License Information +/* +* Copyright 2007-2013 The OpenRA Developers (see AUTHORS) +* This file is part of OpenRA, which is free software. It is made +* available to you under the terms of the GNU General Public License +* as published by the Free Software Foundation. For more information, +* see COPYING. +*/ +#endregion + +using System; +using System.Drawing; +using System.Linq; +using OpenRA.FileFormats.Graphics; +using OpenRA.Renderer.Glsl; +using OpenRA.Renderer.SdlCommon; +using SDL2; +using Tao.OpenGl; + +[assembly: Renderer(typeof(OpenRA.Renderer.Sdl2.DeviceFactory))] + +namespace OpenRA.Renderer.Sdl2 +{ + public class DeviceFactory : IDeviceFactory + { + public IGraphicsDevice Create(Size size, WindowMode windowMode) + { + Console.WriteLine("Using SDL2 renderer"); + return new Sdl2GraphicsDevice(size, windowMode); + } + } + + public class Sdl2GraphicsDevice : IGraphicsDevice + { + static string[] requiredExtensions = + { + "GL_ARB_vertex_shader", + "GL_ARB_fragment_shader", + "GL_ARB_vertex_buffer_object", + "GL_EXT_framebuffer_object" + }; + + Size size; + Sdl2Input input; + IntPtr window; + + public Size WindowSize { get { return size; } } + + public Sdl2GraphicsDevice(Size windowSize, WindowMode windowMode) + { + size = windowSize; + + SDL.SDL_Init(SDL.SDL_INIT_NOPARACHUTE | SDL.SDL_INIT_VIDEO); + SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1); + SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_RED_SIZE, 8); + SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_GREEN_SIZE, 8); + SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_BLUE_SIZE, 8); + SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ALPHA_SIZE, 0); + + var windowFlags = SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL; + if (windowMode == WindowMode.Fullscreen) + windowFlags |= SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN; + else if (windowMode == WindowMode.PseudoFullscreen) + { + windowFlags |= SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP; + Environment.SetEnvironmentVariable("SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS", "0"); + } + + SDL.SDL_DisplayMode display; + SDL.SDL_GetCurrentDisplayMode(0, out display); + + Console.WriteLine("Desktop resolution: {0}x{1}", display.w, display.h); + if (size.Width == 0 && size.Height == 0) + { + Console.WriteLine("No custom resolution provided, using desktop resolution"); + size = new Size(display.w, display.h); + } + + Console.WriteLine("Using resolution: {0}x{1}", size.Width, size.Height); + + window = SDL.SDL_CreateWindow("OpenRA", SDL.SDL_WINDOWPOS_CENTERED, SDL.SDL_WINDOWPOS_CENTERED, size.Width, size.Height, windowFlags); + + SDL.SDL_ShowCursor(0); + SDL.SDL_GL_CreateContext(window); + ErrorHandler.CheckGlError(); + + var extensions = Gl.glGetString(Gl.GL_EXTENSIONS); + if (extensions == null) + Console.WriteLine("Failed to fetch GL_EXTENSIONS, this is bad."); + + var missingExtensions = requiredExtensions.Where(r => !extensions.Contains(r)).ToArray(); + if (missingExtensions.Any()) + { + ErrorHandler.WriteGraphicsLog("Unsupported GPU: Missing extensions: {0}".F(missingExtensions.JoinWith(","))); + throw new InvalidProgramException("Unsupported GPU. See graphics.log for details."); + } + + Gl.glEnableClientState(Gl.GL_VERTEX_ARRAY); + ErrorHandler.CheckGlError(); + Gl.glEnableClientState(Gl.GL_TEXTURE_COORD_ARRAY); + ErrorHandler.CheckGlError(); + + SDL.SDL_SetModState(0); + input = new Sdl2Input(); + } + + public virtual void Quit() + { + SDL.SDL_Quit(); + } + + int ModeFromPrimitiveType(PrimitiveType pt) + { + switch (pt) + { + case PrimitiveType.PointList: return Gl.GL_POINTS; + case PrimitiveType.LineList: return Gl.GL_LINES; + case PrimitiveType.TriangleList: return Gl.GL_TRIANGLES; + case PrimitiveType.QuadList: return Gl.GL_QUADS; + } + + throw new NotImplementedException(); + } + + public void DrawPrimitives(PrimitiveType pt, int firstVertex, int numVertices) + { + Gl.glDrawArrays(ModeFromPrimitiveType(pt), firstVertex, numVertices); + ErrorHandler.CheckGlError(); + } + + public void Clear() + { + Gl.glClearColor(0, 0, 0, 0); + ErrorHandler.CheckGlError(); + Gl.glClear(Gl.GL_COLOR_BUFFER_BIT); + ErrorHandler.CheckGlError(); + } + + public void EnableDepthBuffer() + { + Gl.glClear(Gl.GL_DEPTH_BUFFER_BIT); + ErrorHandler.CheckGlError(); + Gl.glEnable(Gl.GL_DEPTH_TEST); + ErrorHandler.CheckGlError(); + } + + public void DisableDepthBuffer() + { + Gl.glDisable(Gl.GL_DEPTH_TEST); + ErrorHandler.CheckGlError(); + } + + public void SetBlendMode(BlendMode mode) + { + Gl.glBlendEquation(Gl.GL_FUNC_ADD); + ErrorHandler.CheckGlError(); + + switch (mode) + { + case BlendMode.None: + Gl.glDisable(Gl.GL_BLEND); + break; + case BlendMode.Alpha: + Gl.glEnable(Gl.GL_BLEND); + ErrorHandler.CheckGlError(); + Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA); + break; + case BlendMode.Additive: + Gl.glEnable(Gl.GL_BLEND); + ErrorHandler.CheckGlError(); + Gl.glBlendFunc(Gl.GL_ONE, Gl.GL_ONE); + break; + case BlendMode.Subtractive: + Gl.glEnable(Gl.GL_BLEND); + ErrorHandler.CheckGlError(); + Gl.glBlendFunc(Gl.GL_ONE, Gl.GL_ONE); + ErrorHandler.CheckGlError(); + Gl.glBlendEquation(Gl.GL_FUNC_REVERSE_SUBTRACT); + break; + } + + ErrorHandler.CheckGlError(); + } + + public void EnableScissor(int left, int top, int width, int height) + { + if (width < 0) + width = 0; + + if (height < 0) + height = 0; + + Gl.glScissor(left, size.Height - (top + height), width, height); + ErrorHandler.CheckGlError(); + Gl.glEnable(Gl.GL_SCISSOR_TEST); + ErrorHandler.CheckGlError(); + } + + public void DisableScissor() + { + Gl.glDisable(Gl.GL_SCISSOR_TEST); + ErrorHandler.CheckGlError(); + } + + public void SetLineWidth(float width) + { + Gl.glLineWidth(width); + ErrorHandler.CheckGlError(); + } + + public void Present() { SDL.SDL_GL_SwapWindow(window); } + public void PumpInput(IInputHandler inputHandler) { input.PumpInput(inputHandler); } + public IVertexBuffer CreateVertexBuffer(int size) { return new VertexBuffer(size); } + public ITexture CreateTexture() { return new Texture(); } + public ITexture CreateTexture(Bitmap bitmap) { return new Texture(bitmap); } + public IFrameBuffer CreateFrameBuffer(Size s) { return new FrameBuffer(s); } + public IShader CreateShader(string name) { return new Shader(name); } + } +} diff --git a/OpenRA.Renderer.Sdl2/Sdl2Input.cs b/OpenRA.Renderer.Sdl2/Sdl2Input.cs new file mode 100644 index 0000000000..686b21ccc9 --- /dev/null +++ b/OpenRA.Renderer.Sdl2/Sdl2Input.cs @@ -0,0 +1,200 @@ +#region Copyright & License Information +/* +* Copyright 2007-2013 The OpenRA Developers (see AUTHORS) +* This file is part of OpenRA, which is free software. It is made +* available to you under the terms of the GNU General Public License +* as published by the Free Software Foundation. For more information, +* see COPYING. +*/ +#endregion + +using System; +using System.IO; +using System.Text; +using OpenRA.Renderer.SdlCommon; +using SDL2; + +namespace OpenRA.Renderer.Sdl2 +{ + public class Sdl2Input + { + MouseButton lastButtonBits = (MouseButton)0; + + MouseButton MakeButton(byte b) + { + return b == SDL.SDL_BUTTON_LEFT ? MouseButton.Left + : b == SDL.SDL_BUTTON_RIGHT ? MouseButton.Right + : b == SDL.SDL_BUTTON_MIDDLE ? MouseButton.Middle + : 0; + } + + Modifiers MakeModifiers(int raw) + { + return ((raw & (int)SDL.SDL_Keymod.KMOD_ALT) != 0 ? Modifiers.Alt : 0) + | ((raw & (int)SDL.SDL_Keymod.KMOD_CTRL) != 0 ? Modifiers.Ctrl : 0) + | ((raw & (int)SDL.SDL_Keymod.KMOD_LGUI) != 0 ? Modifiers.Meta : 0) + | ((raw & (int)SDL.SDL_Keymod.KMOD_RGUI) != 0 ? Modifiers.Meta : 0) + | ((raw & (int)SDL.SDL_Keymod.KMOD_SHIFT) != 0 ? Modifiers.Shift : 0); + } + + public void PumpInput(IInputHandler inputHandler) + { + var mods = MakeModifiers((int)SDL.SDL_GetModState()); + inputHandler.ModifierKeys(mods); + MouseInput? pendingMotion = null; + + SDL.SDL_Event e; + while (SDL.SDL_PollEvent(out e) != 0) + { + switch (e.type) + { + case SDL.SDL_EventType.SDL_QUIT: + OpenRA.Game.Exit(); + break; + + case SDL.SDL_EventType.SDL_WINDOWEVENT: + { + switch (e.window.windowEvent) + { + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_LOST: + Game.HasInputFocus = false; + break; + + case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED: + Game.HasInputFocus = true; + break; + } + + break; + } + + case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN: + { + if (pendingMotion != null) + { + inputHandler.OnMouseInput(pendingMotion.Value); + pendingMotion = null; + } + + var button = MakeButton(e.button.button); + lastButtonBits |= button; + + var pos = new int2(e.button.x, e.button.y); + + inputHandler.OnMouseInput(new MouseInput( + MouseInputEvent.Down, button, pos, mods, + MultiTapDetection.DetectFromMouse(e.button.button, pos))); + + break; + } + + case SDL.SDL_EventType.SDL_MOUSEBUTTONUP: + { + if (pendingMotion != null) + { + inputHandler.OnMouseInput(pendingMotion.Value); + pendingMotion = null; + } + + var button = MakeButton(e.button.button); + lastButtonBits &= ~button; + + var pos = new int2(e.button.x, e.button.y); + inputHandler.OnMouseInput(new MouseInput( + MouseInputEvent.Up, button, pos, mods, + MultiTapDetection.InfoFromMouse(e.button.button))); + + break; + } + + case SDL.SDL_EventType.SDL_MOUSEMOTION: + { + pendingMotion = new MouseInput( + MouseInputEvent.Move, lastButtonBits, + new int2(e.motion.x, e.motion.y), mods, 0); + + break; + } + + case SDL.SDL_EventType.SDL_MOUSEWHEEL: + { + // Retain compatibility with existing bogus behavior + // TODO: Implement real scroll behavior after we drop SDL 1.2 support + if (e.wheel.y == 0) + break; + + int x, y; + SDL.SDL_GetMouseState(out x, out y); + var button = e.wheel.y < 0 ? MouseButton.WheelDown : MouseButton.WheelUp; + inputHandler.OnMouseInput(new MouseInput(MouseInputEvent.Down, button, new int2(x, y), Modifiers.None, 0)); + + break; + } + + case SDL.SDL_EventType.SDL_TEXTINPUT: + { + string input; + unsafe + { + var data = new byte[SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE]; + var i = 0; + for (; i < SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE; i++) + { + var b = e.text.text[i]; + if (b == '\0') + break; + + data[i] = b; + } + + input = Encoding.UTF8.GetString(data, 0, i); + } + + inputHandler.OnTextInput(input); + break; + } + + case SDL.SDL_EventType.SDL_KEYDOWN: + case SDL.SDL_EventType.SDL_KEYUP: + { + var keyCode = (Keycode)e.key.keysym.sym; + var type = e.type == SDL.SDL_EventType.SDL_KEYDOWN ? + KeyInputEvent.Down : KeyInputEvent.Up; + + var tapCount = e.type == SDL.SDL_EventType.SDL_KEYDOWN ? + MultiTapDetection.DetectFromKeyboard(keyCode) : + MultiTapDetection.InfoFromKeyboard(keyCode); + + var keyEvent = new KeyInput + { + Event = type, + Key = keyCode, + Modifiers = mods, + UnicodeChar = (char)e.key.keysym.sym, + MultiTapCount = tapCount + }; + + // Special case workaround for windows users + if (e.key.keysym.sym == SDL.SDL_Keycode.SDLK_F4 && mods.HasModifier(Modifiers.Alt) && + Platform.CurrentPlatform == PlatformType.Windows) + { + OpenRA.Game.Exit(); + } + else + inputHandler.OnKeyInput(keyEvent); + + break; + } + } + } + + if (pendingMotion != null) + { + inputHandler.OnMouseInput(pendingMotion.Value); + pendingMotion = null; + } + + ErrorHandler.CheckGlError(); + } + } +} \ No newline at end of file diff --git a/OpenRA.Renderer.Sdl2/Settings.StyleCop b/OpenRA.Renderer.Sdl2/Settings.StyleCop new file mode 100644 index 0000000000..1590d17baa --- /dev/null +++ b/OpenRA.Renderer.Sdl2/Settings.StyleCop @@ -0,0 +1,344 @@ + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + \ No newline at end of file diff --git a/OpenRA.Renderer.SdlCommon/OpenRA.Renderer.SdlCommon.csproj b/OpenRA.Renderer.SdlCommon/OpenRA.Renderer.SdlCommon.csproj index a489aae220..659ddfe69a 100644 --- a/OpenRA.Renderer.SdlCommon/OpenRA.Renderer.SdlCommon.csproj +++ b/OpenRA.Renderer.SdlCommon/OpenRA.Renderer.SdlCommon.csproj @@ -54,7 +54,6 @@ - False ..\thirdparty\Tao\Tao.OpenGl.dll diff --git a/OpenRA.Renderer.SdlCommon/SdlInput.cs b/OpenRA.Renderer.SdlCommon/SdlInput.cs index 80badd2568..2e652ca31d 100644 --- a/OpenRA.Renderer.SdlCommon/SdlInput.cs +++ b/OpenRA.Renderer.SdlCommon/SdlInput.cs @@ -130,6 +130,9 @@ namespace OpenRA.Renderer.SdlCommon else inputHandler.OnKeyInput(keyEvent); + if (keyEvent.IsValidInput()) + inputHandler.OnTextInput(keyEvent.UnicodeChar.ToString()); + break; } } diff --git a/OpenRA.sln b/OpenRA.sln index 2f304547f8..2e9cbc466c 100644 --- a/OpenRA.sln +++ b/OpenRA.sln @@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoIP", "GeoIP\GeoIP.csproj EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Irc", "OpenRA.Irc\OpenRA.Irc.csproj", "{85B48234-8B31-4BE6-AF9C-665CC6866841}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Renderer.Sdl2", "OpenRA.Renderer.Sdl2\OpenRA.Renderer.Sdl2.csproj", "{33D03738-C154-4028-8EA8-63A3C488A651}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -134,6 +136,14 @@ Global {E9C01A96-C3E2-4772-825B-A740AC513D31}.Release|Any CPU.Build.0 = Release|Any CPU {E9C01A96-C3E2-4772-825B-A740AC513D31}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {E9C01A96-C3E2-4772-825B-A740AC513D31}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {33D03738-C154-4028-8EA8-63A3C488A651}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {33D03738-C154-4028-8EA8-63A3C488A651}.Debug|Any CPU.Build.0 = Debug|Any CPU + {33D03738-C154-4028-8EA8-63A3C488A651}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {33D03738-C154-4028-8EA8-63A3C488A651}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {33D03738-C154-4028-8EA8-63A3C488A651}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33D03738-C154-4028-8EA8-63A3C488A651}.Release|Any CPU.Build.0 = Release|Any CPU + {33D03738-C154-4028-8EA8-63A3C488A651}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {33D03738-C154-4028-8EA8-63A3C488A651}.Release|Mixed Platforms.Build.0 = Release|Any CPU {52FD9F0B-B209-4ED7-8A32-AC8033363263}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {52FD9F0B-B209-4ED7-8A32-AC8033363263}.Debug|Any CPU.Build.0 = Debug|Any CPU {52FD9F0B-B209-4ED7-8A32-AC8033363263}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU diff --git a/thirdparty/SDL2#.dll b/thirdparty/SDL2#.dll new file mode 100755 index 0000000000..9b74e5df23 Binary files /dev/null and b/thirdparty/SDL2#.dll differ diff --git a/thirdparty/SDL2#.dll.config b/thirdparty/SDL2#.dll.config new file mode 100644 index 0000000000..64e9166b4c --- /dev/null +++ b/thirdparty/SDL2#.dll.config @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + +