From 0873a627c2534b548ba2136d82bb7827b0bb7f21 Mon Sep 17 00:00:00 2001 From: Amin Delavar Date: Mon, 5 Aug 2019 04:54:18 +0200 Subject: [PATCH] Add input manager --- DirectX12Game/CameraController.cs | 38 ++- DirectX12Game/DirectX12Game.csproj | 2 +- DirectX12Game/TestScript.cs | 88 +++---- .../DirectX12GameEngine.Assets.csproj | 2 +- .../ContentManager.Deserializing.cs | 34 +-- .../ContentManager.cs | 4 +- .../DirectX12GameEngine.Core.Assets.csproj | 2 +- .../DirectX12GameEngine.Core.csproj | 2 +- .../DirectX12GameEngine.Editor.csproj | 1 + .../ViewModels/EntityViewModel.cs | 27 ++- .../ViewModels/ProjectLoaderViewModel.cs | 29 ++- .../Properties/PrimitivePropertyViewModels.cs | 142 ++---------- .../Properties/PropertyViewModel.cs | 1 - .../Properties/PropertyViewModelFactory.cs | 6 +- .../Properties/VectorPropertyViewModels.cs | 121 ++++++++++ .../ViewModels/PropertyGridViewModel.cs | 44 ++-- .../ViewModels/SolutionExplorerViewModel.cs | 26 +-- .../ViewModels/StorageFolderViewModel.cs | 5 +- .../Properties/PropertyMemberTemplate.xaml | 7 +- .../Properties/PropertyMemberTemplate.xaml.cs | 3 +- .../Views/PropertyGridView.xaml | 218 +++++++++++++----- .../Views/SceneView.xaml | 5 + .../Views/SolutionExplorerView.xaml.cs | 4 +- .../DirectX12GameEngine.Engine.csproj | 3 +- .../EntityComponents/ScriptComponent.cs | 5 + DirectX12GameEngine.Engine/Game.cs | 10 +- DirectX12GameEngine.Engine/GameContext.Uwp.cs | 18 +- .../GameContext.WindowsDesktop.cs | 7 +- .../GameContextWithGraphics.cs | 5 +- DirectX12GameEngine.Engine/SceneSystem.cs | 6 +- .../CoreWindowGameWindow.cs | 6 +- .../DirectX12GameEngine.Games.csproj | 2 +- DirectX12GameEngine.Games/GameContext.cs | 2 - DirectX12GameEngine.Games/GameWindow.cs | 2 +- .../WinFormsGameWindow.cs | 4 +- DirectX12GameEngine.Games/XamlGameWindow.cs | 8 +- ...tX12GameEngine.Graphics.Holographic.csproj | 2 +- .../DirectX12GameEngine.Graphics.csproj | 2 +- DirectX12GameEngine.Input/BatteryReport.cs | 15 ++ DirectX12GameEngine.Input/BatteryStatus.cs | 10 + .../CoreWindowInputSourceConfiguration.cs | 22 ++ .../CoreWindowKeyboardInputSource.cs | 47 ++++ .../CoreWindowPointerInputSource.cs | 107 +++++++++ DirectX12GameEngine.Input/Cursor.cs | 15 ++ DirectX12GameEngine.Input/CursorType.cs | 22 ++ .../DirectX12GameEngine.Input.csproj | 15 ++ DirectX12GameEngine.Input/GamepadButtons.cs | 28 +++ .../GamepadDeviceBase.cs | 43 ++++ .../GamepadInputSourceBase.cs | 26 +++ DirectX12GameEngine.Input/GamepadReading.cs | 17 ++ DirectX12GameEngine.Input/GamepadVibration.cs | 14 ++ DirectX12GameEngine.Input/IGamepadDevice.cs | 23 ++ .../IGamepadInputSource.cs | 9 + DirectX12GameEngine.Input/IInputSource.cs | 11 + .../IInputSourceConfiguration.cs | 9 + .../IKeyboardInputSource.cs | 18 ++ .../IPointerInputSource.cs | 34 +++ DirectX12GameEngine.Input/InputManager.cs | 132 +++++++++++ DirectX12GameEngine.Input/KeyEventArgs.cs | 11 + .../KeyboardInputSourceBase.cs | 71 ++++++ DirectX12GameEngine.Input/PointerEventArgs.cs | 16 ++ .../PointerInputSourceBase.cs | 81 +++++++ DirectX12GameEngine.Input/PointerPoint.cs | 15 ++ .../PointerPointProperties.cs | 56 +++++ .../PointerUpdateKind.cs | 17 ++ DirectX12GameEngine.Input/Uwp/UwpGamepad.cs | 103 +++++++++ .../Uwp/UwpGamepadInputSource.cs | 55 +++++ .../Uwp/UwpPointerPoint.cs | 22 ++ .../Uwp/UwpPointerPointProperties.cs | 63 +++++ DirectX12GameEngine.Input/VirtualKey.cs | 176 ++++++++++++++ .../VirtualKeyModifiers.cs | 14 ++ .../WinFormsInputSourceConfiguration.cs | 21 ++ .../WinForms/WinFormsKeyboardInputSource.cs | 49 ++++ .../Xaml/XamlInputSourceConfiguration.cs | 22 ++ .../Xaml/XamlKeyboardInputSource.cs | 48 ++++ .../Xaml/XamlPointerInputSource.cs | 104 +++++++++ .../DirectX12GameEngine.Rendering.csproj | 2 +- .../DirectX12GameEngine.Shaders.csproj | 2 +- DirectX12GameEngine.sln | 22 ++ .../DirectX12WinFormsApp.csproj | 2 +- 80 files changed, 2093 insertions(+), 389 deletions(-) create mode 100644 DirectX12GameEngine.Editor/ViewModels/Properties/VectorPropertyViewModels.cs create mode 100644 DirectX12GameEngine.Input/BatteryReport.cs create mode 100644 DirectX12GameEngine.Input/BatteryStatus.cs create mode 100644 DirectX12GameEngine.Input/CoreWindow/CoreWindowInputSourceConfiguration.cs create mode 100644 DirectX12GameEngine.Input/CoreWindow/CoreWindowKeyboardInputSource.cs create mode 100644 DirectX12GameEngine.Input/CoreWindow/CoreWindowPointerInputSource.cs create mode 100644 DirectX12GameEngine.Input/Cursor.cs create mode 100644 DirectX12GameEngine.Input/CursorType.cs create mode 100644 DirectX12GameEngine.Input/DirectX12GameEngine.Input.csproj create mode 100644 DirectX12GameEngine.Input/GamepadButtons.cs create mode 100644 DirectX12GameEngine.Input/GamepadDeviceBase.cs create mode 100644 DirectX12GameEngine.Input/GamepadInputSourceBase.cs create mode 100644 DirectX12GameEngine.Input/GamepadReading.cs create mode 100644 DirectX12GameEngine.Input/GamepadVibration.cs create mode 100644 DirectX12GameEngine.Input/IGamepadDevice.cs create mode 100644 DirectX12GameEngine.Input/IGamepadInputSource.cs create mode 100644 DirectX12GameEngine.Input/IInputSource.cs create mode 100644 DirectX12GameEngine.Input/IInputSourceConfiguration.cs create mode 100644 DirectX12GameEngine.Input/IKeyboardInputSource.cs create mode 100644 DirectX12GameEngine.Input/IPointerInputSource.cs create mode 100644 DirectX12GameEngine.Input/InputManager.cs create mode 100644 DirectX12GameEngine.Input/KeyEventArgs.cs create mode 100644 DirectX12GameEngine.Input/KeyboardInputSourceBase.cs create mode 100644 DirectX12GameEngine.Input/PointerEventArgs.cs create mode 100644 DirectX12GameEngine.Input/PointerInputSourceBase.cs create mode 100644 DirectX12GameEngine.Input/PointerPoint.cs create mode 100644 DirectX12GameEngine.Input/PointerPointProperties.cs create mode 100644 DirectX12GameEngine.Input/PointerUpdateKind.cs create mode 100644 DirectX12GameEngine.Input/Uwp/UwpGamepad.cs create mode 100644 DirectX12GameEngine.Input/Uwp/UwpGamepadInputSource.cs create mode 100644 DirectX12GameEngine.Input/Uwp/UwpPointerPoint.cs create mode 100644 DirectX12GameEngine.Input/Uwp/UwpPointerPointProperties.cs create mode 100644 DirectX12GameEngine.Input/VirtualKey.cs create mode 100644 DirectX12GameEngine.Input/VirtualKeyModifiers.cs create mode 100644 DirectX12GameEngine.Input/WinForms/WinFormsInputSourceConfiguration.cs create mode 100644 DirectX12GameEngine.Input/WinForms/WinFormsKeyboardInputSource.cs create mode 100644 DirectX12GameEngine.Input/Xaml/XamlInputSourceConfiguration.cs create mode 100644 DirectX12GameEngine.Input/Xaml/XamlKeyboardInputSource.cs create mode 100644 DirectX12GameEngine.Input/Xaml/XamlPointerInputSource.cs diff --git a/DirectX12Game/CameraController.cs b/DirectX12Game/CameraController.cs index 5951da0..b42ee32 100644 --- a/DirectX12Game/CameraController.cs +++ b/DirectX12Game/CameraController.cs @@ -1,7 +1,7 @@ using System; using System.Numerics; using DirectX12GameEngine.Engine; -using DirectX12GameEngine.Games; +using DirectX12GameEngine.Input; namespace DirectX12Game { @@ -15,26 +15,16 @@ public override void Start() { SceneSystem.CurrentCamera = Camera; -#if WINDOWS_UWP - if (Game.Context is CoreWindowGameContext context) + if (Input.Keyboard != null) { - context.Control.PointerPressed += (s, e) => OnPointerPressed(e.CurrentPoint); - context.Control.PointerWheelChanged += (s, e) => OnPointerWheelChanged(e.CurrentPoint); - context.Control.KeyDown += (s, e) => OnKeyDown(e.VirtualKey); + Input.Keyboard.KeyDown += (s, e) => OnKeyDown(e.Key); } - else if (Game.Context is XamlGameContext xamlContext) - { - xamlContext.Control.PointerPressed += (s, e) => OnPointerPressed(e.GetCurrentPoint(xamlContext.Control)); - xamlContext.Control.PointerWheelChanged += (s, e) => OnPointerWheelChanged(e.GetCurrentPoint(xamlContext.Control)); - xamlContext.Control.KeyDown += (s, e) => OnKeyDown(e.Key); - } -#endif -#if NETCOREAPP - if (Game.Context is WinFormsGameContext winFormsContext) + + if (Input.Pointer != null) { - winFormsContext.Control.KeyDown += (s, e) => OnKeyDown((Windows.System.VirtualKey)e.KeyCode); + Input.Pointer.PointerPressed += (s, e) => OnPointerPressed(e.CurrentPoint); + Input.Pointer.PointerWheelChanged += (s, e) => OnPointerWheelChanged(e.CurrentPoint); } -#endif } public override void Update() @@ -51,7 +41,7 @@ private void MoveCamera(float value) } } - private void OnPointerPressed(Windows.UI.Input.PointerPoint pointerPoint) + private void OnPointerPressed(PointerPoint pointerPoint) { if (pointerPoint.Properties.IsLeftButtonPressed) { @@ -63,25 +53,25 @@ private void OnPointerPressed(Windows.UI.Input.PointerPoint pointerPoint) } } - private void OnPointerWheelChanged(Windows.UI.Input.PointerPoint pointerPoint) + private void OnPointerWheelChanged(PointerPoint pointerPoint) { MoveCamera(-pointerPoint.Properties.MouseWheelDelta * scrollSpeed); } - private void OnKeyDown(Windows.System.VirtualKey key) + private void OnKeyDown(VirtualKey key) { switch (key) { - case Windows.System.VirtualKey.Left: + case VirtualKey.Left: if (Camera?.Entity != null) Camera.Entity.Transform.Rotation *= Quaternion.CreateFromAxisAngle(Vector3.UnitY, (float)(10 * Math.PI / 180.0f)); break; - case Windows.System.VirtualKey.Right: + case VirtualKey.Right: if (Camera?.Entity != null) Camera.Entity.Transform.Rotation *= Quaternion.CreateFromAxisAngle(Vector3.UnitY, (float)(-10 * Math.PI / 180.0f)); break; - case Windows.System.VirtualKey.Up: + case VirtualKey.Up: MoveCamera(-10.0f); break; - case Windows.System.VirtualKey.Down: + case VirtualKey.Down: MoveCamera(10.0f); break; } diff --git a/DirectX12Game/DirectX12Game.csproj b/DirectX12Game/DirectX12Game.csproj index 3de6095..87de8fa 100644 --- a/DirectX12Game/DirectX12Game.csproj +++ b/DirectX12Game/DirectX12Game.csproj @@ -3,7 +3,7 @@ netstandard2.0;netcoreapp3.0 8.0 - enable + enable true WINDOWS_UWP diff --git a/DirectX12Game/TestScript.cs b/DirectX12Game/TestScript.cs index 5df203a..ead7bb8 100644 --- a/DirectX12Game/TestScript.cs +++ b/DirectX12Game/TestScript.cs @@ -8,93 +8,61 @@ using DirectX12GameEngine.Rendering; using DirectX12GameEngine.Rendering.Materials; using Microsoft.Extensions.DependencyInjection; +using DirectX12GameEngine.Input; + +#nullable enable namespace DirectX12Game { public class TestScript : StartupScript { - public string NullProperty { get; set; } + public string? NullProperty { get; set; } public ColorChannel MyColorChannel { get; set; } = ColorChannel.G; public ColorChannel MyOtherColorChannel { get; set; } = ColorChannel.B; + public DateTimeOffset? MyDateTime { get; set; } + public List MyStringList { get; } = new List { "One", "Two", "Three", "Four" }; public List MyVectorList { get; } = new List { new Vector3(4, 3, 2), new Vector3(34, 2, 9) }; public override void Start() { -#if WINDOWS_UWP - if (Game.Context is CoreWindowGameContext context) - { - context.Control.KeyDown += Control_KeyDown; - } - else if (Game.Context is XamlGameContext xamlContext) - { - xamlContext.Control.KeyDown += Control_KeyDown1; - } -#endif -#if NETCOREAPP - if (Game.Context is WinFormsGameContext winFormsContext) + if (Input.Keyboard != null) { - winFormsContext.Control.KeyDown += Control_KeyDown2; + Input.Keyboard.KeyDown += Keyboard_KeyDown; } -#endif } -#if WINDOWS_UWP - private void Control_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args) + public override void Cancel() { - OnKeyDown(args.VirtualKey); + if (Input.Keyboard != null) + { + Input.Keyboard.KeyDown -= Keyboard_KeyDown; + } } - private void Control_KeyDown1(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e) + private void Keyboard_KeyDown(object sender, KeyEventArgs e) { OnKeyDown(e.Key); } -#endif -#if NETCOREAPP - private void Control_KeyDown2(object sender, System.Windows.Forms.KeyEventArgs e) - { - OnKeyDown((Windows.System.VirtualKey)e.KeyCode); - } -#endif - - public override void Cancel() - { -#if WINDOWS_UWP - if (Game.Context is CoreWindowGameContext context) - { - context.Control.KeyDown -= Control_KeyDown; - } - else if (Game.Context is XamlGameContext xamlContext) - { - xamlContext.Control.KeyDown -= Control_KeyDown1; - } -#endif -#if NETCOREAPP - if (Game.Context is WinFormsGameContext winFormsContext) - { - winFormsContext.Control.KeyDown -= Control_KeyDown2; - } -#endif - } - private async void OnKeyDown(Windows.System.VirtualKey key) + private async void OnKeyDown(VirtualKey key) { Entity? cameraEntity = SceneSystem.CurrentCamera?.Entity; Entity scene = SceneSystem.SceneInstance?.RootEntity ?? throw new InvalidOperationException(); switch (key) { - case Windows.System.VirtualKey.Number0 when GraphicsDevice?.Presenter != null: + case VirtualKey.Number0 when GraphicsDevice?.Presenter != null: GraphicsDevice.Presenter.PresentationParameters.SyncInterval = 0; break; - case Windows.System.VirtualKey.Number1 when GraphicsDevice?.Presenter != null: + case VirtualKey.Number1 when GraphicsDevice?.Presenter != null: GraphicsDevice.Presenter.PresentationParameters.SyncInterval = 1; break; - case Windows.System.VirtualKey.D: + case VirtualKey.D: Entity? customCliffhouse = Entity?.EntityManager?.FirstOrDefault(m => m.Name == "CustomCliffhouse"); if (customCliffhouse != null) { @@ -107,18 +75,18 @@ private async void OnKeyDown(Windows.System.VirtualKey key) } } break; - case Windows.System.VirtualKey.R: + case VirtualKey.R: Entity? cliffhouse = SceneSystem.SceneInstance?.RootEntity?.Children.FirstOrDefault(m => m.Name == "Cliffhouse"); if (cliffhouse != null) { SceneSystem.SceneInstance?.RootEntity?.Children.Remove(cliffhouse); } break; - case Windows.System.VirtualKey.T: + case VirtualKey.T: Entity? cliffhouse1 = SceneSystem.SceneInstance?.RootEntity?.Children.FirstOrDefault(m => m.Name == "Cliffhouse"); cliffhouse1?.Remove(); break; - case Windows.System.VirtualKey.A: + case VirtualKey.A: Entity newCliffhouse = new Entity("Cliffhouse") { new TransformComponent { Position = new Vector3(-200.0f, 120.0f, 500.0f) }, @@ -127,7 +95,7 @@ private async void OnKeyDown(Windows.System.VirtualKey key) SceneSystem.SceneInstance?.RootEntity?.Children.Add(newCliffhouse); break; - case Windows.System.VirtualKey.P: + case VirtualKey.P: Entity? child1 = Entity?.EntityManager?.FirstOrDefault(m => m.Name == "Child1"); if (child1 != null && child1.Parent is null) { @@ -135,7 +103,7 @@ private async void OnKeyDown(Windows.System.VirtualKey key) SceneSystem.SceneInstance?.RootEntity?.Children.Add(child1); } break; - case Windows.System.VirtualKey.Q: + case VirtualKey.Q: Entity? child2 = Entity?.EntityManager?.FirstOrDefault(m => m.Name == "Child1"); if (child2 != null && child2.Parent != null) { @@ -143,7 +111,7 @@ private async void OnKeyDown(Windows.System.VirtualKey key) child2.Transform.Parent = Entity?.EntityManager?.FirstOrDefault(m => m.Name == "Parent1").Transform; } break; - case Windows.System.VirtualKey.S: + case VirtualKey.S: SceneInstance? sceneInstance = SceneSystem.SceneInstance; Entity? previousRootScene = sceneInstance?.RootEntity; @@ -156,14 +124,14 @@ private async void OnKeyDown(Windows.System.VirtualKey key) sceneInstance.RootEntity.Children.Add(previousRootScene); } break; - case Windows.System.VirtualKey.O: + case VirtualKey.O: Entity? entity = Entity?.EntityManager?.FirstOrDefault(m => m.Name == "CustomCliffhouse"); if (entity != null) { await Content.SaveAsync(@"Assets\CustomCliffhouse", entity); } break; - case Windows.System.VirtualKey.I: + case VirtualKey.I: { if (scene != null) { @@ -180,10 +148,10 @@ private async void OnKeyDown(Windows.System.VirtualKey key) } } break; - case Windows.System.VirtualKey.G: + case VirtualKey.G: GC.Collect(); break; - case Windows.System.VirtualKey.K: + case VirtualKey.K: await Content.ReloadAsync(scene); break; } diff --git a/DirectX12GameEngine.Assets/DirectX12GameEngine.Assets.csproj b/DirectX12GameEngine.Assets/DirectX12GameEngine.Assets.csproj index a5ecfba..ac14401 100644 --- a/DirectX12GameEngine.Assets/DirectX12GameEngine.Assets.csproj +++ b/DirectX12GameEngine.Assets/DirectX12GameEngine.Assets.csproj @@ -3,7 +3,7 @@ netstandard2.0 8.0 - enable + enable true diff --git a/DirectX12GameEngine.Core.Assets/ContentManager.Deserializing.cs b/DirectX12GameEngine.Core.Assets/ContentManager.Deserializing.cs index 8d61866..dcab316 100644 --- a/DirectX12GameEngine.Core.Assets/ContentManager.Deserializing.cs +++ b/DirectX12GameEngine.Core.Assets/ContentManager.Deserializing.cs @@ -44,38 +44,26 @@ public Task DeserializeAsync(XElement element, object? obj = null) return DeserializeAsync(element, operation, obj); } - internal async Task DeserializeAsync(string initialPath, string newPath, Type type, object? obj) + internal async Task DeserializeExistingObjectAsync(string initialPath, string newPath, object obj) { - Reference? reference = null; + Type type = obj.GetType(); - if (obj != null) - { - reference = FindDeserializedObject(initialPath, type); - - if (reference is null || reference.Object != obj) - { - throw new InvalidOperationException(); - } - } + Reference reference = FindDeserializedObject(initialPath, type); - HashSet? references = null; - - if (reference != null) + if (reference is null || reference.Object != obj) { - references = reference.References; - reference.References = new HashSet(); - - reference.IsDeserialized = false; + throw new InvalidOperationException(); } + HashSet? references = reference.References; + reference.References = new HashSet(); + reference.IsDeserialized = false; + object asset = await DeserializeAsync(newPath, type, null, obj); - if (references != null) + foreach (Reference childReference in references) { - foreach (Reference childReference in references) - { - DecrementReference(childReference, false); - } + DecrementReference(childReference, false); } return asset; diff --git a/DirectX12GameEngine.Core.Assets/ContentManager.cs b/DirectX12GameEngine.Core.Assets/ContentManager.cs index 44688d0..4364c29 100644 --- a/DirectX12GameEngine.Core.Assets/ContentManager.cs +++ b/DirectX12GameEngine.Core.Assets/ContentManager.cs @@ -98,7 +98,7 @@ public async Task LoadAsync(Type type, string path) { using (await asyncLock.LockAsync()) { - return await DeserializeAsync(path, path, type, null); + return await DeserializeAsync(path, type, null, null); } } @@ -113,7 +113,7 @@ public async Task ReloadAsync(object asset, string? newPath = null) string path = newPath ?? reference.Path; - await DeserializeAsync(reference.Path, path, asset.GetType(), asset); + await DeserializeExistingObjectAsync(reference.Path, path, asset); if (path != reference.Path) { diff --git a/DirectX12GameEngine.Core.Assets/DirectX12GameEngine.Core.Assets.csproj b/DirectX12GameEngine.Core.Assets/DirectX12GameEngine.Core.Assets.csproj index a171816..8c486ff 100644 --- a/DirectX12GameEngine.Core.Assets/DirectX12GameEngine.Core.Assets.csproj +++ b/DirectX12GameEngine.Core.Assets/DirectX12GameEngine.Core.Assets.csproj @@ -3,7 +3,7 @@ netstandard2.0 8.0 - enable + enable WINDOWS_UWP diff --git a/DirectX12GameEngine.Core/DirectX12GameEngine.Core.csproj b/DirectX12GameEngine.Core/DirectX12GameEngine.Core.csproj index 3b57459..faf53a1 100644 --- a/DirectX12GameEngine.Core/DirectX12GameEngine.Core.csproj +++ b/DirectX12GameEngine.Core/DirectX12GameEngine.Core.csproj @@ -3,7 +3,7 @@ netstandard2.0 8.0 - enable + enable true diff --git a/DirectX12GameEngine.Editor/DirectX12GameEngine.Editor.csproj b/DirectX12GameEngine.Editor/DirectX12GameEngine.Editor.csproj index 1222128..02798e5 100644 --- a/DirectX12GameEngine.Editor/DirectX12GameEngine.Editor.csproj +++ b/DirectX12GameEngine.Editor/DirectX12GameEngine.Editor.csproj @@ -135,6 +135,7 @@ + diff --git a/DirectX12GameEngine.Editor/ViewModels/EntityViewModel.cs b/DirectX12GameEngine.Editor/ViewModels/EntityViewModel.cs index 19c6f18..25017ab 100644 --- a/DirectX12GameEngine.Editor/ViewModels/EntityViewModel.cs +++ b/DirectX12GameEngine.Editor/ViewModels/EntityViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Specialized; +using System.ComponentModel; using DirectX12GameEngine.Engine; #nullable enable @@ -22,6 +23,7 @@ public EntityViewModel(Entity model) : base(model) } Children.CollectionChanged += Children_CollectionChanged; + Model.PropertyChanged += Model_PropertyChanged; } public EntityViewModel? Parent @@ -36,18 +38,18 @@ public bool IsSelected set => Set(ref isSelected, value); } - public string Name - { - get => Model.Name; - set => Set(Model.Name, value, () => Model.Name = value); - } - public Guid Id { get => Model.Id; set => Set(Model.Id, value, () => Model.Id = value); } + public string Name + { + get => Model.Name; + set => Set(Model.Name, value, () => Model.Name = value); + } + public ObservableViewModelCollection Children { get; } public ObservableViewModelCollection Components { get; } @@ -90,5 +92,18 @@ private void Children_CollectionChanged(object sender, NotifyCollectionChangedEv break; } } + + private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) + { + case nameof(Id): + NotifyPropertyChanged(nameof(Id)); + break; + case nameof(Name): + NotifyPropertyChanged(nameof(Name)); + break; + } + } } } diff --git a/DirectX12GameEngine.Editor/ViewModels/ProjectLoaderViewModel.cs b/DirectX12GameEngine.Editor/ViewModels/ProjectLoaderViewModel.cs index 1dc6939..0bf49c8 100644 --- a/DirectX12GameEngine.Editor/ViewModels/ProjectLoaderViewModel.cs +++ b/DirectX12GameEngine.Editor/ViewModels/ProjectLoaderViewModel.cs @@ -11,6 +11,7 @@ using Windows.Storage; using Windows.Storage.AccessCache; using Windows.Storage.Pickers; +using Windows.UI.StartScreen; #nullable enable @@ -64,16 +65,40 @@ public async Task OpenRecentProjectAsync(string token) public async Task OpenProjectAsync(StorageFolder folder) { + string token; + if (!StorageApplicationPermissions.MostRecentlyUsedList.CheckAccess(folder)) { - string token = StorageApplicationPermissions.MostRecentlyUsedList.Add(folder, folder.Path); + token = StorageApplicationPermissions.MostRecentlyUsedList.Add(folder, folder.Path); AccessListEntry accessListEntry = new AccessListEntry { Token = token, Metadata = folder.Path }; RecentProjects.Add(accessListEntry); } + else + { + token = RecentProjects.First(e => e.Metadata == folder.Path).Token; + } + + if (JumpList.IsSupported()) + { + JumpList jumpList = await JumpList.LoadCurrentAsync(); + jumpList.SystemGroupKind = JumpListSystemGroupKind.Recent; + + JumpListItem? existingJumpListItem = jumpList.Items.FirstOrDefault(j => j.Arguments == token); + + if (existingJumpListItem is null || existingJumpListItem.RemovedByUser) + { + JumpListItem jumpListItem = JumpListItem.CreateWithArguments(token, folder.Name); + jumpListItem.Description = folder.Path; + jumpListItem.GroupName = "Recent"; + + jumpList.Items.Add(jumpListItem); + } + + await jumpList.SaveAsync(); + } if (IsProjectLoaded) { - string token = RecentProjects.First(e => e.Metadata == folder.Path).Token; await CoreApplication.RequestRestartAsync(token); } else diff --git a/DirectX12GameEngine.Editor/ViewModels/Properties/PrimitivePropertyViewModels.cs b/DirectX12GameEngine.Editor/ViewModels/Properties/PrimitivePropertyViewModels.cs index be8d567..6c8a29d 100644 --- a/DirectX12GameEngine.Editor/ViewModels/Properties/PrimitivePropertyViewModels.cs +++ b/DirectX12GameEngine.Editor/ViewModels/Properties/PrimitivePropertyViewModels.cs @@ -1,7 +1,7 @@ using System; -using System.Numerics; using System.Reflection; -using System.Runtime.CompilerServices; + +#nullable enable namespace DirectX12GameEngine.Editor.ViewModels.Properties { @@ -12,25 +12,6 @@ public NullPropertyViewModel(object model, PropertyInfo propertyInfo) : base(mod } } - public class EnumPropertyViewModel : PropertyViewModel - { - public EnumPropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) - { - Values = Enum.GetValues(Value.GetType()); - } - - public Array Values { get; } - - protected override void NotifyPropertyChanged([CallerMemberName] string? propertyName = null) - { - base.NotifyPropertyChanged(propertyName); - - if (propertyName == nameof(Value)) - { - } - } - } - public class CharPropertyViewModel : PropertyViewModel { public CharPropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) @@ -52,23 +33,23 @@ public BooleanPropertyViewModel(object model, PropertyInfo propertyInfo) : base( } } - public class DecimalPropertyViewModel : PropertyViewModel + public class SinglePropertyViewModel : PropertyViewModel { - public DecimalPropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) + public SinglePropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) { } } - public class SinglePropertyViewModel : PropertyViewModel + public class DoublePropertyViewModel : PropertyViewModel { - public SinglePropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) + public DoublePropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) { } } - public class DoublePropertyViewModel : PropertyViewModel + public class DecimalPropertyViewModel : PropertyViewModel { - public DoublePropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) + public DecimalPropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) { } } @@ -129,119 +110,28 @@ public UInt64PropertyViewModel(object model, PropertyInfo propertyInfo) : base(m } } - public class Vector3PropertyViewModel : PropertyViewModel + public class EnumPropertyViewModel : PropertyViewModel { - public Vector3PropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) - { - } - - public float X - { - get => Value.X; - set => Set(X, value, () => Value = new Vector3(value, Y, Z)); - } + private Array? values; - public float Y - { - get => Value.Y; - set => Set(Y, value, () => Value = new Vector3(X, value, Z)); - } - - public float Z + public EnumPropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) { - get => Value.Z; - set => Set(Z, value, () => Value = new Vector3(X, Y, value)); } - protected override void OnOwnerPropertyChanged() - { - base.OnOwnerPropertyChanged(); - - NotifyPropertyChanged(nameof(X)); - NotifyPropertyChanged(nameof(Y)); - NotifyPropertyChanged(nameof(Z)); - } + public Array Values => values ?? (values = Enum.GetValues(Type)); } - public class Vector4PropertyViewModel : PropertyViewModel + public class GuidPropertyViewModel : PropertyViewModel { - public Vector4PropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) - { - } - - public float X - { - get => Value.X; - set => Set(X, value, () => Value = new Vector4(value, Y, Z, W)); - } - - public float Y + public GuidPropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) { - get => Value.Y; - set => Set(Y, value, () => Value = new Vector4(X, value, Z, W)); - } - - public float Z - { - get => Value.Z; - set => Set(Z, value, () => Value = new Vector4(X, Y, value, W)); - } - - public float W - { - get => Value.W; - set => Set(W, value, () => Value = new Vector4(X, Y, Z, value)); - } - - protected override void OnOwnerPropertyChanged() - { - base.OnOwnerPropertyChanged(); - - NotifyPropertyChanged(nameof(X)); - NotifyPropertyChanged(nameof(Y)); - NotifyPropertyChanged(nameof(Z)); - NotifyPropertyChanged(nameof(W)); } } - public class QuaternionPropertyViewModel : PropertyViewModel + public class DateTimePropertyViewModel : PropertyViewModel { - public QuaternionPropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) + public DateTimePropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) { } - - public float X - { - get => Value.X; - set => Set(X, value, () => Value = new Quaternion(value, Y, Z, W)); - } - - public float Y - { - get => Value.Y; - set => Set(Y, value, () => Value = new Quaternion(X, value, Z, W)); - } - - public float Z - { - get => Value.Z; - set => Set(Z, value, () => Value = new Quaternion(X, Y, value, W)); - } - - public float W - { - get => Value.W; - set => Set(W, value, () => Value = new Quaternion(X, Y, Z, value)); - } - - protected override void OnOwnerPropertyChanged() - { - base.OnOwnerPropertyChanged(); - - NotifyPropertyChanged(nameof(X)); - NotifyPropertyChanged(nameof(Y)); - NotifyPropertyChanged(nameof(Z)); - NotifyPropertyChanged(nameof(W)); - } } } diff --git a/DirectX12GameEngine.Editor/ViewModels/Properties/PropertyViewModel.cs b/DirectX12GameEngine.Editor/ViewModels/Properties/PropertyViewModel.cs index bd381af..30cb256 100644 --- a/DirectX12GameEngine.Editor/ViewModels/Properties/PropertyViewModel.cs +++ b/DirectX12GameEngine.Editor/ViewModels/Properties/PropertyViewModel.cs @@ -2,7 +2,6 @@ using System.Collections; using System.Collections.ObjectModel; using System.ComponentModel; -using System.Linq; using System.Reflection; using DirectX12GameEngine.Core.Assets; diff --git a/DirectX12GameEngine.Editor/ViewModels/Properties/PropertyViewModelFactory.cs b/DirectX12GameEngine.Editor/ViewModels/Properties/PropertyViewModelFactory.cs index 21ecff9..ad470f3 100644 --- a/DirectX12GameEngine.Editor/ViewModels/Properties/PropertyViewModelFactory.cs +++ b/DirectX12GameEngine.Editor/ViewModels/Properties/PropertyViewModelFactory.cs @@ -8,7 +8,7 @@ namespace DirectX12GameEngine.Editor.ViewModels.Properties { - public class PropertyViewModelFactory : IPropertyViewModelFactory + public class PropertyViewModelFactory : IPropertyViewModelFactory, IEnumerable> { private static PropertyViewModelFactory defaultInstance; @@ -76,6 +76,10 @@ public PropertyViewModel Create(object model, PropertyInfo propertyInfo, object? return propertyViewModel; } + + public IEnumerator> GetEnumerator() => factories.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } public class FunctionalPropertyViewModelFactory : IPropertyViewModelFactory diff --git a/DirectX12GameEngine.Editor/ViewModels/Properties/VectorPropertyViewModels.cs b/DirectX12GameEngine.Editor/ViewModels/Properties/VectorPropertyViewModels.cs new file mode 100644 index 0000000..f5dcc48 --- /dev/null +++ b/DirectX12GameEngine.Editor/ViewModels/Properties/VectorPropertyViewModels.cs @@ -0,0 +1,121 @@ +using System.Numerics; +using System.Reflection; + +namespace DirectX12GameEngine.Editor.ViewModels.Properties +{ + public class Vector3PropertyViewModel : PropertyViewModel + { + public Vector3PropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) + { + } + + public float X + { + get => Value.X; + set => Set(X, value, () => Value = new Vector3(value, Y, Z)); + } + + public float Y + { + get => Value.Y; + set => Set(Y, value, () => Value = new Vector3(X, value, Z)); + } + + public float Z + { + get => Value.Z; + set => Set(Z, value, () => Value = new Vector3(X, Y, value)); + } + + protected override void OnOwnerPropertyChanged() + { + base.OnOwnerPropertyChanged(); + + NotifyPropertyChanged(nameof(X)); + NotifyPropertyChanged(nameof(Y)); + NotifyPropertyChanged(nameof(Z)); + } + } + + public class Vector4PropertyViewModel : PropertyViewModel + { + public Vector4PropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) + { + } + + public float X + { + get => Value.X; + set => Set(X, value, () => Value = new Vector4(value, Y, Z, W)); + } + + public float Y + { + get => Value.Y; + set => Set(Y, value, () => Value = new Vector4(X, value, Z, W)); + } + + public float Z + { + get => Value.Z; + set => Set(Z, value, () => Value = new Vector4(X, Y, value, W)); + } + + public float W + { + get => Value.W; + set => Set(W, value, () => Value = new Vector4(X, Y, Z, value)); + } + + protected override void OnOwnerPropertyChanged() + { + base.OnOwnerPropertyChanged(); + + NotifyPropertyChanged(nameof(X)); + NotifyPropertyChanged(nameof(Y)); + NotifyPropertyChanged(nameof(Z)); + NotifyPropertyChanged(nameof(W)); + } + } + + public class QuaternionPropertyViewModel : PropertyViewModel + { + public QuaternionPropertyViewModel(object model, PropertyInfo propertyInfo) : base(model, propertyInfo) + { + } + + public float X + { + get => Value.X; + set => Set(X, value, () => Value = new Quaternion(value, Y, Z, W)); + } + + public float Y + { + get => Value.Y; + set => Set(Y, value, () => Value = new Quaternion(X, value, Z, W)); + } + + public float Z + { + get => Value.Z; + set => Set(Z, value, () => Value = new Quaternion(X, Y, value, W)); + } + + public float W + { + get => Value.W; + set => Set(W, value, () => Value = new Quaternion(X, Y, Z, value)); + } + + protected override void OnOwnerPropertyChanged() + { + base.OnOwnerPropertyChanged(); + + NotifyPropertyChanged(nameof(X)); + NotifyPropertyChanged(nameof(Y)); + NotifyPropertyChanged(nameof(Z)); + NotifyPropertyChanged(nameof(W)); + } + } +} diff --git a/DirectX12GameEngine.Editor/ViewModels/PropertyGridViewModel.cs b/DirectX12GameEngine.Editor/ViewModels/PropertyGridViewModel.cs index b133672..d16528a 100644 --- a/DirectX12GameEngine.Editor/ViewModels/PropertyGridViewModel.cs +++ b/DirectX12GameEngine.Editor/ViewModels/PropertyGridViewModel.cs @@ -18,24 +18,32 @@ public class PropertyGridViewModel : ViewModelBase public PropertyGridViewModel() { - PropertyViewModelFactory.Default.Add(typeof(Enum), (m, p) => new EnumPropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(byte), (m, p) => new BytePropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(sbyte), (m, p) => new SBytePropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(short), (m, p) => new Int16PropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(ushort), (m, p) => new UInt16PropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(int), (m, p) => new Int32PropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(uint), (m, p) => new UInt32PropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(long), (m, p) => new Int64PropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(ulong), (m, p) => new UInt64PropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(float), (m, p) => new SinglePropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(double), (m, p) => new DoublePropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(decimal), (m, p) => new DecimalPropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(string), (m, p) => new StringPropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(char), (m, p) => new CharPropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(bool), (m, p) => new BooleanPropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(Vector3), (m, p) => new Vector3PropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(Vector4), (m, p) => new Vector4PropertyViewModel(m, p)); - PropertyViewModelFactory.Default.Add(typeof(Quaternion), (m, p) => new QuaternionPropertyViewModel(m, p)); + PropertyViewModelFactory factory = new PropertyViewModelFactory + { + { typeof(char), (m, p) => new CharPropertyViewModel(m, p) }, + { typeof(string), (m, p) => new StringPropertyViewModel(m, p) }, + { typeof(bool), (m, p) => new BooleanPropertyViewModel(m, p) }, + { typeof(float), (m, p) => new SinglePropertyViewModel(m, p) }, + { typeof(double), (m, p) => new DoublePropertyViewModel(m, p) }, + { typeof(decimal), (m, p) => new DecimalPropertyViewModel(m, p) }, + { typeof(byte), (m, p) => new BytePropertyViewModel(m, p) }, + { typeof(sbyte), (m, p) => new SBytePropertyViewModel(m, p) }, + { typeof(short), (m, p) => new Int16PropertyViewModel(m, p) }, + { typeof(ushort), (m, p) => new UInt16PropertyViewModel(m, p) }, + { typeof(int), (m, p) => new Int32PropertyViewModel(m, p) }, + { typeof(uint), (m, p) => new UInt32PropertyViewModel(m, p) }, + { typeof(long), (m, p) => new Int64PropertyViewModel(m, p) }, + { typeof(ulong), (m, p) => new UInt64PropertyViewModel(m, p) }, + { typeof(Enum), (m, p) => new EnumPropertyViewModel(m, p) }, + { typeof(Guid), (m, p) => new GuidPropertyViewModel(m, p) }, + { typeof(DateTimeOffset?), (m, p) => new DateTimePropertyViewModel(m, p) }, + + { typeof(Vector3), (m, p) => new Vector3PropertyViewModel(m, p) }, + { typeof(Vector4), (m, p) => new Vector4PropertyViewModel(m, p) }, + { typeof(Quaternion), (m, p) => new QuaternionPropertyViewModel(m, p) } + }; + + PropertyViewModelFactory.Default = factory; Messenger.Default.Register(this, m => ShowProperties(m.Entity)); } diff --git a/DirectX12GameEngine.Editor/ViewModels/SolutionExplorerViewModel.cs b/DirectX12GameEngine.Editor/ViewModels/SolutionExplorerViewModel.cs index a4ca49d..93dfcb0 100644 --- a/DirectX12GameEngine.Editor/ViewModels/SolutionExplorerViewModel.cs +++ b/DirectX12GameEngine.Editor/ViewModels/SolutionExplorerViewModel.cs @@ -1,4 +1,5 @@ -using DirectX12GameEngine.Editor.Commanding; +using System.Threading.Tasks; +using DirectX12GameEngine.Editor.Commanding; using DirectX12GameEngine.Editor.Messages; using DirectX12GameEngine.Editor.Messaging; @@ -14,7 +15,7 @@ public SolutionExplorerViewModel() { OpenCommand = new RelayCommand(Open); DeleteCommand = new RelayCommand(Delete); - RefreshCommand = new RelayCommand(Refresh, () => RootFolder != null); + RefreshCommand = new RelayCommand(async () => await RefreshAsync(), () => RootFolder != null); Messenger.Default.Register(this, m => { @@ -35,6 +36,16 @@ public StorageFolderViewModel? RootFolder public RelayCommand RefreshCommand { get; } + public async Task RefreshAsync() + { + if (RootFolder != null) + { + RootFolder = new StorageFolderViewModel(RootFolder.Model); + await RootFolder.FillAsync(); + RootFolder.IsExpanded = true; + } + } + private void Open(StorageItemViewModel item) { Messenger.Default.Send(new LaunchStorageItemMessage(item)); @@ -44,16 +55,5 @@ private void Delete(StorageItemViewModel item) { item.Parent?.Children.Remove(item); } - - private void Refresh() - { - if (RootFolder != null) - { - RootFolder = new StorageFolderViewModel(RootFolder.Model) - { - IsExpanded = true - }; - } - } } } diff --git a/DirectX12GameEngine.Editor/ViewModels/StorageFolderViewModel.cs b/DirectX12GameEngine.Editor/ViewModels/StorageFolderViewModel.cs index 7213228..8f8bde4 100644 --- a/DirectX12GameEngine.Editor/ViewModels/StorageFolderViewModel.cs +++ b/DirectX12GameEngine.Editor/ViewModels/StorageFolderViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.Threading.Tasks; using Windows.Storage; #nullable enable @@ -38,13 +39,13 @@ public bool IsExpanded { if (isExpanded) { - Fill(); + _ = FillAsync(); } } } } - private async void Fill() + public async Task FillAsync() { if (HasUnrealizedChildren) { diff --git a/DirectX12GameEngine.Editor/Views/Properties/PropertyMemberTemplate.xaml b/DirectX12GameEngine.Editor/Views/Properties/PropertyMemberTemplate.xaml index 383738e..8303ebc 100644 --- a/DirectX12GameEngine.Editor/Views/Properties/PropertyMemberTemplate.xaml +++ b/DirectX12GameEngine.Editor/Views/Properties/PropertyMemberTemplate.xaml @@ -3,6 +3,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:extensions="using:Microsoft.Toolkit.Uwp.UI.Extensions" xmlns:local="using:DirectX12GameEngine.Editor.Views.Properties" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="32" @@ -18,13 +19,13 @@ + BorderThickness="2"> + Text="{x:Bind MemberName, Mode=OneWay}" /> - + diff --git a/DirectX12GameEngine.Editor/Views/Properties/PropertyMemberTemplate.xaml.cs b/DirectX12GameEngine.Editor/Views/Properties/PropertyMemberTemplate.xaml.cs index e660368..152cfd8 100644 --- a/DirectX12GameEngine.Editor/Views/Properties/PropertyMemberTemplate.xaml.cs +++ b/DirectX12GameEngine.Editor/Views/Properties/PropertyMemberTemplate.xaml.cs @@ -1,5 +1,4 @@ -using Windows.UI; -using Windows.UI.Xaml; +using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; diff --git a/DirectX12GameEngine.Editor/Views/PropertyGridView.xaml b/DirectX12GameEngine.Editor/Views/PropertyGridView.xaml index 0fdabc1..819c813 100644 --- a/DirectX12GameEngine.Editor/Views/PropertyGridView.xaml +++ b/DirectX12GameEngine.Editor/Views/PropertyGridView.xaml @@ -14,6 +14,10 @@ mc:Ignorable="d"> + + @@ -26,6 +30,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -103,77 +239,31 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + + + + + + + + + + + + + + + diff --git a/DirectX12GameEngine.Editor/Views/SceneView.xaml b/DirectX12GameEngine.Editor/Views/SceneView.xaml index a5a3b93..b2aa170 100644 --- a/DirectX12GameEngine.Editor/Views/SceneView.xaml +++ b/DirectX12GameEngine.Editor/Views/SceneView.xaml @@ -58,6 +58,11 @@ + + + diff --git a/DirectX12GameEngine.Editor/Views/SolutionExplorerView.xaml.cs b/DirectX12GameEngine.Editor/Views/SolutionExplorerView.xaml.cs index 87c0b63..24a3b93 100644 --- a/DirectX12GameEngine.Editor/Views/SolutionExplorerView.xaml.cs +++ b/DirectX12GameEngine.Editor/Views/SolutionExplorerView.xaml.cs @@ -27,11 +27,11 @@ public SolutionExplorerView() public SolutionExplorerViewModel ViewModel => (SolutionExplorerViewModel)DataContext; - private void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) + private async void RefreshContainer_RefreshRequested(Microsoft.UI.Xaml.Controls.RefreshContainer sender, Microsoft.UI.Xaml.Controls.RefreshRequestedEventArgs args) { Deferral deferral = args.GetDeferral(); - ViewModel.RefreshCommand.Execute(null); + await ViewModel.RefreshAsync(); deferral.Complete(); } diff --git a/DirectX12GameEngine.Engine/DirectX12GameEngine.Engine.csproj b/DirectX12GameEngine.Engine/DirectX12GameEngine.Engine.csproj index 7b78523..7d39cf4 100644 --- a/DirectX12GameEngine.Engine/DirectX12GameEngine.Engine.csproj +++ b/DirectX12GameEngine.Engine/DirectX12GameEngine.Engine.csproj @@ -3,7 +3,7 @@ netstandard2.0;netcoreapp3.0 8.0 - enable + enable true true WINDOWS_UWP @@ -16,6 +16,7 @@ + diff --git a/DirectX12GameEngine.Engine/EntityComponents/ScriptComponent.cs b/DirectX12GameEngine.Engine/EntityComponents/ScriptComponent.cs index a1fb426..41ceeb1 100644 --- a/DirectX12GameEngine.Engine/EntityComponents/ScriptComponent.cs +++ b/DirectX12GameEngine.Engine/EntityComponents/ScriptComponent.cs @@ -3,6 +3,7 @@ using DirectX12GameEngine.Core.Assets; using DirectX12GameEngine.Games; using DirectX12GameEngine.Graphics; +using DirectX12GameEngine.Input; using Microsoft.Extensions.DependencyInjection; namespace DirectX12GameEngine.Engine @@ -23,6 +24,9 @@ public abstract class ScriptComponent : EntityComponent [IgnoreDataMember] public GameBase Game { get; private set; } + [IgnoreDataMember] + public InputManager Input { get; private set; } + [IgnoreDataMember] public SceneSystem SceneSystem { get; private set; } @@ -38,6 +42,7 @@ internal void Initialize(IServiceProvider services) Content = Services.GetRequiredService(); Game = Services.GetRequiredService(); + Input = Services.GetRequiredService(); SceneSystem = Services.GetRequiredService(); Script = Services.GetRequiredService(); } diff --git a/DirectX12GameEngine.Engine/Game.cs b/DirectX12GameEngine.Engine/Game.cs index 9342bf3..6541fc2 100644 --- a/DirectX12GameEngine.Engine/Game.cs +++ b/DirectX12GameEngine.Engine/Game.cs @@ -1,5 +1,6 @@ using DirectX12GameEngine.Games; using DirectX12GameEngine.Graphics; +using DirectX12GameEngine.Input; using DirectX12GameEngine.Rendering.Materials; using Microsoft.Extensions.DependencyInjection; @@ -16,16 +17,20 @@ public Game(GameContext context) : base(context) GraphicsDevice.Presenter = Services.GetService(); } + Input = Services.GetRequiredService(); SceneSystem = Services.GetRequiredService(); Script = Services.GetRequiredService(); ShaderContent = Services.GetRequiredService(); + GameSystems.Add(Input); GameSystems.Add(SceneSystem); GameSystems.Add(Script); } public GraphicsDevice? GraphicsDevice { get; set; } + public InputManager Input { get; } + public SceneSystem SceneSystem { get; } public ScriptSystem Script { get; } @@ -57,8 +62,8 @@ protected override void BeginDraw() if (Window != null && GraphicsDevice.Presenter != null) { - int windowWidth = Window.ClientBounds.Width; - int windowHeight = Window.ClientBounds.Height; + int windowWidth = (int)Window.ClientBounds.Width; + int windowHeight = (int)Window.ClientBounds.Height; if (windowWidth != GraphicsDevice.Presenter.BackBuffer.Width || windowHeight != GraphicsDevice.Presenter.BackBuffer.Height) { @@ -86,6 +91,7 @@ protected override void ConfigureServices(IServiceCollection services) { base.ConfigureServices(services); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/DirectX12GameEngine.Engine/GameContext.Uwp.cs b/DirectX12GameEngine.Engine/GameContext.Uwp.cs index 641eb5a..f557fe1 100644 --- a/DirectX12GameEngine.Engine/GameContext.Uwp.cs +++ b/DirectX12GameEngine.Engine/GameContext.Uwp.cs @@ -1,6 +1,8 @@ #if WINDOWS_UWP using System; using DirectX12GameEngine.Graphics; +using DirectX12GameEngine.Graphics.Holographic; +using DirectX12GameEngine.Input; using Microsoft.Extensions.DependencyInjection; using Windows.Graphics.Holographic; using Windows.UI.Core; @@ -21,8 +23,9 @@ public override void ConfigureServices(IServiceCollection services) { base.ConfigureServices(services); - services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(new CoreWindowGameWindow(Control)); + services.AddSingleton(new CoreWindowSwapChainGraphicsPresenter(GraphicsDevice, PresentationParameters, Control)); + services.AddSingleton(new CoreWindowInputSourceConfiguration(Control)); } } @@ -43,9 +46,9 @@ public override void ConfigureServices(IServiceCollection services) { base.ConfigureServices(services); - services.AddSingleton(HolographicSpace); - services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(new CoreWindowGameWindow(Control)); + services.AddSingleton(new HolographicGraphicsPresenter(GraphicsDevice, PresentationParameters, HolographicSpace)); + services.AddSingleton(new CoreWindowInputSourceConfiguration(Control)); } } @@ -61,8 +64,9 @@ public override void ConfigureServices(IServiceCollection services) { base.ConfigureServices(services); - services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(new XamlGameWindow(Control)); + services.AddSingleton(new XamlSwapChainGraphicsPresenter(GraphicsDevice, PresentationParameters, Control)); + services.AddSingleton(new XamlInputSourceConfiguration(Control)); } } } diff --git a/DirectX12GameEngine.Engine/GameContext.WindowsDesktop.cs b/DirectX12GameEngine.Engine/GameContext.WindowsDesktop.cs index 540e82a..d416f13 100644 --- a/DirectX12GameEngine.Engine/GameContext.WindowsDesktop.cs +++ b/DirectX12GameEngine.Engine/GameContext.WindowsDesktop.cs @@ -1,6 +1,7 @@ #if NETCOREAPP using System.Windows.Forms; using DirectX12GameEngine.Graphics; +using DirectX12GameEngine.Input; using Microsoft.Extensions.DependencyInjection; namespace DirectX12GameEngine.Games @@ -18,9 +19,9 @@ public override void ConfigureServices(IServiceCollection services) { base.ConfigureServices(services); - services.AddSingleton(new WindowHandle(Control.Handle)); - services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(new WinFormsGameWindow(Control)); + services.AddSingleton(new HwndSwapChainGraphicsPresenter(GraphicsDevice, PresentationParameters, new WindowHandle(Control.Handle))); + services.AddSingleton(new WinFormsInputSourceConfiguration(Control)); } } } diff --git a/DirectX12GameEngine.Engine/GameContextWithGraphics.cs b/DirectX12GameEngine.Engine/GameContextWithGraphics.cs index f92aa55..8c564bd 100644 --- a/DirectX12GameEngine.Engine/GameContextWithGraphics.cs +++ b/DirectX12GameEngine.Engine/GameContextWithGraphics.cs @@ -9,14 +9,15 @@ public GameContextWithGraphics(TControl control) : base(control) { } + public GraphicsDevice GraphicsDevice { get; } = new GraphicsDevice(); + public PresentationParameters PresentationParameters { get; } = new PresentationParameters(); public override void ConfigureServices(IServiceCollection services) { base.ConfigureServices(services); - services.AddSingleton(); - services.AddSingleton(PresentationParameters); + services.AddSingleton(GraphicsDevice); } } } diff --git a/DirectX12GameEngine.Engine/SceneSystem.cs b/DirectX12GameEngine.Engine/SceneSystem.cs index c72cd31..29de6fd 100644 --- a/DirectX12GameEngine.Engine/SceneSystem.cs +++ b/DirectX12GameEngine.Engine/SceneSystem.cs @@ -32,17 +32,17 @@ public override async Task LoadContentAsync() public override void Update(GameTime gameTime) { - SceneInstance?.Update(gameTime); + SceneInstance.Update(gameTime); } public override void Draw(GameTime gameTime) { - SceneInstance?.Draw(gameTime); + SceneInstance.Draw(gameTime); } public override void Dispose() { - SceneInstance?.Dispose(); + SceneInstance.Dispose(); } } } diff --git a/DirectX12GameEngine.Games/CoreWindowGameWindow.cs b/DirectX12GameEngine.Games/CoreWindowGameWindow.cs index 959a69f..e048d05 100644 --- a/DirectX12GameEngine.Games/CoreWindowGameWindow.cs +++ b/DirectX12GameEngine.Games/CoreWindowGameWindow.cs @@ -17,14 +17,14 @@ public CoreWindowGameWindow(CoreWindow coreWindow) coreWindow.SizeChanged += CoreWindow_SizeChanged; } - public override Rectangle ClientBounds + public override RectangleF ClientBounds { get { double resolutionScale = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel; - return new Rectangle((int)coreWindow.Bounds.X, (int)coreWindow.Bounds.X, - Math.Max(1, (int)(coreWindow.Bounds.Width * resolutionScale)), Math.Max(1, (int)(coreWindow.Bounds.Height * resolutionScale))); + return new RectangleF((float)coreWindow.Bounds.X, (float)coreWindow.Bounds.X, + Math.Max(1, (float)(coreWindow.Bounds.Width * resolutionScale)), Math.Max(1, (float)(coreWindow.Bounds.Height * resolutionScale))); } } diff --git a/DirectX12GameEngine.Games/DirectX12GameEngine.Games.csproj b/DirectX12GameEngine.Games/DirectX12GameEngine.Games.csproj index a555fed..baa110e 100644 --- a/DirectX12GameEngine.Games/DirectX12GameEngine.Games.csproj +++ b/DirectX12GameEngine.Games/DirectX12GameEngine.Games.csproj @@ -3,7 +3,7 @@ netstandard2.0;netcoreapp3.0 8.0 - enable + enable true WINDOWS_UWP diff --git a/DirectX12GameEngine.Games/GameContext.cs b/DirectX12GameEngine.Games/GameContext.cs index 35bd4dc..597a795 100644 --- a/DirectX12GameEngine.Games/GameContext.cs +++ b/DirectX12GameEngine.Games/GameContext.cs @@ -21,8 +21,6 @@ protected GameContext(TControl control) public override void ConfigureServices(IServiceCollection services) { base.ConfigureServices(services); - - services.AddSingleton(Control); } } } diff --git a/DirectX12GameEngine.Games/GameWindow.cs b/DirectX12GameEngine.Games/GameWindow.cs index c8a2b54..bf23cf1 100644 --- a/DirectX12GameEngine.Games/GameWindow.cs +++ b/DirectX12GameEngine.Games/GameWindow.cs @@ -11,7 +11,7 @@ public abstract class GameWindow : IDisposable public bool IsExiting { get; private set; } - public abstract Rectangle ClientBounds { get; } + public abstract RectangleF ClientBounds { get; } public virtual void Dispose() { diff --git a/DirectX12GameEngine.Games/WinFormsGameWindow.cs b/DirectX12GameEngine.Games/WinFormsGameWindow.cs index 1b7930a..aa5bc8f 100644 --- a/DirectX12GameEngine.Games/WinFormsGameWindow.cs +++ b/DirectX12GameEngine.Games/WinFormsGameWindow.cs @@ -17,11 +17,11 @@ public WinFormsGameWindow(Control control) control.ClientSizeChanged += Control_ClientSizeChanged; } - public override Rectangle ClientBounds + public override RectangleF ClientBounds { get { - Rectangle clientRectangle = control.ClientRectangle; + RectangleF clientRectangle = control.ClientRectangle; clientRectangle.Width = Math.Max(clientRectangle.Width, 1); clientRectangle.Height = Math.Max(clientRectangle.Height, 1); diff --git a/DirectX12GameEngine.Games/XamlGameWindow.cs b/DirectX12GameEngine.Games/XamlGameWindow.cs index d79fb63..96822f2 100644 --- a/DirectX12GameEngine.Games/XamlGameWindow.cs +++ b/DirectX12GameEngine.Games/XamlGameWindow.cs @@ -17,13 +17,13 @@ public XamlGameWindow(SwapChainPanel swapChainPanel) swapChainPanel.CompositionScaleChanged += SwapChainPanel_CompositionScaleChanged; } - public override Rectangle ClientBounds + public override RectangleF ClientBounds { get { - return new Rectangle(0, 0, - Math.Max(1, (int)(swapChainPanel.ActualWidth * swapChainPanel.CompositionScaleX + 0.5f)), - Math.Max(1, (int)(swapChainPanel.ActualHeight * swapChainPanel.CompositionScaleY + 0.5f))); + return new RectangleF(0, 0, + Math.Max(1.0f, (float)swapChainPanel.ActualWidth * swapChainPanel.CompositionScaleX + 0.5f), + Math.Max(1, (float)swapChainPanel.ActualHeight * swapChainPanel.CompositionScaleY + 0.5f)); } } diff --git a/DirectX12GameEngine.Graphics.Holographic/DirectX12GameEngine.Graphics.Holographic.csproj b/DirectX12GameEngine.Graphics.Holographic/DirectX12GameEngine.Graphics.Holographic.csproj index 0b8a2b5..f579774 100644 --- a/DirectX12GameEngine.Graphics.Holographic/DirectX12GameEngine.Graphics.Holographic.csproj +++ b/DirectX12GameEngine.Graphics.Holographic/DirectX12GameEngine.Graphics.Holographic.csproj @@ -3,7 +3,7 @@ netstandard2.0 8.0 - enable + enable WINDOWS_UWP diff --git a/DirectX12GameEngine.Graphics/DirectX12GameEngine.Graphics.csproj b/DirectX12GameEngine.Graphics/DirectX12GameEngine.Graphics.csproj index cb89b65..4f43297 100644 --- a/DirectX12GameEngine.Graphics/DirectX12GameEngine.Graphics.csproj +++ b/DirectX12GameEngine.Graphics/DirectX12GameEngine.Graphics.csproj @@ -3,7 +3,7 @@ netstandard2.0 8.0 - enable + enable true true diff --git a/DirectX12GameEngine.Input/BatteryReport.cs b/DirectX12GameEngine.Input/BatteryReport.cs new file mode 100644 index 0000000..a91d7b7 --- /dev/null +++ b/DirectX12GameEngine.Input/BatteryReport.cs @@ -0,0 +1,15 @@ +namespace DirectX12GameEngine.Input +{ + public abstract class BatteryReport + { + public abstract int? ChargeRateInMilliwatts { get; } + + public abstract int? DesignCapacityInMilliwattHours { get; } + + public abstract int? FullChargeCapacityInMilliwattHours { get; } + + public abstract int? RemainingCapacityInMilliwattHours { get; } + + public abstract BatteryStatus Status { get; } + } +} diff --git a/DirectX12GameEngine.Input/BatteryStatus.cs b/DirectX12GameEngine.Input/BatteryStatus.cs new file mode 100644 index 0000000..c1b4a4a --- /dev/null +++ b/DirectX12GameEngine.Input/BatteryStatus.cs @@ -0,0 +1,10 @@ +namespace DirectX12GameEngine.Input +{ + public enum BatteryStatus + { + NotPresent = 0, + Discharging = 1, + Idle = 2, + Charging = 3 + } +} diff --git a/DirectX12GameEngine.Input/CoreWindow/CoreWindowInputSourceConfiguration.cs b/DirectX12GameEngine.Input/CoreWindow/CoreWindowInputSourceConfiguration.cs new file mode 100644 index 0000000..eb5147d --- /dev/null +++ b/DirectX12GameEngine.Input/CoreWindow/CoreWindowInputSourceConfiguration.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Windows.UI.Core; + +namespace DirectX12GameEngine.Input +{ + public sealed class CoreWindowInputSourceConfiguration : IInputSourceConfiguration + { + public CoreWindowInputSourceConfiguration(CoreWindow coreWindow) + { + UwpGamepadInputSource gamepadSource = new UwpGamepadInputSource(); + Sources.Add(gamepadSource); + + CoreWindowKeyboardInputSource keyboardSource = new CoreWindowKeyboardInputSource(coreWindow); + Sources.Add(keyboardSource); + + CoreWindowPointerInputSource pointerSource = new CoreWindowPointerInputSource(coreWindow); + Sources.Add(pointerSource); + } + + public IList Sources { get; } = new List(); + } +} diff --git a/DirectX12GameEngine.Input/CoreWindow/CoreWindowKeyboardInputSource.cs b/DirectX12GameEngine.Input/CoreWindow/CoreWindowKeyboardInputSource.cs new file mode 100644 index 0000000..b18ecf1 --- /dev/null +++ b/DirectX12GameEngine.Input/CoreWindow/CoreWindowKeyboardInputSource.cs @@ -0,0 +1,47 @@ +using Windows.UI.Core; + +namespace DirectX12GameEngine.Input +{ + public class CoreWindowKeyboardInputSource : KeyboardInputSourceBase + { + private readonly CoreWindow control; + + public CoreWindowKeyboardInputSource(CoreWindow coreWindow) + { + control = coreWindow; + + control.KeyDown += Control_KeyDown; + control.KeyUp += Control_KeyUp; + } + + public override void Dispose() + { + control.KeyDown -= Control_KeyDown; + control.KeyUp -= Control_KeyUp; + } + + private void Control_KeyDown(CoreWindow sender, Windows.UI.Core.KeyEventArgs args) + { + OnKeyDown(new CoreWindowKeyEventArgs(args)); + } + + private void Control_KeyUp(CoreWindow sender, Windows.UI.Core.KeyEventArgs args) + { + OnKeyUp(new CoreWindowKeyEventArgs(args)); + } + + private class CoreWindowKeyEventArgs : KeyEventArgs + { + private readonly Windows.UI.Core.KeyEventArgs args; + + public CoreWindowKeyEventArgs(Windows.UI.Core.KeyEventArgs args) + { + this.args = args; + } + + public override bool Handled { get => args.Handled; set => args.Handled = value; } + + public override VirtualKey Key => (VirtualKey)args.VirtualKey; + } + } +} diff --git a/DirectX12GameEngine.Input/CoreWindow/CoreWindowPointerInputSource.cs b/DirectX12GameEngine.Input/CoreWindow/CoreWindowPointerInputSource.cs new file mode 100644 index 0000000..3ba6d2e --- /dev/null +++ b/DirectX12GameEngine.Input/CoreWindow/CoreWindowPointerInputSource.cs @@ -0,0 +1,107 @@ +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using Windows.UI.Core; + +namespace DirectX12GameEngine.Input +{ + public class CoreWindowPointerInputSource : PointerInputSourceBase + { + private readonly CoreWindow control; + + public CoreWindowPointerInputSource(CoreWindow coreWindow) + { + control = coreWindow; + + control.PointerCaptureLost += Control_PointerCaptureLost; + control.PointerEntered += Control_PointerEntered; + control.PointerExited += Control_PointerExited; + control.PointerMoved += Control_PointerMoved; + control.PointerPressed += Control_PointerPressed; + control.PointerReleased += Control_PointerReleased; + control.PointerWheelChanged += Control_PointerWheelChanged; + } + + public override bool HasCapture => true; + + public override bool IsInputEnabled { get => control.IsInputEnabled; set => control.IsInputEnabled = value; } + + public override Cursor PointerCursor + { + get => new Cursor((CursorType)control.PointerCursor.Type, control.PointerCursor.Id); + set => control.PointerCursor = new CoreCursor((CoreCursorType)value.Type, value.Id); + } + + public override Vector2 PointerPosition => new Vector2((float)control.PointerPosition.X, (float)control.PointerPosition.Y); + + public override void ReleasePointerCapture() => control.ReleasePointerCapture(); + + public override void SetPointerCapture() => control.SetPointerCapture(); + + public override void Dispose() + { + base.Dispose(); + + control.PointerCaptureLost -= Control_PointerCaptureLost; + control.PointerEntered -= Control_PointerEntered; + control.PointerExited -= Control_PointerExited; + control.PointerMoved -= Control_PointerMoved; + control.PointerPressed -= Control_PointerPressed; + control.PointerReleased -= Control_PointerReleased; + control.PointerWheelChanged -= Control_PointerWheelChanged; + } + + private void Control_PointerCaptureLost(CoreWindow sender, Windows.UI.Core.PointerEventArgs args) + { + OnPointerCaptureLost(new CoreWindowPointerEventArgs(args)); + } + + private void Control_PointerEntered(CoreWindow sender, Windows.UI.Core.PointerEventArgs args) + { + OnPointerEntered(new CoreWindowPointerEventArgs(args)); + } + + private void Control_PointerExited(CoreWindow sender, Windows.UI.Core.PointerEventArgs args) + { + OnPointerExited(new CoreWindowPointerEventArgs(args)); + } + + private void Control_PointerMoved(CoreWindow sender, Windows.UI.Core.PointerEventArgs args) + { + OnPointerMoved(new CoreWindowPointerEventArgs(args)); + } + + private void Control_PointerPressed(CoreWindow sender, Windows.UI.Core.PointerEventArgs args) + { + OnPointerPressed(new CoreWindowPointerEventArgs(args)); + } + + private void Control_PointerReleased(CoreWindow sender, Windows.UI.Core.PointerEventArgs args) + { + OnPointerReleased(new CoreWindowPointerEventArgs(args)); + } + + private void Control_PointerWheelChanged(CoreWindow sender, Windows.UI.Core.PointerEventArgs args) + { + OnPointerWheelChanged(new CoreWindowPointerEventArgs(args)); + } + + private class CoreWindowPointerEventArgs : PointerEventArgs + { + private readonly Windows.UI.Core.PointerEventArgs args; + + public CoreWindowPointerEventArgs(Windows.UI.Core.PointerEventArgs args) + { + this.args = args; + } + + public override bool Handled { get => args.Handled; set => args.Handled = value; } + + public override PointerPoint CurrentPoint => new UwpPointerPoint(args.CurrentPoint); + + public override VirtualKeyModifiers KeyModifiers => (VirtualKeyModifiers)args.KeyModifiers; + + public override IList GetIntermediatePoints() => args.GetIntermediatePoints().Select(p => new UwpPointerPoint(p)).ToArray(); + } + } +} diff --git a/DirectX12GameEngine.Input/Cursor.cs b/DirectX12GameEngine.Input/Cursor.cs new file mode 100644 index 0000000..1a809cc --- /dev/null +++ b/DirectX12GameEngine.Input/Cursor.cs @@ -0,0 +1,15 @@ +namespace DirectX12GameEngine.Input +{ + public class Cursor + { + public Cursor(CursorType type, uint id) + { + Type = type; + Id = id; + } + + public uint Id { get; } + + public CursorType Type { get; } + } +} diff --git a/DirectX12GameEngine.Input/CursorType.cs b/DirectX12GameEngine.Input/CursorType.cs new file mode 100644 index 0000000..2c75401 --- /dev/null +++ b/DirectX12GameEngine.Input/CursorType.cs @@ -0,0 +1,22 @@ +namespace DirectX12GameEngine.Input +{ + public enum CursorType + { + Arrow = 0, + Cross = 1, + Custom = 2, + Hand = 3, + Help = 4, + IBeam = 5, + SizeAll = 6, + SizeNortheastSouthwest = 7, + SizeNorthSouth = 8, + SizeNorthwestSoutheast = 9, + SizeWestEast = 10, + UniversalNo = 11, + UpArrow = 12, + Wait = 13, + Pin = 14, + Person = 15 + } +} diff --git a/DirectX12GameEngine.Input/DirectX12GameEngine.Input.csproj b/DirectX12GameEngine.Input/DirectX12GameEngine.Input.csproj new file mode 100644 index 0000000..a1344af --- /dev/null +++ b/DirectX12GameEngine.Input/DirectX12GameEngine.Input.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0;netcoreapp3.0 + 8.0 + enable + true + WINDOWS_UWP + + + + + + + diff --git a/DirectX12GameEngine.Input/GamepadButtons.cs b/DirectX12GameEngine.Input/GamepadButtons.cs new file mode 100644 index 0000000..255f854 --- /dev/null +++ b/DirectX12GameEngine.Input/GamepadButtons.cs @@ -0,0 +1,28 @@ +using System; + +namespace DirectX12GameEngine.Input +{ + [Flags] + public enum GamepadButtons : uint + { + None = 0, + Menu = 1, + View = 2, + A = 4, + B = 8, + X = 16, + Y = 32, + DPadUp = 64, + DPadDown = 128, + DPadLeft = 256, + DPadRight = 512, + LeftShoulder = 1024, + RightShoulder = 2048, + LeftThumbstick = 4096, + RightThumbstick = 8192, + Paddle1 = 16384, + Paddle2 = 32768, + Paddle3 = 65536, + Paddle4 = 131072 + } +} diff --git a/DirectX12GameEngine.Input/GamepadDeviceBase.cs b/DirectX12GameEngine.Input/GamepadDeviceBase.cs new file mode 100644 index 0000000..c17ec03 --- /dev/null +++ b/DirectX12GameEngine.Input/GamepadDeviceBase.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; + +namespace DirectX12GameEngine.Input +{ + public abstract class GamepadDeviceBase : IGamepadDevice + { + public abstract bool IsWireless { get; } + + public abstract GamepadVibration Vibration { get; set; } + + public ISet DownButtons { get; } = new HashSet(); + + public ISet PressedButtons { get; } = new HashSet(); + + public ISet ReleasedButtons { get; } = new HashSet(); + + public abstract GamepadReading CurrentReading { get; } + + public abstract BatteryReport TryGetBatteryReport(); + + public abstract void Update(); + + protected void ClearButtonStates() + { + PressedButtons.Clear(); + ReleasedButtons.Clear(); + } + + protected void UpdateButtonState(GamepadButtons button, bool isDown) + { + if (isDown && !DownButtons.Contains(button)) + { + PressedButtons.Add(button); + DownButtons.Add(button); + } + else if (!isDown && DownButtons.Contains(button)) + { + ReleasedButtons.Add(button); + DownButtons.Remove(button); + } + } + } +} diff --git a/DirectX12GameEngine.Input/GamepadInputSourceBase.cs b/DirectX12GameEngine.Input/GamepadInputSourceBase.cs new file mode 100644 index 0000000..958d8c3 --- /dev/null +++ b/DirectX12GameEngine.Input/GamepadInputSourceBase.cs @@ -0,0 +1,26 @@ +using System.Collections.ObjectModel; + +namespace DirectX12GameEngine.Input +{ + public class GamepadInputSourceBase : IGamepadInputSource + { + public ObservableCollection Gamepads { get; } = new ObservableCollection(); + + public virtual void Dispose() + { + Gamepads.Clear(); + } + + public virtual void Scan() + { + } + + public virtual void Update() + { + foreach (IGamepadDevice gamepad in Gamepads) + { + gamepad.Update(); + } + } + } +} diff --git a/DirectX12GameEngine.Input/GamepadReading.cs b/DirectX12GameEngine.Input/GamepadReading.cs new file mode 100644 index 0000000..9cc373e --- /dev/null +++ b/DirectX12GameEngine.Input/GamepadReading.cs @@ -0,0 +1,17 @@ +using System.Numerics; + +namespace DirectX12GameEngine.Input +{ + public struct GamepadReading + { + public GamepadButtons Buttons { get; set; } + + public float LeftTrigger { get; set; } + + public float RightTrigger { get; set; } + + public Vector2 LeftThumbstick { get; set; } + + public Vector2 RightThumbstick { get; set; } + } +} diff --git a/DirectX12GameEngine.Input/GamepadVibration.cs b/DirectX12GameEngine.Input/GamepadVibration.cs new file mode 100644 index 0000000..c890b84 --- /dev/null +++ b/DirectX12GameEngine.Input/GamepadVibration.cs @@ -0,0 +1,14 @@ +namespace DirectX12GameEngine.Input +{ + public struct GamepadVibration + { + public double LeftMotor { get; set; } + + public double RightMotor { get; set; } + + public double LeftTrigger { get; set; } + + public double RightTrigger { get; set; } + } +} + diff --git a/DirectX12GameEngine.Input/IGamepadDevice.cs b/DirectX12GameEngine.Input/IGamepadDevice.cs new file mode 100644 index 0000000..38b4feb --- /dev/null +++ b/DirectX12GameEngine.Input/IGamepadDevice.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace DirectX12GameEngine.Input +{ + public interface IGamepadDevice + { + public bool IsWireless { get; } + + public GamepadVibration Vibration { get; set; } + + public ISet DownButtons { get; } + + public ISet PressedButtons { get; } + + public ISet ReleasedButtons { get; } + + public GamepadReading CurrentReading { get; } + + public BatteryReport TryGetBatteryReport(); + + public void Update(); + } +} diff --git a/DirectX12GameEngine.Input/IGamepadInputSource.cs b/DirectX12GameEngine.Input/IGamepadInputSource.cs new file mode 100644 index 0000000..cb2f5c4 --- /dev/null +++ b/DirectX12GameEngine.Input/IGamepadInputSource.cs @@ -0,0 +1,9 @@ +using System.Collections.ObjectModel; + +namespace DirectX12GameEngine.Input +{ + public interface IGamepadInputSource : IInputSource + { + ObservableCollection Gamepads { get; } + } +} diff --git a/DirectX12GameEngine.Input/IInputSource.cs b/DirectX12GameEngine.Input/IInputSource.cs new file mode 100644 index 0000000..76f424c --- /dev/null +++ b/DirectX12GameEngine.Input/IInputSource.cs @@ -0,0 +1,11 @@ +using System; + +namespace DirectX12GameEngine.Input +{ + public interface IInputSource : IDisposable + { + void Scan(); + + void Update(); + } +} diff --git a/DirectX12GameEngine.Input/IInputSourceConfiguration.cs b/DirectX12GameEngine.Input/IInputSourceConfiguration.cs new file mode 100644 index 0000000..e06b7b3 --- /dev/null +++ b/DirectX12GameEngine.Input/IInputSourceConfiguration.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace DirectX12GameEngine.Input +{ + public interface IInputSourceConfiguration + { + public IList Sources { get; } + } +} diff --git a/DirectX12GameEngine.Input/IKeyboardInputSource.cs b/DirectX12GameEngine.Input/IKeyboardInputSource.cs new file mode 100644 index 0000000..82dc79e --- /dev/null +++ b/DirectX12GameEngine.Input/IKeyboardInputSource.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace DirectX12GameEngine.Input +{ + public interface IKeyboardInputSource : IInputSource + { + public event EventHandler KeyDown; + + public event EventHandler KeyUp; + + public ISet DownKeys { get; } + + public ISet PressedKeys { get; } + + public ISet ReleasedKeys { get; } + } +} diff --git a/DirectX12GameEngine.Input/IPointerInputSource.cs b/DirectX12GameEngine.Input/IPointerInputSource.cs new file mode 100644 index 0000000..837eb95 --- /dev/null +++ b/DirectX12GameEngine.Input/IPointerInputSource.cs @@ -0,0 +1,34 @@ +using System; +using System.Numerics; + +namespace DirectX12GameEngine.Input +{ + public interface IPointerInputSource : IInputSource + { + event EventHandler PointerCaptureLost; + + event EventHandler PointerEntered; + + event EventHandler PointerExited; + + event EventHandler PointerMoved; + + event EventHandler PointerPressed; + + event EventHandler PointerReleased; + + event EventHandler PointerWheelChanged; + + bool HasCapture { get; } + + bool IsInputEnabled { get; set; } + + Cursor PointerCursor { get; set; } + + Vector2 PointerPosition { get; } + + void ReleasePointerCapture(); + + void SetPointerCapture(); + } +} diff --git a/DirectX12GameEngine.Input/InputManager.cs b/DirectX12GameEngine.Input/InputManager.cs new file mode 100644 index 0000000..3ee01c8 --- /dev/null +++ b/DirectX12GameEngine.Input/InputManager.cs @@ -0,0 +1,132 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Linq; +using DirectX12GameEngine.Games; + +namespace DirectX12GameEngine.Input +{ + public class InputManager : GameSystemBase + { + private readonly List gamepadSources = new List(); + private readonly List keyboardSources = new List(); + private readonly List pointerSources = new List(); + + private readonly HashSet noKeys = new HashSet(); + + public ObservableCollection Sources { get; } = new ObservableCollection(); + + public IGamepadInputSource? Gamepad => gamepadSources.FirstOrDefault(); + + public IKeyboardInputSource? Keyboard => keyboardSources.FirstOrDefault(); + + public IPointerInputSource? Pointer => pointerSources.FirstOrDefault(); + + public IReadOnlyList GamepadSources => gamepadSources.AsReadOnly(); + + public IReadOnlyList KeyboardSources => keyboardSources.AsReadOnly(); + + public IReadOnlyList PointerSources => pointerSources.AsReadOnly(); + + public InputManager() + { + Sources.CollectionChanged += Sources_CollectionChanged; + } + + public InputManager(IInputSourceConfiguration configuration) : this() + { + foreach (IInputSource inputSource in configuration.Sources) + { + Sources.Add(inputSource); + } + } + + public bool IsKeyDown(VirtualKey key) + { + return Keyboard?.DownKeys.Contains(key) ?? false; + } + + public bool IsKeyPressed(VirtualKey key) + { + return Keyboard?.PressedKeys.Contains(key) ?? false; + } + + public bool IsKeyReleased(VirtualKey key) + { + return Keyboard?.ReleasedKeys.Contains(key) ?? false; + } + + public ISet DownKeys => Keyboard is null ? noKeys : Keyboard.DownKeys; + + public ISet PressedKeys => Keyboard is null ? noKeys : Keyboard.PressedKeys; + + public ISet ReleasedKeys => Keyboard is null ? noKeys : Keyboard.ReleasedKeys; + + public void Scan() + { + foreach (IInputSource source in Sources) + { + source.Scan(); + } + } + + public override void Update(GameTime gameTime) + { + foreach (IInputSource source in Sources) + { + source.Update(); + } + } + + private void OnInputSourceAdded(IInputSource source) + { + switch (source) + { + case IKeyboardInputSource keyboardSource: + keyboardSources.Add(keyboardSource); + break; + case IPointerInputSource pointerSource: + pointerSources.Add(pointerSource); + break; + case IGamepadInputSource gamepadSource: + gamepadSources.Add(gamepadSource); + break; + } + } + + private void OnInputSourceRemoved(IInputSource source) + { + switch (source) + { + case IKeyboardInputSource keyboardDevice: + keyboardSources.Remove(keyboardDevice); + break; + case IPointerInputSource pointerSource: + pointerSources.Remove(pointerSource); + break; + case IGamepadInputSource gamepadSource: + gamepadSources.Remove(gamepadSource); + break; + } + } + + private void Sources_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + foreach (IInputSource? source in e.NewItems) + { + OnInputSourceAdded(source!); + } + break; + case NotifyCollectionChangedAction.Remove: + foreach (IInputSource? source in e.OldItems) + { + OnInputSourceRemoved(source!); + } + break; + } + } + } +} diff --git a/DirectX12GameEngine.Input/KeyEventArgs.cs b/DirectX12GameEngine.Input/KeyEventArgs.cs new file mode 100644 index 0000000..5136652 --- /dev/null +++ b/DirectX12GameEngine.Input/KeyEventArgs.cs @@ -0,0 +1,11 @@ +using System; + +namespace DirectX12GameEngine.Input +{ + public abstract class KeyEventArgs : EventArgs + { + public abstract bool Handled { get; set; } + + public abstract VirtualKey Key { get; } + } +} diff --git a/DirectX12GameEngine.Input/KeyboardInputSourceBase.cs b/DirectX12GameEngine.Input/KeyboardInputSourceBase.cs new file mode 100644 index 0000000..39cb5b7 --- /dev/null +++ b/DirectX12GameEngine.Input/KeyboardInputSourceBase.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace DirectX12GameEngine.Input +{ + public class KeyboardInputSourceBase : IKeyboardInputSource + { + private readonly List keyEvents = new List(); + + public event EventHandler KeyDown; + + public event EventHandler KeyUp; + + public ISet DownKeys { get; } = new HashSet(); + + public ISet PressedKeys { get; } = new HashSet(); + + public ISet ReleasedKeys { get; } = new HashSet(); + + public virtual void Dispose() + { + } + + public virtual void Scan() + { + } + + public virtual void Update() + { + PressedKeys.Clear(); + ReleasedKeys.Clear(); + + foreach (KeyEventArgs keyEvent in keyEvents) + { + if (DownKeys.Contains(keyEvent.Key)) + { + PressedKeys.Add(keyEvent.Key); + } + else + { + ReleasedKeys.Add(keyEvent.Key); + } + } + + keyEvents.Clear(); + } + + protected virtual void OnKeyDown(KeyEventArgs e) + { + if (!DownKeys.Contains(e.Key)) + { + DownKeys.Add(e.Key); + keyEvents.Add(e); + } + + KeyDown?.Invoke(this, e); + } + + protected virtual void OnKeyUp(KeyEventArgs e) + { + if (DownKeys.Contains(e.Key)) + { + DownKeys.Remove(e.Key); + keyEvents.Add(e); + } + + KeyUp?.Invoke(this, e); + } + } +} diff --git a/DirectX12GameEngine.Input/PointerEventArgs.cs b/DirectX12GameEngine.Input/PointerEventArgs.cs new file mode 100644 index 0000000..07e97b8 --- /dev/null +++ b/DirectX12GameEngine.Input/PointerEventArgs.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace DirectX12GameEngine.Input +{ + public abstract class PointerEventArgs : EventArgs + { + public abstract bool Handled { get; set; } + + public abstract PointerPoint CurrentPoint { get; } + + public abstract VirtualKeyModifiers KeyModifiers { get; } + + public abstract IList GetIntermediatePoints(); + } +} diff --git a/DirectX12GameEngine.Input/PointerInputSourceBase.cs b/DirectX12GameEngine.Input/PointerInputSourceBase.cs new file mode 100644 index 0000000..c88a13c --- /dev/null +++ b/DirectX12GameEngine.Input/PointerInputSourceBase.cs @@ -0,0 +1,81 @@ +using System; +using System.Numerics; + +namespace DirectX12GameEngine.Input +{ + public abstract class PointerInputSourceBase : IPointerInputSource + { + public event EventHandler PointerCaptureLost; + + public event EventHandler PointerEntered; + + public event EventHandler PointerExited; + + public event EventHandler PointerMoved; + + public event EventHandler PointerPressed; + + public event EventHandler PointerReleased; + + public event EventHandler PointerWheelChanged; + + public abstract bool HasCapture { get; } + + public abstract bool IsInputEnabled { get; set; } + + public abstract Cursor PointerCursor { get; set; } + + public abstract Vector2 PointerPosition { get; } + + public virtual void Dispose() + { + } + + public abstract void ReleasePointerCapture(); + + public abstract void SetPointerCapture(); + + public virtual void Scan() + { + } + + public virtual void Update() + { + } + + protected virtual void OnPointerCaptureLost(PointerEventArgs e) + { + PointerCaptureLost?.Invoke(this, e); + } + + protected virtual void OnPointerEntered(PointerEventArgs e) + { + PointerEntered?.Invoke(this, e); + } + + protected virtual void OnPointerExited(PointerEventArgs e) + { + PointerExited?.Invoke(this, e); + } + + protected virtual void OnPointerMoved(PointerEventArgs e) + { + PointerMoved?.Invoke(this, e); + } + + protected virtual void OnPointerPressed(PointerEventArgs e) + { + PointerPressed?.Invoke(this, e); + } + + protected virtual void OnPointerReleased(PointerEventArgs e) + { + PointerReleased?.Invoke(this, e); + } + + protected virtual void OnPointerWheelChanged(PointerEventArgs e) + { + PointerWheelChanged?.Invoke(this, e); + } + } +} diff --git a/DirectX12GameEngine.Input/PointerPoint.cs b/DirectX12GameEngine.Input/PointerPoint.cs new file mode 100644 index 0000000..3619a40 --- /dev/null +++ b/DirectX12GameEngine.Input/PointerPoint.cs @@ -0,0 +1,15 @@ +using System.Numerics; + +namespace DirectX12GameEngine.Input +{ + public abstract class PointerPoint + { + public abstract bool IsInContact { get; } + + public abstract uint PointerId { get; } + + public abstract Vector2 Position { get; } + + public abstract PointerPointProperties Properties { get; } + } +} diff --git a/DirectX12GameEngine.Input/PointerPointProperties.cs b/DirectX12GameEngine.Input/PointerPointProperties.cs new file mode 100644 index 0000000..85ba289 --- /dev/null +++ b/DirectX12GameEngine.Input/PointerPointProperties.cs @@ -0,0 +1,56 @@ +using System.Drawing; +using System.Numerics; + +namespace DirectX12GameEngine.Input +{ + public abstract class PointerPointProperties + { + public abstract RectangleF ContactRect { get; } + + public abstract RectangleF ContactRectRaw { get; } + + public abstract bool IsBarrelButtonPressed { get; } + + public abstract bool IsCanceled { get; } + + public abstract bool IsEraser { get; } + + public abstract bool IsHorizontalMouseWheel { get; } + + public abstract bool IsInRange { get; } + + public abstract bool IsInverted { get; } + + public abstract bool IsLeftButtonPressed { get; } + + public abstract bool IsMiddleButtonPressed { get; } + + public abstract bool IsPrimary { get; } + + public abstract bool IsRightButtonPressed { get; } + + public abstract bool IsXButton1Pressed { get; } + + public abstract bool IsXButton2Pressed { get; } + + public abstract int MouseWheelDelta { get; } + + public abstract float Orientation { get; } + + public abstract PointerUpdateKind PointerUpdateKind { get; } + + public abstract float Pressure { get; } + + public abstract Vector2 Tilt { get; } + + public abstract bool TouchConfidence { get; } + + public abstract float Twist { get; } + + public abstract float? ZDistance { get; } + + public abstract bool HasUsage(uint usagePage, uint usageId); + + public abstract int GetUsageValue(uint usagePage, uint usageId); + } +} diff --git a/DirectX12GameEngine.Input/PointerUpdateKind.cs b/DirectX12GameEngine.Input/PointerUpdateKind.cs new file mode 100644 index 0000000..269bf40 --- /dev/null +++ b/DirectX12GameEngine.Input/PointerUpdateKind.cs @@ -0,0 +1,17 @@ +namespace DirectX12GameEngine.Input +{ + public enum PointerUpdateKind + { + Other = 0, + LeftButtonPressed = 1, + LeftButtonReleased = 2, + RightButtonPressed = 3, + RightButtonReleased = 4, + MiddleButtonPressed = 5, + MiddleButtonReleased = 6, + XButton1Pressed = 7, + XButton1Released = 8, + XButton2Pressed = 9, + XButton2Released = 10 + } +} diff --git a/DirectX12GameEngine.Input/Uwp/UwpGamepad.cs b/DirectX12GameEngine.Input/Uwp/UwpGamepad.cs new file mode 100644 index 0000000..7c18dd9 --- /dev/null +++ b/DirectX12GameEngine.Input/Uwp/UwpGamepad.cs @@ -0,0 +1,103 @@ +using System; +using System.Numerics; +using Windows.Gaming.Input; + +namespace DirectX12GameEngine.Input +{ + public class UwpGamepad : GamepadDeviceBase + { + private readonly Gamepad gamepad; + private GamepadReading currentReading; + + public UwpGamepad(Gamepad gamepad) + { + this.gamepad = gamepad; + } + + public override bool IsWireless => gamepad.IsWireless; + + public override GamepadVibration Vibration + { + get => ToVibration(gamepad.Vibration); + set => gamepad.Vibration = ToVibration(value); + } + + public override GamepadReading CurrentReading => currentReading; + + public override BatteryReport TryGetBatteryReport() + { + return new UwpBatteryReport(gamepad.TryGetBatteryReport()); + } + + public override void Update() + { + GamepadReading oldReading = currentReading; + GamepadReading newReading = GetCurrentReading(); + + currentReading = newReading; + + ClearButtonStates(); + + foreach (GamepadButtons button in Enum.GetValues(typeof(GamepadButtons))) + { + bool oldState = oldReading.Buttons.HasFlag(button); + bool newState = newReading.Buttons.HasFlag(button); + + if (oldState != newState) + { + UpdateButtonState(button, newState); + } + } + } + + private GamepadReading GetCurrentReading() + { + Windows.Gaming.Input.GamepadReading reading = gamepad.GetCurrentReading(); + + return new GamepadReading + { + Buttons = (GamepadButtons)reading.Buttons, + LeftThumbstick = new Vector2((float)reading.LeftThumbstickX, (float)reading.LeftThumbstickY), + RightThumbstick = new Vector2((float)reading.RightThumbstickX, (float)reading.RightThumbstickY), + LeftTrigger = (float)reading.LeftTrigger, + RightTrigger = (float)reading.RightTrigger, + }; + } + + public GamepadVibration ToVibration(in Windows.Gaming.Input.GamepadVibration vibration) => new GamepadVibration + { + LeftMotor = vibration.LeftMotor, + LeftTrigger = vibration.LeftTrigger, + RightMotor = vibration.RightMotor, + RightTrigger = vibration.RightTrigger + }; + + private Windows.Gaming.Input.GamepadVibration ToVibration(in GamepadVibration vibration) => new Windows.Gaming.Input.GamepadVibration + { + LeftMotor = vibration.LeftMotor, + LeftTrigger = vibration.LeftTrigger, + RightMotor = vibration.RightMotor, + RightTrigger = vibration.RightTrigger + }; + + private class UwpBatteryReport : BatteryReport + { + private readonly Windows.Devices.Power.BatteryReport batteryReport; + + public UwpBatteryReport(Windows.Devices.Power.BatteryReport batteryReport) + { + this.batteryReport = batteryReport; + } + + public override int? ChargeRateInMilliwatts => batteryReport.ChargeRateInMilliwatts; + + public override int? DesignCapacityInMilliwattHours => batteryReport.DesignCapacityInMilliwattHours; + + public override int? FullChargeCapacityInMilliwattHours => batteryReport.FullChargeCapacityInMilliwattHours; + + public override int? RemainingCapacityInMilliwattHours => batteryReport.RemainingCapacityInMilliwattHours; + + public override BatteryStatus Status => (BatteryStatus)batteryReport.Status; + } + } +} diff --git a/DirectX12GameEngine.Input/Uwp/UwpGamepadInputSource.cs b/DirectX12GameEngine.Input/Uwp/UwpGamepadInputSource.cs new file mode 100644 index 0000000..904e1b0 --- /dev/null +++ b/DirectX12GameEngine.Input/Uwp/UwpGamepadInputSource.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using Windows.Gaming.Input; + +namespace DirectX12GameEngine.Input +{ + public class UwpGamepadInputSource : GamepadInputSourceBase + { + private readonly Dictionary gamepads = new Dictionary(); + + public UwpGamepadInputSource() + { + Gamepad.GamepadAdded += OnGamepadAdded; + Gamepad.GamepadRemoved += OnGamepadRemoved; + + Scan(); + } + + public override void Dispose() + { + base.Dispose(); + + Gamepad.GamepadAdded -= OnGamepadAdded; + Gamepad.GamepadRemoved -= OnGamepadRemoved; + } + + public override void Scan() + { + base.Scan(); + + foreach (Gamepad gamepad in Gamepad.Gamepads) + { + OnGamepadAdded(this, gamepad); + } + } + + private void OnGamepadAdded(object sender, Gamepad gamepad) + { + if (!gamepads.ContainsKey(gamepad)) + { + UwpGamepad newGamepad = new UwpGamepad(gamepad); + gamepads.Add(gamepad, newGamepad); + Gamepads.Add(newGamepad); + } + } + + private void OnGamepadRemoved(object sender, Gamepad gamepad) + { + if (gamepads.TryGetValue(gamepad, out UwpGamepad currentGamepad)) + { + gamepads.Remove(gamepad); + Gamepads.Remove(currentGamepad); + } + } + } +} diff --git a/DirectX12GameEngine.Input/Uwp/UwpPointerPoint.cs b/DirectX12GameEngine.Input/Uwp/UwpPointerPoint.cs new file mode 100644 index 0000000..bfcdeeb --- /dev/null +++ b/DirectX12GameEngine.Input/Uwp/UwpPointerPoint.cs @@ -0,0 +1,22 @@ +using System.Numerics; + +namespace DirectX12GameEngine.Input +{ + internal class UwpPointerPoint : PointerPoint + { + private readonly Windows.UI.Input.PointerPoint pointerPoint; + + public UwpPointerPoint(Windows.UI.Input.PointerPoint pointerPoint) + { + this.pointerPoint = pointerPoint; + } + + public override bool IsInContact => pointerPoint.IsInContact; + + public override uint PointerId => pointerPoint.PointerId; + + public override Vector2 Position => new Vector2((float)pointerPoint.Position.X, (float)pointerPoint.Position.Y); + + public override PointerPointProperties Properties => new UwpPointerPointProperties(pointerPoint.Properties); + } +} diff --git a/DirectX12GameEngine.Input/Uwp/UwpPointerPointProperties.cs b/DirectX12GameEngine.Input/Uwp/UwpPointerPointProperties.cs new file mode 100644 index 0000000..60e16e1 --- /dev/null +++ b/DirectX12GameEngine.Input/Uwp/UwpPointerPointProperties.cs @@ -0,0 +1,63 @@ +using System.Drawing; +using System.Numerics; + +namespace DirectX12GameEngine.Input +{ + internal class UwpPointerPointProperties : PointerPointProperties + { + private readonly Windows.UI.Input.PointerPointProperties properties; + + public UwpPointerPointProperties(Windows.UI.Input.PointerPointProperties properties) + { + this.properties = properties; + } + + public override RectangleF ContactRect => new RectangleF((float)properties.ContactRect.X, (float)properties.ContactRect.Y, (float)properties.ContactRect.Width, (float)properties.ContactRect.Height); + + public override RectangleF ContactRectRaw => new RectangleF((float)properties.ContactRect.X, (float)properties.ContactRect.Y, (float)properties.ContactRect.Width, (float)properties.ContactRect.Height); + + public override bool IsBarrelButtonPressed => properties.IsBarrelButtonPressed; + + public override bool IsCanceled => properties.IsCanceled; + + public override bool IsEraser => properties.IsEraser; + + public override bool IsHorizontalMouseWheel => properties.IsHorizontalMouseWheel; + + public override bool IsInRange => properties.IsInRange; + + public override bool IsInverted => properties.IsInverted; + + public override bool IsLeftButtonPressed => properties.IsLeftButtonPressed; + + public override bool IsMiddleButtonPressed => properties.IsMiddleButtonPressed; + + public override bool IsPrimary => properties.IsPrimary; + + public override bool IsRightButtonPressed => properties.IsRightButtonPressed; + + public override bool IsXButton1Pressed => properties.IsXButton1Pressed; + + public override bool IsXButton2Pressed => properties.IsXButton2Pressed; + + public override int MouseWheelDelta => properties.MouseWheelDelta; + + public override float Orientation => properties.Orientation; + + public override PointerUpdateKind PointerUpdateKind => (PointerUpdateKind)properties.PointerUpdateKind; + + public override float Pressure => properties.Pressure; + + public override Vector2 Tilt => new Vector2(properties.XTilt, properties.YTilt); + + public override bool TouchConfidence => properties.TouchConfidence; + + public override float Twist => properties.Twist; + + public override float? ZDistance => properties.ZDistance; + + public override int GetUsageValue(uint usagePage, uint usageId) => properties.GetUsageValue(usagePage, usageId); + + public override bool HasUsage(uint usagePage, uint usageId) => properties.HasUsage(usagePage, usageId); + } +} diff --git a/DirectX12GameEngine.Input/VirtualKey.cs b/DirectX12GameEngine.Input/VirtualKey.cs new file mode 100644 index 0000000..8d844e7 --- /dev/null +++ b/DirectX12GameEngine.Input/VirtualKey.cs @@ -0,0 +1,176 @@ +namespace DirectX12GameEngine.Input +{ + public enum VirtualKey + { + None = 0, + LeftButton = 1, + RightButton = 2, + Cancel = 3, + MiddleButton = 4, + XButton1 = 5, + XButton2 = 6, + Back = 8, + Tab = 9, + Clear = 12, + Enter = 13, + Shift = 16, + Control = 17, + Menu = 18, + Pause = 19, + CapitalLock = 20, + Kana = 21, + Hangul = 21, + Junja = 23, + Final = 24, + Hanja = 25, + Kanji = 25, + Escape = 27, + Convert = 28, + NonConvert = 29, + Accept = 30, + ModeChange = 31, + Space = 32, + PageUp = 33, + PageDown = 34, + End = 35, + Home = 36, + Left = 37, + Up = 38, + Right = 39, + Down = 40, + Select = 41, + Print = 42, + Execute = 43, + Snapshot = 44, + Insert = 45, + Delete = 46, + Help = 47, + Number0 = 48, + Number1 = 49, + Number2 = 50, + Number3 = 51, + Number4 = 52, + Number5 = 53, + Number6 = 54, + Number7 = 55, + Number8 = 56, + Number9 = 57, + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + LeftWindows = 91, + RightWindows = 92, + Application = 93, + Sleep = 95, + NumberPad0 = 96, + NumberPad1 = 97, + NumberPad2 = 98, + NumberPad3 = 99, + NumberPad4 = 100, + NumberPad5 = 101, + NumberPad6 = 102, + NumberPad7 = 103, + NumberPad8 = 104, + NumberPad9 = 105, + Multiply = 106, + Add = 107, + Separator = 108, + Subtract = 109, + Decimal = 110, + Divide = 111, + F1 = 112, + F2 = 113, + F3 = 114, + F4 = 115, + F5 = 116, + F6 = 117, + F7 = 118, + F8 = 119, + F9 = 120, + F10 = 121, + F11 = 122, + F12 = 123, + F13 = 124, + F14 = 125, + F15 = 126, + F16 = 127, + F17 = 128, + F18 = 129, + F19 = 130, + F20 = 131, + F21 = 132, + F22 = 133, + F23 = 134, + F24 = 135, + NavigationView = 136, + NavigationMenu = 137, + NavigationUp = 138, + NavigationDown = 139, + NavigationLeft = 140, + NavigationRight = 141, + NavigationAccept = 142, + NavigationCancel = 143, + NumberKeyLock = 144, + Scroll = 145, + LeftShift = 160, + RightShift = 161, + LeftControl = 162, + RightControl = 163, + LeftMenu = 164, + RightMenu = 165, + GoBack = 166, + GoForward = 167, + Refresh = 168, + Stop = 169, + Search = 170, + Favorites = 171, + GoHome = 172, + GamepadA = 195, + GamepadB = 196, + GamepadX = 197, + GamepadY = 198, + GamepadRightShoulder = 199, + GamepadLeftShoulder = 200, + GamepadLeftTrigger = 201, + GamepadRightTrigger = 202, + GamepadDPadUp = 203, + GamepadDPadDown = 204, + GamepadDPadLeft = 205, + GamepadDPadRight = 206, + GamepadMenu = 207, + GamepadView = 208, + GamepadLeftThumbstickButton = 209, + GamepadRightThumbstickButton = 210, + GamepadLeftThumbstickUp = 211, + GamepadLeftThumbstickDown = 212, + GamepadLeftThumbstickRight = 213, + GamepadLeftThumbstickLeft = 214, + GamepadRightThumbstickUp = 215, + GamepadRightThumbstickDown = 216, + GamepadRightThumbstickRight = 217, + GamepadRightThumbstickLeft = 218 + } +} diff --git a/DirectX12GameEngine.Input/VirtualKeyModifiers.cs b/DirectX12GameEngine.Input/VirtualKeyModifiers.cs new file mode 100644 index 0000000..b4d841c --- /dev/null +++ b/DirectX12GameEngine.Input/VirtualKeyModifiers.cs @@ -0,0 +1,14 @@ +using System; + +namespace DirectX12GameEngine.Input +{ + [Flags] + public enum VirtualKeyModifiers : uint + { + None = 0, + Control = 1, + Menu = 2, + Shift = 4, + Windows = 8 + } +} diff --git a/DirectX12GameEngine.Input/WinForms/WinFormsInputSourceConfiguration.cs b/DirectX12GameEngine.Input/WinForms/WinFormsInputSourceConfiguration.cs new file mode 100644 index 0000000..76560bd --- /dev/null +++ b/DirectX12GameEngine.Input/WinForms/WinFormsInputSourceConfiguration.cs @@ -0,0 +1,21 @@ +#if NETCOREAPP +using System.Collections.Generic; +using System.Windows.Forms; + +namespace DirectX12GameEngine.Input +{ + public class WinFormsInputSourceConfiguration : IInputSourceConfiguration + { + public WinFormsInputSourceConfiguration(Control control) + { + UwpGamepadInputSource gamepadSource = new UwpGamepadInputSource(); + Sources.Add(gamepadSource); + + WinFormsKeyboard keyboard = new WinFormsKeyboard(control); + Sources.Add(keyboard); + } + + public IList Sources { get; } = new List(); + } +} +#endif diff --git a/DirectX12GameEngine.Input/WinForms/WinFormsKeyboardInputSource.cs b/DirectX12GameEngine.Input/WinForms/WinFormsKeyboardInputSource.cs new file mode 100644 index 0000000..ff0735d --- /dev/null +++ b/DirectX12GameEngine.Input/WinForms/WinFormsKeyboardInputSource.cs @@ -0,0 +1,49 @@ +#if NETCOREAPP +using System.Windows.Forms; + +namespace DirectX12GameEngine.Input +{ + public class WinFormsKeyboard : KeyboardInputSourceBase + { + private readonly Control control; + + public WinFormsKeyboard(Control control) + { + this.control = control; + + control.KeyDown += Control_KeyDown; + control.KeyUp += Control_KeyUp; + } + + public override void Dispose() + { + control.KeyDown -= Control_KeyDown; + control.KeyUp -= Control_KeyUp; + } + + private void Control_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) + { + OnKeyDown(new WinFormsKeyEventArgs(e)); + } + + private void Control_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) + { + OnKeyUp(new WinFormsKeyEventArgs(e)); + } + + private class WinFormsKeyEventArgs : KeyEventArgs + { + private readonly System.Windows.Forms.KeyEventArgs args; + + public WinFormsKeyEventArgs(System.Windows.Forms.KeyEventArgs args) + { + this.args = args; + } + + public override bool Handled { get => args.Handled; set => args.Handled = value; } + + public override VirtualKey Key => (VirtualKey)args.KeyCode; + } + } +} +#endif diff --git a/DirectX12GameEngine.Input/Xaml/XamlInputSourceConfiguration.cs b/DirectX12GameEngine.Input/Xaml/XamlInputSourceConfiguration.cs new file mode 100644 index 0000000..469ebcc --- /dev/null +++ b/DirectX12GameEngine.Input/Xaml/XamlInputSourceConfiguration.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Windows.UI.Xaml; + +namespace DirectX12GameEngine.Input +{ + public class XamlInputSourceConfiguration : IInputSourceConfiguration + { + public XamlInputSourceConfiguration(UIElement uiElement) + { + UwpGamepadInputSource gamepadSource = new UwpGamepadInputSource(); + Sources.Add(gamepadSource); + + XamlKeyboardInputSource keyboardSource = new XamlKeyboardInputSource(uiElement); + Sources.Add(keyboardSource); + + XamlPointerInputSource pointerSource = new XamlPointerInputSource(uiElement); + Sources.Add(pointerSource); + } + + public IList Sources { get; } = new List(); + } +} diff --git a/DirectX12GameEngine.Input/Xaml/XamlKeyboardInputSource.cs b/DirectX12GameEngine.Input/Xaml/XamlKeyboardInputSource.cs new file mode 100644 index 0000000..312e2e3 --- /dev/null +++ b/DirectX12GameEngine.Input/Xaml/XamlKeyboardInputSource.cs @@ -0,0 +1,48 @@ +using Windows.UI.Xaml; +using Windows.UI.Xaml.Input; + +namespace DirectX12GameEngine.Input +{ + public class XamlKeyboardInputSource : KeyboardInputSourceBase + { + private readonly UIElement control; + + public XamlKeyboardInputSource(UIElement uiElement) + { + control = uiElement; + + control.KeyDown += Control_KeyDown; + control.KeyUp += Control_KeyUp; + } + + public override void Dispose() + { + control.KeyDown -= Control_KeyDown; + control.KeyUp -= Control_KeyUp; + } + + private void Control_KeyDown(object sender, KeyRoutedEventArgs e) + { + OnKeyDown(new XamlKeyEventArgs(e)); + } + + private void Control_KeyUp(object sender, KeyRoutedEventArgs e) + { + OnKeyUp(new XamlKeyEventArgs(e)); + } + + private class XamlKeyEventArgs : KeyEventArgs + { + private readonly KeyRoutedEventArgs args; + + public XamlKeyEventArgs(KeyRoutedEventArgs args) + { + this.args = args; + } + + public override bool Handled { get => args.Handled; set => args.Handled = value; } + + public override VirtualKey Key => (VirtualKey)args.Key; + } + } +} diff --git a/DirectX12GameEngine.Input/Xaml/XamlPointerInputSource.cs b/DirectX12GameEngine.Input/Xaml/XamlPointerInputSource.cs new file mode 100644 index 0000000..c31f26d --- /dev/null +++ b/DirectX12GameEngine.Input/Xaml/XamlPointerInputSource.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Input; + +namespace DirectX12GameEngine.Input +{ + public class XamlPointerInputSource : PointerInputSourceBase + { + private readonly UIElement control; + + public XamlPointerInputSource(UIElement uiElement) + { + control = uiElement; + + control.PointerCaptureLost += Control_PointerCaptureLost; + control.PointerEntered += Control_PointerEntered; + control.PointerExited += Control_PointerExited; + control.PointerMoved += Control_PointerMoved; + control.PointerPressed += Control_PointerPressed; + control.PointerReleased += Control_PointerReleased; + control.PointerWheelChanged += Control_PointerWheelChanged; + } + + public override bool HasCapture => true; + + public override bool IsInputEnabled { get => control.IsHitTestVisible; set => control.IsHitTestVisible = value; } + + public override Cursor PointerCursor + { + get => new Cursor((CursorType)Window.Current.CoreWindow.PointerCursor.Type, Window.Current.CoreWindow.PointerCursor.Id); + set => Window.Current.CoreWindow.PointerCursor = new CoreCursor((CoreCursorType)value.Type, value.Id); + } + + public override Vector2 PointerPosition { get; } + + public override void ReleasePointerCapture() + { + throw new System.NotImplementedException(); + } + + public override void SetPointerCapture() + { + throw new System.NotImplementedException(); + } + + private void Control_PointerCaptureLost(object sender, PointerRoutedEventArgs e) + { + OnPointerCaptureLost(new XamlPointerEventArgs(e, control)); + } + + private void Control_PointerEntered(object sender, PointerRoutedEventArgs e) + { + OnPointerEntered(new XamlPointerEventArgs(e, control)); + } + + private void Control_PointerExited(object sender, PointerRoutedEventArgs e) + { + OnPointerExited(new XamlPointerEventArgs(e, control)); + } + + private void Control_PointerMoved(object sender, PointerRoutedEventArgs e) + { + OnPointerMoved(new XamlPointerEventArgs(e, control)); + } + + private void Control_PointerPressed(object sender, PointerRoutedEventArgs e) + { + OnPointerPressed(new XamlPointerEventArgs(e, control)); + } + + private void Control_PointerReleased(object sender, PointerRoutedEventArgs e) + { + OnPointerReleased(new XamlPointerEventArgs(e, control)); + } + + private void Control_PointerWheelChanged(object sender, PointerRoutedEventArgs e) + { + OnPointerWheelChanged(new XamlPointerEventArgs(e, control)); + } + + private class XamlPointerEventArgs : PointerEventArgs + { + private readonly PointerRoutedEventArgs args; + private readonly UIElement control; + + public XamlPointerEventArgs(PointerRoutedEventArgs args, UIElement uiElement) + { + this.args = args; + control = uiElement; + } + + public override bool Handled { get => args.Handled; set => args.Handled = value; } + + public override PointerPoint CurrentPoint => new UwpPointerPoint(args.GetCurrentPoint(control)); + + public override VirtualKeyModifiers KeyModifiers => (VirtualKeyModifiers)args.KeyModifiers; + + public override IList GetIntermediatePoints() => args.GetIntermediatePoints(control).Select(p => new UwpPointerPoint(p)).ToArray(); + } + } +} diff --git a/DirectX12GameEngine.Rendering/DirectX12GameEngine.Rendering.csproj b/DirectX12GameEngine.Rendering/DirectX12GameEngine.Rendering.csproj index 0e5ea75..47c2d52 100644 --- a/DirectX12GameEngine.Rendering/DirectX12GameEngine.Rendering.csproj +++ b/DirectX12GameEngine.Rendering/DirectX12GameEngine.Rendering.csproj @@ -3,7 +3,7 @@ netstandard2.0 8.0 - enable + enable true diff --git a/DirectX12GameEngine.Shaders/DirectX12GameEngine.Shaders.csproj b/DirectX12GameEngine.Shaders/DirectX12GameEngine.Shaders.csproj index 7784dae..6045217 100644 --- a/DirectX12GameEngine.Shaders/DirectX12GameEngine.Shaders.csproj +++ b/DirectX12GameEngine.Shaders/DirectX12GameEngine.Shaders.csproj @@ -3,7 +3,7 @@ netstandard2.0 8.0 - enable + enable true diff --git a/DirectX12GameEngine.sln b/DirectX12GameEngine.sln index 0993bea..e470ab5 100644 --- a/DirectX12GameEngine.sln +++ b/DirectX12GameEngine.sln @@ -31,6 +31,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DirectX12GameEngine.Assets" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DirectX12GameEngine.Editor", "DirectX12GameEngine.Editor\DirectX12GameEngine.Editor.csproj", "{D1F2CBF7-6205-4A81-9262-06B2B747D05B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DirectX12GameEngine.Input", "DirectX12GameEngine.Input\DirectX12GameEngine.Input.csproj", "{DB93C2C6-419A-4D51-AD9A-12556771C28D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -341,6 +343,26 @@ Global {D1F2CBF7-6205-4A81-9262-06B2B747D05B}.Release|x86.ActiveCfg = Release|x86 {D1F2CBF7-6205-4A81-9262-06B2B747D05B}.Release|x86.Build.0 = Release|x86 {D1F2CBF7-6205-4A81-9262-06B2B747D05B}.Release|x86.Deploy.0 = Release|x86 + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|ARM.ActiveCfg = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|ARM.Build.0 = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|ARM64.Build.0 = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|x64.ActiveCfg = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|x64.Build.0 = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|x86.ActiveCfg = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Debug|x86.Build.0 = Debug|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|Any CPU.Build.0 = Release|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|ARM.ActiveCfg = Release|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|ARM.Build.0 = Release|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|ARM64.ActiveCfg = Release|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|ARM64.Build.0 = Release|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|x64.ActiveCfg = Release|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|x64.Build.0 = Release|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|x86.ActiveCfg = Release|Any CPU + {DB93C2C6-419A-4D51-AD9A-12556771C28D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/DirectX12WinFormsApp/DirectX12WinFormsApp.csproj b/DirectX12WinFormsApp/DirectX12WinFormsApp.csproj index c1a5d83..fb0a503 100644 --- a/DirectX12WinFormsApp/DirectX12WinFormsApp.csproj +++ b/DirectX12WinFormsApp/DirectX12WinFormsApp.csproj @@ -5,7 +5,7 @@ netcoreapp3.0 true 8.0 - enable + enable