diff --git a/Engine b/Engine index efed24d..a4b8367 160000 --- a/Engine +++ b/Engine @@ -1 +1 @@ -Subproject commit efed24de2011eb9aad6fbeac38697eb9a7c37e3f +Subproject commit a4b83679b1c45313b57a7a2581547aacf9f3064f diff --git a/Platforms/Android/.config/dotnet-tools.json b/Platforms/Android/.config/dotnet-tools.json new file mode 100644 index 0000000..efabe22 --- /dev/null +++ b/Platforms/Android/.config/dotnet-tools.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-mgcb": { + "version": "3.8.1.303", + "commands": [ + "mgcb" + ] + }, + "dotnet-mgcb-editor": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor" + ] + }, + "dotnet-mgcb-editor-linux": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-linux" + ] + }, + "dotnet-mgcb-editor-windows": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-windows" + ] + }, + "dotnet-mgcb-editor-mac": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-mac" + ] + } + } +} \ No newline at end of file diff --git a/Platforms/Android/Android.csproj b/Platforms/Android/Android.csproj new file mode 100644 index 0000000..845b1c5 --- /dev/null +++ b/Platforms/Android/Android.csproj @@ -0,0 +1,42 @@ + + + + net9.0-android + 23 + Exe + com.MyCompany.MyGame + 1 + 1.0 + true + true + + + + + + + + + + Content/Content.mgcb + + + + + + + + + + + + + + + + + + diff --git a/Platforms/Android/AndroidManifest.xml b/Platforms/Android/AndroidManifest.xml new file mode 100644 index 0000000..e22c6dc --- /dev/null +++ b/Platforms/Android/AndroidManifest.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/Platforms/Android/MobileInputs.cs b/Platforms/Android/MobileInputs.cs new file mode 100644 index 0000000..9055ffc --- /dev/null +++ b/Platforms/Android/MobileInputs.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; + +using Microsoft.Xna.Framework.Input.Touch; + +using Engine.Core; +using Engine.Systems.Input; + +using MyUniverse.Shared.Behaviours.Abstract; + +namespace MyUniverse.Platforms.Android; + +public class MobileInputs : Behaviour, IUpdate, IGameInputs +{ + public Event, IButtonInputs.ButtonCallbackArguments> OnAnyButtonPressed { get; } = new(); + public Event, IButtonInputs.ButtonCallbackArguments> OnAnyButtonReleased { get; } = new(); + + private readonly Dictionary, IButtonInputs.ButtonCallbackArguments>> OnPressed = new(256); + private readonly Dictionary, IButtonInputs.ButtonCallbackArguments>> OnReleased = new(256); + + private TouchCollection touchCollection = default; + + public void RegisterOnPress(IGameInputs.Button key, Event, IButtonInputs.ButtonCallbackArguments>.EventHandler callback) + { + if (OnPressed.TryGetValue(key, out Event, IButtonInputs.ButtonCallbackArguments> @event)) + { + @event.AddListener(callback); + return; + } + + @event = new(); + @event.AddListener(callback); + OnPressed.Add(key, @event); + } + + public void UnregisterOnPress(IGameInputs.Button key, Event, IButtonInputs.ButtonCallbackArguments>.EventHandler callback) + { + if (OnPressed.TryGetValue(key, out Event, IButtonInputs.ButtonCallbackArguments> @event)) + @event.RemoveListener(callback); + } + + public void RegisterOnRelease(IGameInputs.Button key, Event, IButtonInputs.ButtonCallbackArguments>.EventHandler callback) + { + if (OnReleased.TryGetValue(key, out Event, IButtonInputs.ButtonCallbackArguments> @event)) + { + @event.AddListener(callback); + return; + } + + @event = new(); + @event.AddListener(callback); + OnReleased.Add(key, @event); + } + + public void UnregisterOnRelease(IGameInputs.Button key, Event, IButtonInputs.ButtonCallbackArguments>.EventHandler callback) + { + if (OnReleased.TryGetValue(key, out Event, IButtonInputs.ButtonCallbackArguments> @event)) + @event.RemoveListener(callback); + } + + public void Update() + { + touchCollection = TouchPanel.GetState(); + + if (touchCollection.Count > 0) + { + TouchLocation touchLocation = touchCollection[(int)IGameInputs.Button.Interact]; + if (touchLocation.State == TouchLocationState.Pressed) + { + if (OnPressed.TryGetValue(IGameInputs.Button.Interact, out Event, IButtonInputs.ButtonCallbackArguments> @event)) + @event.Invoke(this, new(IGameInputs.Button.Interact)); + OnAnyButtonPressed?.Invoke(this, new(IGameInputs.Button.Interact)); + } + else if (touchLocation.State == TouchLocationState.Released) + { + if (OnReleased.TryGetValue(IGameInputs.Button.Interact, out Event, IButtonInputs.ButtonCallbackArguments> @event)) + @event.Invoke(this, new(IGameInputs.Button.Interact)); + OnAnyButtonReleased?.Invoke(this, new(IGameInputs.Button.Interact)); + } + } + } + + public bool IsPressed(IGameInputs.Button button) + { + if (touchCollection.Count > 0) + return false; + + TouchLocation touchLocation = touchCollection[(int)IGameInputs.Button.Interact]; + return touchLocation.State == TouchLocationState.Pressed || touchLocation.State == TouchLocationState.Moved; + } +} diff --git a/Platforms/Android/Program.cs b/Platforms/Android/Program.cs new file mode 100644 index 0000000..2fc0962 --- /dev/null +++ b/Platforms/Android/Program.cs @@ -0,0 +1,60 @@ +using Microsoft.Xna.Framework; + +using Android.App; +using Android.Content.PM; +using Android.OS; +using Android.Views; +using Engine.Integration.MonoGame; +using Engine.Core; +using Engine.Core.Debug; + +namespace MyUniverse.Platforms.Android +{ + [Activity( + Label = "@string/app_name", + MainLauncher = true, + Icon = "@drawable/icon", + AlwaysRetainTaskState = true, + LaunchMode = LaunchMode.SingleInstance, + ScreenOrientation = ScreenOrientation.Portrait, + ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize + )] + public class Program : AndroidGameActivity + { + private MonoGameWindow _game; + private View _view; + + protected override void OnCreate(Bundle bundle) + { + base.OnCreate(bundle); + + Universe universe = new(); + + ILogger logger = new RotatingFileLogger("Logs", "MyGame"); + + universe.InstantiateUniverseObject().SetUniverseObject("Logger") + .BehaviourController.AddBehaviour().Logger = ILogger.Shared = logger; + + universe.InstantiateUniverseObject().SetUniverseObject("Desktop Inputs") + .BehaviourController.AddBehaviour(); + + universe.InstantiateUniverseObject().SetUniverseObject("Visual Managers") + .BehaviourController.AddBehaviour() + .BehaviourController.AddBehaviour(); + + /* For Networking + LiteNetLibClient client = universe.InstantiateUniverseObject().SetUniverseObject("Client").BehaviourController.AddBehaviour(); + client.BehaviourController.AddBehaviour(); + universe.OnPreUpdate.AddOneTimeListener((_, _) => client.Connect("localhost", 8888)); + */ + + Shared.UniverseSource.ApplyUniverse(universe); + + _game = new MonoGameWindow(universe); + _view = _game.Services.GetService(typeof(View)) as View; + + SetContentView(_view); + _game.Run(); + } + } +} diff --git a/Platforms/Android/Resources/Drawable/Icon.png b/Platforms/Android/Resources/Drawable/Icon.png new file mode 100644 index 0000000..0e4c41c Binary files /dev/null and b/Platforms/Android/Resources/Drawable/Icon.png differ diff --git a/Platforms/Android/Resources/Values/Strings.xml b/Platforms/Android/Resources/Values/Strings.xml new file mode 100644 index 0000000..267b972 --- /dev/null +++ b/Platforms/Android/Resources/Values/Strings.xml @@ -0,0 +1,4 @@ + + + MyGame + diff --git a/Project.sln b/Project.sln index ed57f5b..72a23b9 100644 --- a/Project.sln +++ b/Project.sln @@ -29,6 +29,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Integration.Yaml", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Integration.LiteNetLib", "Engine\Engine.Integration\Engine.Integration.LiteNetLib\Engine.Integration.LiteNetLib.csproj", "{7AA22306-772F-45F4-8F30-97EBD1FC124D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Android", "Platforms\Android\Android.csproj", "{6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -159,6 +161,18 @@ Global {7AA22306-772F-45F4-8F30-97EBD1FC124D}.Release|x64.Build.0 = Release|Any CPU {7AA22306-772F-45F4-8F30-97EBD1FC124D}.Release|x86.ActiveCfg = Release|Any CPU {7AA22306-772F-45F4-8F30-97EBD1FC124D}.Release|x86.Build.0 = Release|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Debug|x64.ActiveCfg = Debug|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Debug|x64.Build.0 = Debug|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Debug|x86.ActiveCfg = Debug|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Debug|x86.Build.0 = Debug|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Release|Any CPU.Build.0 = Release|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Release|x64.ActiveCfg = Release|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Release|x64.Build.0 = Release|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Release|x86.ActiveCfg = Release|Any CPU + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -173,5 +187,6 @@ Global {7CC31BC4-38EE-40F4-BBBA-9FC2F4CF6283} = {9059393F-4073-9273-0EEC-2B1BA61B620B} {A15263DB-DF65-4A07-8CA1-33A2919501A0} = {FECFFD54-338F-4060-9161-1E5770D1DC33} {7AA22306-772F-45F4-8F30-97EBD1FC124D} = {9059393F-4073-9273-0EEC-2B1BA61B620B} + {6D4F3E3C-4E89-44A1-B6D3-03627AA8A8AF} = {FECFFD54-338F-4060-9161-1E5770D1DC33} EndGlobalSection EndGlobal