diff --git a/NativeUI.dll b/NativeUI.dll index 9cbf7231..5b866a7c 100644 Binary files a/NativeUI.dll and b/NativeUI.dll differ diff --git a/vMenu/MainMenu.cs b/vMenu/MainMenu.cs index afe2ce6a..d0408449 100644 --- a/vMenu/MainMenu.cs +++ b/vMenu/MainMenu.cs @@ -76,7 +76,8 @@ public MainMenu() else { Tick += OnTick; - Tick += ProcessMenus; + Tick += ProcessMainButtons; + Tick += ProcessDirectionalButtons; } } @@ -101,7 +102,11 @@ public static void SetPermissions(dynamic dict) permissionsSetupDone = true; } #endregion - + #region set settings + /// + /// Sets the settings received from the server. + /// + /// public static void SetOptions(dynamic options) { MenuOptions = new Dictionary(); @@ -116,19 +121,196 @@ public static void SetOptions(dynamic options) MenuToggleKey = int.Parse(MenuOptions["menuKey"].ToString()); optionsSetupDone = true; } + #endregion + #region Process Menu Buttons /// - /// This has to be separated from the "draw" function to fix the fast scrolling bug. + /// Process the select & go back/cancel buttons. /// /// - private async Task ProcessMenus() + private async Task ProcessMainButtons() { - await Mp.ProcessControlAsync(); - Mp.WidthOffset = 50; + UIMenu currentMenu = Cf.GetOpenMenu(); + if (currentMenu != null) + { + // Select / Enter + if (Game.IsDisabledControlJustReleased(0, Control.FrontendAccept) || Game.IsControlJustReleased(0, Control.FrontendAccept)) + { + currentMenu.SelectItem(); + if (DebugMode) + { + Subtitle.Custom("select"); + } + } + // Cancel / Go Back + else if (Game.IsDisabledControlJustReleased(0, Control.PhoneCancel)) + { + // Wait for the next frame to make sure the "cinematic camera" button doesn't get "re-enabled" before the menu gets closed. + await Delay(0); + currentMenu.GoBack(); + if (DebugMode) + { + + Subtitle.Custom("cancel"); + } + } + } + else + { + await Delay(0); + } } /// - /// OnTick runs every game tick. + /// Process left/right/up/down buttons (also holding down buttons will speed up after 3 iterations) + /// + /// + private async Task ProcessDirectionalButtons() + { + // Get the currently open menu. + UIMenu currentMenu = Cf.GetOpenMenu(); + // If it exists. + if (currentMenu != null) + { + // Check if the Go Up controls are pressed. + if (Game.IsDisabledControlJustPressed(0, Control.Phone) || Game.IsControlJustPressed(0, Control.SniperZoomInSecondary)) + { + // Update the currently selected item to the new one. + currentMenu.GoUp(); + currentMenu.GoUpOverflow(); + + // Get the current game time. + var time = GetGameTimer(); + var times = 0; + var delay = 200; + + // Do the following as long as the controls are being pressed. + while (Game.IsDisabledControlPressed(0, Control.Phone) && Cf.GetOpenMenu() != null) + { + // Update the current menu. + currentMenu = Cf.GetOpenMenu(); + + // Check if the game time has changed by "delay" amount. + if (GetGameTimer() - time > delay) + { + // Increment the "changed indexes" counter + times++; + + // If the controls are still being held down after moving 3 indexes, reduce the delay between index changes. + if (times > 2) + { + delay = 150; + } + + // Update the currently selected item to the new one. + currentMenu.GoUp(); + currentMenu.GoUpOverflow(); + + // Reset the time to the current game timer. + time = GetGameTimer(); + } + + // Wait for the next game tick. + await Delay(0); + } + // If debugging is enabled, a subtitle will be shown when this control is pressed. + if (DebugMode) + { + Subtitle.Custom("up"); + } + } + + // Check if the Go Left controls are pressed. + else if (Game.IsDisabledControlJustPressed(0, Control.PhoneLeft)) + { + currentMenu.GoLeft(); + var time = GetGameTimer(); + var times = 0; + var delay = 200; + while (Game.IsDisabledControlPressed(0, Control.PhoneLeft) && Cf.GetOpenMenu() != null) + { + currentMenu = Cf.GetOpenMenu(); + if (GetGameTimer() - time > delay) + { + times++; + if (times > 2) + { + delay = 150; + } + currentMenu.GoLeft(); + time = GetGameTimer(); + } + await Delay(0); + } + if (DebugMode) + { + Subtitle.Custom("left"); + } + } + + // Check if the Go Right controls are pressed. + else if (Game.IsDisabledControlJustPressed(0, Control.PhoneRight)) + { + currentMenu.GoRight(); + var time = GetGameTimer(); + var times = 0; + var delay = 200; + while (Game.IsDisabledControlPressed(0, Control.PhoneRight) && Cf.GetOpenMenu() != null) + { + currentMenu = Cf.GetOpenMenu(); + if (GetGameTimer() - time > delay) + { + times++; + if (times > 2) + { + delay = 150; + } + currentMenu.GoRight(); + time = GetGameTimer(); + } + await Delay(0); + } + if (DebugMode) + { + Subtitle.Custom("right"); + } + } + + // Check if the Go Down controls are pressed. + else if (Game.IsDisabledControlJustPressed(0, Control.PhoneDown) || Game.IsControlJustPressed(0, Control.SniperZoomOutSecondary)) + { + currentMenu.GoDown(); + currentMenu.GoDownOverflow(); + var time = GetGameTimer(); + var times = 0; + var delay = 200; + while (Game.IsDisabledControlPressed(0, Control.PhoneDown) && Cf.GetOpenMenu() != null) + { + currentMenu = Cf.GetOpenMenu(); + if (GetGameTimer() - time > delay) + { + times++; + if (times > 2) + { + delay = 150; + } + currentMenu.GoDown(); + currentMenu.GoDownOverflow(); + time = GetGameTimer(); + } + await Delay(0); + } + if (DebugMode) + { + Subtitle.Custom("down"); + } + } + } + } + #endregion + + /// + /// Main OnTick task runs every game tick and handles all the menu stuff. /// /// private async Task OnTick() @@ -171,7 +353,7 @@ private async Task OnTick() #endregion // If the setup (permissions) is done, and it's not the first tick, then do this: - if (permissionsSetupDone && !firstTick) + if (permissionsSetupDone && optionsSetupDone && !firstTick) { #region Handle Opening/Closing of the menu. // If menus can be opened. @@ -196,25 +378,23 @@ private async Task OnTick() else if (!Mp.IsAnyMenuOpen() && Game.CurrentInputMode == InputMode.GamePad) { // Create a timer and set it to 0. - float timer = 0f; + //float timer = 0f; + int timer = GetGameTimer(); // While (and only if) the player keeps using only the controller, and keeps holding down the interactionmenu button (select on controller). while (Game.CurrentInputMode == InputMode.GamePad && Game.IsControlPressed(0, Control.InteractionMenu)) { - // Increment the timer. - timer++; - // If debugging is enabled, show the progress using a timerbar. if (DebugMode) { bt.Draw(0); - float percent = (timer / 60f); + float percent = ((GetGameTimer() - timer) / 900f); bt.Percentage = percent; - Subtitle.Success(percent.ToString(), 0, true, "Progress:"); + //Subtitle.Success(percent.ToString(), 0, true, "Progress:"); } - // If the timer has reached 60, open the menu. (60 is +/- 1 second, so the player is holding down the button for at least 1 second). - if (timer > 59) + // If 900ms in real time have passed. + if (GetGameTimer() - timer > 900) { Menu.Visible = !Mp.IsAnyMenuOpen(); // Break the loop (resetting the timer). @@ -288,7 +468,7 @@ private async Task OnTick() Game.DisableControlThisFrame(0, (Control)MenuToggleKey); // When in a vehicle - if (IsPedInAnyVehicle(PlayerPedId(), false)) + //if (IsPedInAnyVehicle(PlayerPedId(), false)) { Game.DisableControlThisFrame(0, Control.VehicleSelectNextWeapon); Game.DisableControlThisFrame(0, Control.VehicleSelectPrevWeapon); @@ -296,12 +476,13 @@ private async Task OnTick() } } #endregion - // Only draw the menu each frame, control handling is done in another Tick task because that needs delays. + + // Process the menu. Draw it and reset the menu width offset to make sure any newly generated menus always have the right width offset. + Mp.WidthOffset = 50; Mp.Draw(); } } - #region Add Menu Function /// /// Add the menu to the menu pool and set it up correctly.