diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 3757169fc8..ad920d2da8 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -17,6 +17,7 @@ using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Net; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using OpenRA.Chat; @@ -252,16 +253,26 @@ namespace OpenRA Log.AddChannel("irc", "irc.log"); Log.AddChannel("nat", "nat.log"); - var renderers = new[] { Settings.Graphics.Renderer, "Default", null }; - foreach (var r in renderers) + var platforms = new[] { Settings.Game.Platform, "Default", null }; + foreach (var p in platforms) { - if (r == null) - throw new InvalidOperationException("No suitable renderers were found. Check graphics.log for details."); + if (p == null) + throw new InvalidOperationException("Failed to initialize platform-integration library. Check graphics.log for details."); - Settings.Graphics.Renderer = r; + Settings.Game.Platform = p; try { - Renderer = new Renderer(Settings.Graphics, Settings.Server); + var rendererPath = Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms." + p + ".dll")); + var assembly = Assembly.LoadFile(rendererPath); + + var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t)); + if (platformType == null) + throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation."); + + var platform = (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null); + Renderer = new Renderer(platform, Settings.Graphics); + Sound = new Sound(platform, Settings.Sound); + break; } catch (Exception e) @@ -281,8 +292,6 @@ namespace OpenRA Game.Settings.Server.AllowPortForward = true; } - Sound = new Sound(Settings.Sound.Engine); - GlobalChat = new GlobalChat(); Console.WriteLine("Available mods:"); diff --git a/OpenRA.Game/Graphics/IGraphicsDevice.cs b/OpenRA.Game/Graphics/IGraphicsDevice.cs index bd788c2338..06addf16b8 100644 --- a/OpenRA.Game/Graphics/IGraphicsDevice.cs +++ b/OpenRA.Game/Graphics/IGraphicsDevice.cs @@ -15,23 +15,10 @@ using OpenRA.Graphics; namespace OpenRA { - [AttributeUsage(AttributeTargets.Assembly)] - public sealed class PlatformAttribute : Attribute - { - public readonly Type Type; - - public PlatformAttribute(Type graphicsDeviceType) - { - if (!typeof(IDeviceFactory).IsAssignableFrom(graphicsDeviceType)) - throw new InvalidOperationException("Incorrect type in RendererAttribute"); - Type = graphicsDeviceType; - } - } - - public interface IDeviceFactory + public interface IPlatform { IGraphicsDevice CreateGraphics(Size size, WindowMode windowMode); - ISoundEngine CreateSound(); + ISoundEngine CreateSound(string device); } public interface IHardwareCursor : IDisposable { } diff --git a/OpenRA.Game/Renderer.cs b/OpenRA.Game/Renderer.cs index 5aab34bdc0..1adacbfd5b 100644 --- a/OpenRA.Game/Renderer.cs +++ b/OpenRA.Game/Renderer.cs @@ -12,9 +12,7 @@ using System; using System.Collections.Generic; using System.Drawing; -using System.IO; using System.Linq; -using System.Reflection; using OpenRA.Graphics; using OpenRA.Support; @@ -49,14 +47,12 @@ namespace OpenRA ITexture currentPaletteTexture; IBatchRenderer currentBatchRenderer; - public Renderer(GraphicSettings graphicSettings, ServerSettings serverSettings) + public Renderer(IPlatform platform, GraphicSettings graphicSettings) { var resolution = GetResolution(graphicSettings); - var rendererName = graphicSettings.Renderer; - var rendererPath = Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms." + rendererName + ".dll")); + Device = platform.CreateGraphics(new Size(resolution.Width, resolution.Height), graphicSettings.Mode); - Device = CreateDevice(Assembly.LoadFile(rendererPath), resolution.Width, resolution.Height, graphicSettings.Mode); TempBufferSize = graphicSettings.BatchSize; SheetSize = graphicSettings.SheetSize; @@ -79,17 +75,6 @@ namespace OpenRA return new Size(size.X, size.Y); } - static IGraphicsDevice CreateDevice(Assembly platformDll, int width, int height, WindowMode window) - { - foreach (PlatformAttribute r in platformDll.GetCustomAttributes(typeof(PlatformAttribute), false)) - { - var factory = (IDeviceFactory)r.Type.GetConstructor(Type.EmptyTypes).Invoke(null); - return factory.CreateGraphics(new Size(width, height), window); - } - - throw new InvalidOperationException("Renderer DLL is missing RendererAttribute to tell us what type to use!"); - } - public void InitializeFonts(ModData modData) { if (Fonts != null) diff --git a/OpenRA.Game/Settings.cs b/OpenRA.Game/Settings.cs index 612323c00e..4fdd3aee30 100644 --- a/OpenRA.Game/Settings.cs +++ b/OpenRA.Game/Settings.cs @@ -102,8 +102,6 @@ namespace OpenRA public class GraphicSettings { - public string Renderer = "Default"; - [Desc("This can be set to Windowed, Fullscreen or PseudoFullscreen.")] public WindowMode Mode = WindowMode.PseudoFullscreen; @@ -142,7 +140,6 @@ namespace OpenRA public bool Shuffle = false; public bool Repeat = false; - public string Engine = "Default"; public string Device = null; public bool CashTicks = true; @@ -162,6 +159,8 @@ namespace OpenRA public string Mod = "modchooser"; public string PreviousMod = "ra"; + public string Platform = "Default"; + public bool ShowShellmap = true; public bool ViewportEdgeScroll = true; diff --git a/OpenRA.Game/Sound/Sound.cs b/OpenRA.Game/Sound/Sound.cs index 4abfcee29b..4d82607cc3 100644 --- a/OpenRA.Game/Sound/Sound.cs +++ b/OpenRA.Game/Sound/Sound.cs @@ -11,8 +11,6 @@ using System; using System.IO; -using System.Linq; -using System.Reflection; using OpenRA.FileSystem; using OpenRA.GameRules; using OpenRA.Primitives; @@ -42,21 +40,9 @@ namespace OpenRA ISound video; MusicInfo currentMusic; - public Sound(string engineName) + public Sound(IPlatform platform, SoundSettings soundSettings) { - var enginePath = Platform.ResolvePath(".", "OpenRA.Platforms." + engineName + ".dll"); - soundEngine = CreateDevice(Assembly.LoadFile(enginePath)); - } - - static ISoundEngine CreateDevice(Assembly platformDll) - { - foreach (PlatformAttribute r in platformDll.GetCustomAttributes(typeof(PlatformAttribute), false)) - { - var factory = (IDeviceFactory)r.Type.GetConstructor(Type.EmptyTypes).Invoke(null); - return factory.CreateSound(); - } - - throw new InvalidOperationException("Platform DLL is missing PlatformAttribute to tell us what type to use!"); + soundEngine = platform.CreateSound(soundSettings.Device); } ISoundSource LoadSound(ISoundLoader[] loaders, IReadOnlyFileSystem fileSystem, string filename) @@ -92,12 +78,7 @@ namespace OpenRA public SoundDevice[] AvailableDevices() { - var defaultDevices = new[] - { - new SoundDevice("Null", null, "Output Disabled") - }; - - return defaultDevices.Concat(soundEngine.AvailableDevices()).ToArray(); + return soundEngine.AvailableDevices(); } public void SetListenerPosition(WPos position) diff --git a/OpenRA.Game/Sound/SoundDevice.cs b/OpenRA.Game/Sound/SoundDevice.cs index ed8a98521f..6c16aa4c47 100644 --- a/OpenRA.Game/Sound/SoundDevice.cs +++ b/OpenRA.Game/Sound/SoundDevice.cs @@ -29,13 +29,11 @@ namespace OpenRA public class SoundDevice { - public readonly string Engine; public readonly string Device; public readonly string Label; - public SoundDevice(string engine, string device, string label) + public SoundDevice(string device, string label) { - Engine = engine; Device = device; Label = label; } diff --git a/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs index a7f5c120a2..ce2fc4ca65 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs @@ -23,9 +23,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic enum PanelType { Display, Audio, Input, Advanced } static readonly string OriginalSoundDevice; - static readonly string OriginalSoundEngine; static readonly WindowMode OriginalGraphicsMode; - static readonly string OriginalGraphicsRenderer; static readonly int2 OriginalGraphicsWindowedSize; static readonly int2 OriginalGraphicsFullscreenSize; @@ -43,9 +41,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { var original = Game.Settings; OriginalSoundDevice = original.Sound.Device; - OriginalSoundEngine = original.Sound.Engine; OriginalGraphicsMode = original.Graphics.Mode; - OriginalGraphicsRenderer = original.Graphics.Renderer; OriginalGraphicsWindowedSize = original.Graphics.WindowedSize; OriginalGraphicsFullscreenSize = original.Graphics.FullscreenSize; } @@ -72,9 +68,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic Action closeAndExit = () => { Ui.CloseWindow(); onExit(); }; if (OriginalSoundDevice != current.Sound.Device || - OriginalSoundEngine != current.Sound.Engine || OriginalGraphicsMode != current.Graphics.Mode || - OriginalGraphicsRenderer != current.Graphics.Renderer || OriginalGraphicsWindowedSize != current.Graphics.WindowedSize || OriginalGraphicsFullscreenSize != current.Graphics.FullscreenSize) ConfirmationDialogs.ButtonPrompt( @@ -336,7 +330,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } var devices = Game.Sound.AvailableDevices(); - soundDevice = devices.FirstOrDefault(d => d.Engine == ss.Engine && d.Device == ss.Device) ?? devices.First(); + soundDevice = devices.FirstOrDefault(d => d.Device == ss.Device) ?? devices.First(); var audioDeviceDropdown = panel.Get("AUDIO_DEVICE"); audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, devices); @@ -349,7 +343,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic return () => { ss.Device = soundDevice.Device; - ss.Engine = soundDevice.Engine; }; } @@ -365,7 +358,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic ss.CashTicks = dss.CashTicks; ss.Mute = dss.Mute; ss.Device = dss.Device; - ss.Engine = dss.Engine; panel.Get("SOUND_VOLUME").Value = ss.SoundVolume; Game.Sound.SoundVolume = ss.SoundVolume; diff --git a/OpenRA.Platforms.Default/DefaultPlatform.cs b/OpenRA.Platforms.Default/DefaultPlatform.cs index 8b86f7c360..90eaa3e718 100644 --- a/OpenRA.Platforms.Default/DefaultPlatform.cs +++ b/OpenRA.Platforms.Default/DefaultPlatform.cs @@ -12,20 +12,18 @@ using System.Drawing; using OpenRA; -[assembly: Platform(typeof(OpenRA.Platforms.Default.DeviceFactory))] - namespace OpenRA.Platforms.Default { - public class DeviceFactory : IDeviceFactory + public class DefaultPlatform : IPlatform { public IGraphicsDevice CreateGraphics(Size size, WindowMode windowMode) { return new Sdl2GraphicsDevice(size, windowMode); } - public ISoundEngine CreateSound() + public ISoundEngine CreateSound(string device) { - return new OpenAlSoundEngine(); + return new OpenAlSoundEngine(device); } } } diff --git a/OpenRA.Platforms.Default/OpenAlSoundEngine.cs b/OpenRA.Platforms.Default/OpenAlSoundEngine.cs index 55b02f4c61..3d6f541af1 100644 --- a/OpenRA.Platforms.Default/OpenAlSoundEngine.cs +++ b/OpenRA.Platforms.Default/OpenAlSoundEngine.cs @@ -24,11 +24,10 @@ namespace OpenRA.Platforms.Default { var defaultDevices = new[] { - new SoundDevice("Default", null, "Default Output"), - new SoundDevice("Null", null, "Output Disabled") + new SoundDevice(null, "Default Output"), }; - var physicalDevices = PhysicalDevices().Select(d => new SoundDevice("Default", d, d)); + var physicalDevices = PhysicalDevices().Select(d => new SoundDevice(d, d)); return defaultDevices.Concat(physicalDevices).ToArray(); } @@ -86,16 +85,14 @@ namespace OpenRA.Platforms.Default return new string[] { }; } - public OpenAlSoundEngine() + public OpenAlSoundEngine(string deviceName) { - Console.WriteLine("Using OpenAL sound engine"); - - if (Game.Settings.Sound.Device != null) - Console.WriteLine("Using device `{0}`", Game.Settings.Sound.Device); + if (deviceName != null) + Console.WriteLine("Using sound device `{0}`", deviceName); else - Console.WriteLine("Using default device"); + Console.WriteLine("Using default sound device"); - device = ALC10.alcOpenDevice(Game.Settings.Sound.Device); + device = ALC10.alcOpenDevice(deviceName); if (device == IntPtr.Zero) { Console.WriteLine("Failed to open device. Falling back to default");