diff --git a/ANX.Framework/NonXNA/AddInSystemFactory.cs b/ANX.Framework/NonXNA/AddInSystemFactory.cs index 751a933e..504f31d8 100644 --- a/ANX.Framework/NonXNA/AddInSystemFactory.cs +++ b/ANX.Framework/NonXNA/AddInSystemFactory.cs @@ -27,6 +27,7 @@ namespace ANX.Framework.NonXNA private static AddInSystemFactory instance; private bool initialized; private Dictionary addInSystems; + private AssemblyLoader assemblyLoader; #endregion #region Public @@ -65,15 +66,15 @@ namespace ANX.Framework.NonXNA initialized = true; Logger.Info("[ANX] Initializing ANX.Framework AddInSystemFactory..."); + assemblyLoader = new AssemblyLoader(); CreateAllAddIns(); SortAddIns(); } #endregion - #region CreateAllAddIns private void CreateAllAddIns() { - foreach (Type creatorType in AssemblyLoader.CreatorTypes) + foreach (Type creatorType in assemblyLoader.CreatorTypes) { Type matchingSupportedPlatformsType = FindSupportedPlatformsTypeByNamespace(creatorType); if (matchingSupportedPlatformsType == null) @@ -89,29 +90,24 @@ namespace ANX.Framework.NonXNA Logger.Info("[ANX] skipped loading file because it is not supported or not a valid AddIn."); } } - #endregion - #region FindSupportedPlatformsTypeByNamespace private Type FindSupportedPlatformsTypeByNamespace(Type creatorType) { - foreach (Type spType in AssemblyLoader.SupportedPlatformsTypes) + foreach (Type spType in assemblyLoader.SupportedPlatformsTypes) if (spType.Namespace == creatorType.Namespace) return spType; return null; } - #endregion - #region FindSupportedPlatformsTypeByAssembly private Type FindSupportedPlatformsTypeByAssembly(Type creatorType) { - foreach (Type spType in AssemblyLoader.SupportedPlatformsTypes) + foreach (Type spType in assemblyLoader.SupportedPlatformsTypes) if (TypeHelper.GetAssemblyFrom(spType) == TypeHelper.GetAssemblyFrom(creatorType)) return spType; return null; } - #endregion #region AddCreator internal void AddCreator(ICreator creator) diff --git a/ANX.Framework/NonXNA/InputDeviceFactory.cs b/ANX.Framework/NonXNA/InputDeviceFactory.cs index 824ac4e6..e09dba57 100644 --- a/ANX.Framework/NonXNA/InputDeviceFactory.cs +++ b/ANX.Framework/NonXNA/InputDeviceFactory.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using ANX.Framework.NonXNA.InputSystem; using ANX.Framework.NonXNA.Reflection; +using System.Collections.ObjectModel; // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. @@ -37,6 +38,17 @@ namespace ANX.Framework.NonXNA get; internal set; } + + public ILookup Providers + { + get { return deviceCreators.SelectMany((x) => x.Value).Select((x) => x.Value).ToLookup((x) => x.Provider); } + } + + public string PrefferedProvider + { + get; + set; + } #endregion #region Constructor @@ -55,7 +67,7 @@ namespace ANX.Framework.NonXNA if (!deviceCreators.ContainsKey(deviceInterface)) deviceCreators.Add(deviceInterface, new Dictionary()); else if (deviceCreators[deviceInterface].ContainsKey(creatorName)) - throw new Exception("Duplicate " + deviceType.Name + " found. A " + deviceType.Name + + throw new ArgumentException("Duplicate " + deviceType.Name + " found. A " + deviceType.Name + " with the name '" + creator.Name + "' was already registered."); deviceCreators[deviceInterface].Add(creatorName, creator); @@ -66,13 +78,12 @@ namespace ANX.Framework.NonXNA #endregion #region GetDefaultTouchPanel - public ITouchPanel GetDefaultTouchPanel() + public ITouchPanel CreateDefaultTouchPanel() { - ValidateWindowHandle(); + ValidateWindowHandle("TouchPanel"); var touchPanel = GetDefaultCreator().CreateDevice(); -#if !WINDOWSMETRO touchPanel.WindowHandle = WindowHandle; -#endif + return touchPanel; } #endregion @@ -87,11 +98,10 @@ namespace ANX.Framework.NonXNA #region CreateDefaultMouse public IMouse CreateDefaultMouse() { - ValidateWindowHandle(); + ValidateWindowHandle("Mouse"); var mouse = GetDefaultCreator().CreateDevice(); -#if !WINDOWSMETRO mouse.WindowHandle = WindowHandle; -#endif + return mouse; } #endregion @@ -99,7 +109,7 @@ namespace ANX.Framework.NonXNA #region CreateDefaultKeyboard public IKeyboard CreateDefaultKeyboard() { - ValidateWindowHandle(); + ValidateWindowHandle("Keyboard"); var keyboard = GetDefaultCreator().CreateDevice(); keyboard.WindowHandle = WindowHandle; @@ -124,18 +134,24 @@ namespace ANX.Framework.NonXNA { var creators = deviceCreators[creatorType]; if (creators.Count > 0) - return (T)creators.Values.First(); + { + var creator = (T)creators.Values.FirstOrDefault((x) => x.Provider == PrefferedProvider); + if (creator != null) + return creator; + else + return (T)creators.Values.First(); + } } - throw new Exception("Unable to find a default creator for type " + creatorType); + throw new ArgumentException("Unable to find a default creator for type " + creatorType); } #endregion #region ValidateWindowHandle - private void ValidateWindowHandle() + private void ValidateWindowHandle(string deviceName) { if (!WindowHandle.IsValid) - throw new Exception("Unable to create a mouse instance because the WindowHandle was not set."); + throw new InvalidOperationException(string.Format("Unable to create a {0} instance because the WindowHandle was not set.", deviceName)); } #endregion } diff --git a/ANX.Framework/NonXNA/InputSystem/IInputDeviceCreator.cs b/ANX.Framework/NonXNA/InputSystem/IInputDeviceCreator.cs index 45b3b8b5..3005fb81 100644 --- a/ANX.Framework/NonXNA/InputSystem/IInputDeviceCreator.cs +++ b/ANX.Framework/NonXNA/InputSystem/IInputDeviceCreator.cs @@ -9,6 +9,9 @@ namespace ANX.Framework.NonXNA.InputSystem public interface IInputDeviceCreator { string Name { get; } + + string Provider { get; } + int Priority { get; } } diff --git a/ANX.Framework/NonXNA/Reflection/AssemblyLoader.cs b/ANX.Framework/NonXNA/Reflection/AssemblyLoader.cs index 78687e17..8a1786e4 100644 --- a/ANX.Framework/NonXNA/Reflection/AssemblyLoader.cs +++ b/ANX.Framework/NonXNA/Reflection/AssemblyLoader.cs @@ -7,11 +7,13 @@ using ANX.Framework.NonXNA.InputSystem; namespace ANX.Framework.NonXNA.Reflection { - internal static class AssemblyLoader + internal class AssemblyLoader { #region Constants private static readonly string[] IgnoreAssemblies = { + "ANX.Framework.dll", + "SharpDX.Direct3D11.Effects.dll", "OpenTK.dll", "OpenTK.GLControl.dll", "OpenTK.Compatibility.dll", @@ -41,49 +43,41 @@ namespace ANX.Framework.NonXNA.Reflection "Microsoft.Xna.Framework.Game.dll", "Microsoft.Xna.Framework.Content.Pipeline.dll", "OggUtils.dll", - "OggUtils.dll", }; #endregion #region Private - private static List allAssemblies = new List(); - private static bool initialized = false; - private static List creatorTypes = new List(); - private static List supportedPlatformsTypes = new List(); + private List allAssemblies = new List(); + private List creatorTypes = new List(); + private List supportedPlatformsTypes = new List(); #endregion #region Public - public static List CreatorTypes + public List CreatorTypes { get { - InitializeIfNotInitializedYet(); return creatorTypes; } } - public static List SupportedPlatformsTypes + public List SupportedPlatformsTypes { get { - InitializeIfNotInitializedYet(); return supportedPlatformsTypes; } } #endregion - private static void InitializeIfNotInitializedYet() + public AssemblyLoader() { - if (initialized) - return; - LoadAllAssemblies(); SearchForValidAddInTypes(); - initialized = true; } #region LoadAllAssemblies - private static void LoadAllAssemblies() + private void LoadAllAssemblies() { LoadAssembliesFromFile(); LoadAssembliesFromNames(); @@ -93,7 +87,7 @@ namespace ANX.Framework.NonXNA.Reflection var entryAssembly = Assembly.GetEntryAssembly(); //Entry assembly could be null if the managed code was called directly from native code without going through a Main entry point. //Which would for example happen when the tests are run via NUnit. - if (entryAssembly != null) + if (entryAssembly != null && !allAssemblies.Contains(entryAssembly)) allAssemblies.Add(entryAssembly); #else // TODO: a lot of testing is required! @@ -103,7 +97,7 @@ namespace ANX.Framework.NonXNA.Reflection #endregion #region LoadAssembliesFromFile - private static void LoadAssembliesFromFile() + private void LoadAssembliesFromFile() { #if !ANDROID && !WINDOWSMETRO string executingAssemblyFilepath = Assembly.GetExecutingAssembly().Location; @@ -118,7 +112,7 @@ namespace ANX.Framework.NonXNA.Reflection bool ignore = false; foreach (string ignoreName in IgnoreAssemblies) { - if (file.EndsWith(ignoreName, StringComparison.InvariantCultureIgnoreCase)) + if (Path.GetFileName(file).Equals(ignoreName, StringComparison.InvariantCultureIgnoreCase)) { ignore = true; break; @@ -132,7 +126,8 @@ namespace ANX.Framework.NonXNA.Reflection try { Assembly assembly = Assembly.LoadFrom(file); - allAssemblies.Add(assembly); + if (!allAssemblies.Contains(assembly)) + allAssemblies.Add(assembly); } catch { @@ -143,7 +138,7 @@ namespace ANX.Framework.NonXNA.Reflection #endregion #region LoadAssembliesFromNames - private static void LoadAssembliesFromNames() + private void LoadAssembliesFromNames() { List allAssemblyNames = new List(); @@ -158,14 +153,14 @@ namespace ANX.Framework.NonXNA.Reflection foreach (string assemblyName in allAssemblyNames) { Assembly loadedAssembly = LoadAssemblyByName(assemblyName); - if (loadedAssembly != null) + if (loadedAssembly != null && !allAssemblies.Contains(loadedAssembly)) allAssemblies.Add(loadedAssembly); } } #endregion #region LoadAssemblyByName - private static Assembly LoadAssemblyByName(string assemblyName) + private Assembly LoadAssemblyByName(string assemblyName) { try { @@ -183,7 +178,7 @@ namespace ANX.Framework.NonXNA.Reflection #endregion #region SearchForValidAddInTypes - private static void SearchForValidAddInTypes() + private void SearchForValidAddInTypes() { foreach (Assembly assembly in allAssemblies) SearchForValidAddInTypesInAssembly(assembly); @@ -191,7 +186,7 @@ namespace ANX.Framework.NonXNA.Reflection #endregion #region SearchForValidAddInTypesInAssembly - private static void SearchForValidAddInTypesInAssembly(Assembly assembly) + private void SearchForValidAddInTypesInAssembly(Assembly assembly) { var assemblyAttributes = assembly.GetCustomAttributes(); @@ -232,11 +227,8 @@ namespace ANX.Framework.NonXNA.Reflection foreach (Type type in allTypes) { - //Can happen if we have types that are incompatible with our Runtime version. - //TODO: Maybe we should instead throw an error? - //Would be a very annoying error to find for someone who uses the code. if (type == null) - continue; + throw new TypeLoadException(string.Format("Can't load a type from {0}, maybe a depdency doesn't exist in the correct version.", assembly.FullName)); bool isTypeCreatable = TypeHelper.IsAbstract(type) == false && TypeHelper.IsInterface(type) == false; if (isTypeCreatable) diff --git a/ANX.Framework/Properties/AssemblyInfo.cs b/ANX.Framework/Properties/AssemblyInfo.cs index cf4a8b6b..deb2d2e2 100644 --- a/ANX.Framework/Properties/AssemblyInfo.cs +++ b/ANX.Framework/Properties/AssemblyInfo.cs @@ -46,6 +46,7 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("ANX.InputDevices.Test")] [assembly: InternalsVisibleTo("ANX.InputDevices.Windows.Kinect")] [assembly: InternalsVisibleTo("ANX.InputDevices.Windows.XInput")] +[assembly: InternalsVisibleTo("ANX.InputDevices.OpenTK")] [assembly: InternalsVisibleTo("ANX.InputDevices.Windows.ModernUI")] [assembly: InternalsVisibleTo("ANX.PlatformSystem.Windows")] [assembly: InternalsVisibleTo("ANX.PlatformSystem.Linux")] diff --git a/InputSystems/ANX.InputDevices.OpenTK/ANX.InputDevices.OpenTK.csproj b/InputSystems/ANX.InputDevices.OpenTK/ANX.InputDevices.OpenTK.csproj index f86ead8c..56ddaeab 100644 --- a/InputSystems/ANX.InputDevices.OpenTK/ANX.InputDevices.OpenTK.csproj +++ b/InputSystems/ANX.InputDevices.OpenTK/ANX.InputDevices.OpenTK.csproj @@ -31,13 +31,14 @@ 4 - - False - ..\..\lib\OpenTK\OpenTK.dll + + ..\..\packages\OpenTK.1.1.1589.5942\lib\NET40\OpenTK.dll + True + @@ -52,6 +53,9 @@ ANX.Framework + + +