From e5df5e946c8daae51312d5936ecb718bb2105a07 Mon Sep 17 00:00:00 2001 From: oscar <29248751+oscar-wos@users.noreply.github.com> Date: Mon, 24 Jun 2024 10:16:02 +0100 Subject: [PATCH] feat: OnDrawMethod for dynamic values --- .github/workflows/dotnet.yml | 2 +- Example/Example.cs | 117 ++++++++++++++++++++++++++++++++++- src/IMenuEvent.cs | 15 +++++ src/Menu.cs | 36 ++++++++++- 4 files changed, 165 insertions(+), 5 deletions(-) create mode 100644 src/IMenuEvent.cs diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 9a8a772..d4e1191 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -57,7 +57,7 @@ jobs: - name: Extract version and create tag id: extract_version run: | - version="1.0.0" + version="1.0.1" echo "Version found: $version" git config --global user.email "actions@github.com" git config --global user.name "GitHub Actions" diff --git a/Example/Example.cs b/Example/Example.cs index 752fc84..a21e840 100644 --- a/Example/Example.cs +++ b/Example/Example.cs @@ -1,5 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; using Menu; using Menu.Enums; @@ -11,6 +12,25 @@ public class Example : BasePlugin public override string ModuleVersion => "1.0.0"; public Menu.Menu Menu { get; } = new(); + private readonly Dictionary _dynamicMenu = new(); + + public Example() + { + global::Menu.Menu.OnDrawMenu += (_, menuEvent) => + { + var controller = menuEvent.Controller; + + if (!_dynamicMenu.TryGetValue(controller, out var dynamicMenu)) + return; + + if (menuEvent.Menu != dynamicMenu) + return; + + var dynamicValue = (DynamicValue)dynamicMenu.Items[0].Head!; + dynamicValue.Position = controller.PlayerPawn.Value!.AbsOrigin!; + }; + } + public override void Load(bool isReload) { AddCommand("css_test", "", (controller, _) => @@ -109,7 +129,7 @@ public override void Load(bool isReload) break; case ButtonType.Select: - CustomSelect(controller); + CustomSelect(controller, new Vector(0, 0, 0)); break; } @@ -139,12 +159,45 @@ public override void Load(bool isReload) } }); }); + + AddCommand("css_test1", "", (controller, _) => + { + if (controller == null || !controller.IsValid) + return; + + var dynamicMenu = new MenuBase(new MenuValue("Dynamic Menu") { Prefix = "", Suffix = "" }); + + var dynamicItem = new MenuItem(MenuItemType.Text, new DynamicValue("")); + dynamicMenu.AddItem(dynamicItem); + + var saveButton = new MenuItem(MenuItemType.Button, [new MenuValue("Save")]); + dynamicMenu.AddItem(saveButton); + + _dynamicMenu[controller] = dynamicMenu; + + Menu.SetMenu(controller, dynamicMenu, (buttons, menu, _) => + { + if (buttons != MenuButtons.Select) + return; + + if (menu.Option != 0) + return; + + if (menu.Option == 0) + { + var dynamicValue = (DynamicValue)menu.Items[0].Head!; + Console.WriteLine($"{dynamicValue}"); + + CustomSelect(controller, dynamicValue.Position); + } + }); + }); } - private void CustomSelect(CCSPlayerController controller) + private void CustomSelect(CCSPlayerController controller, Vector pos) { // Since it's a sub menu setting Prefix will not affect the title as it inherits from Menu[0], Suffix will still work - var subMenu = new MenuBase(new MenuValue("Sub Menu") { Prefix = "", Suffix = "" }) ; + var subMenu = new MenuBase(new MenuValue("Sub Menu") { Prefix = "", Suffix = "" }) ; var options = new List { @@ -160,6 +213,9 @@ private void CustomSelect(CCSPlayerController controller) subMenu.AddItem(itemOptions); subMenu.AddItem(new MenuItem(MenuItemType.Bool)); + subMenu.AddItem(new MenuItem(MenuItemType.Spacer)); + subMenu.AddItem(new MenuItem(MenuItemType.Text, new MenuValue($"Saving: {pos.X} {pos.Y} {pos.Z}"))); + // Menu.AddMenu() to add to the stack (sub-menu) Menu.AddMenu(controller, subMenu, (buttons, menu, item) => { @@ -176,6 +232,51 @@ private void CustomSelect(CCSPlayerController controller) Console.WriteLine($"Bool: {item.Data[0]}"); }); } + + private void BuildMenu(CCSPlayerController controller) + { + // Create a Menu object which holds all data + var mainMenu = new MenuBase(new MenuValue("Main Menu") { Prefix = "", Suffix = "" }); + + // Can add custom formatting, MenuValue[2] Cursor, MenuValue[2] Selector, MenuValue[2] Bool, MenuValue[4] Slider, MenuValue[1] Input + var cursor = new MenuValue[2] + { + // MenuValue is the fundamental building block of everything in the Menu - MenuValue.Value, MenuValue.Prefix, MenuValue.Suffix + new("--> ") { Prefix = "", Suffix = "" }, + new(" <--") { Prefix = "", Suffix = "" } + }; + + mainMenu.Cursor = cursor; + + // Let's add a simple text field to the menu, each (row) is a MenuItem which holds data for that (row) + // Again MenuValue is the fundamental building block of everything in the Menu - MenuValue.Value, MenuValue.Prefix, MenuValue.Suffix + + var textItem = new MenuValue("Welcome to the new menu!"); + + // Let's modify the prefix and suffix of the textItem + + textItem.Prefix = ""; + textItem.Suffix = ""; + + // Simplified + + textItem = new MenuValue("Welcome to the new menu!") + { + Prefix = "", + Suffix = "" + }; + + var simpleTextItem = new MenuItem(MenuItemType.Text, textItem); + + // Now let's add the textItem to the menu + mainMenu.AddItem(simpleTextItem); + + // And let's add to the global stack to print to the player + Menu.SetMenu(controller, mainMenu, (buttons, menu, item) => { }); + + // The library automatically handles the deposition of the menu + // Using Tab (Scoreboard) exists the menu, and Ctrl (Duck) will go back to the previous menu + } } public class PlayerValue(string value, int? id) : MenuValue(value) @@ -195,4 +296,14 @@ public enum ButtonType Search, Find, Select +} + +public class DynamicValue(string value) : MenuValue(value) +{ + public Vector Position { get; set; } = new(0, 0, 0); + + public override string ToString() + { + return $"{Prefix}x: {Position.X} y: {Position.Y} z: {Position.Z}{Suffix}"; + } } \ No newline at end of file diff --git a/src/IMenuEvent.cs b/src/IMenuEvent.cs new file mode 100644 index 0000000..204ddbb --- /dev/null +++ b/src/IMenuEvent.cs @@ -0,0 +1,15 @@ +using CounterStrikeSharp.API.Core; + +namespace Menu; + +public interface IMenuEvent +{ + +} + +public class MenuEvent(CCSPlayerController controller, MenuBase menu, MenuItem? selectedItem) : IMenuEvent +{ + public CCSPlayerController Controller { get; set; } = controller; + public MenuBase Menu { get; set; } = menu; + public MenuItem? SelectedItem { get; set; } = selectedItem; +} \ No newline at end of file diff --git a/src/Menu.cs b/src/Menu.cs index c4bdb1c..1ebc64f 100644 --- a/src/Menu.cs +++ b/src/Menu.cs @@ -11,6 +11,7 @@ public class Menu private static readonly Timer Timer = new(0.1f, TimerRepeat, TimerFlags.REPEAT); private static readonly SayEvent OnSay = new("say", OnSayEvent); private static readonly SayEvent OnSayTeam = new("say_team", OnSayEvent); + public static event EventHandler? OnDrawMenu; private static void OnSayEvent(CCSPlayerController? controller, string message) { @@ -27,6 +28,11 @@ private static void OnSayEvent(CCSPlayerController? controller, string message) menu.AcceptInput = false; } + protected static void RaiseDrawMenu(CCSPlayerController controller, MenuBase menu, MenuItem? selectedItem) + { + OnDrawMenu?.Invoke(null, new MenuEvent(controller, menu, selectedItem)); + } + private static void TimerRepeat() { foreach (var (controller, menus) in Menus) @@ -148,6 +154,7 @@ private static void TimerRepeat() menu.AcceptButtons = buttons == 0; DrawMenu(controller, menu, selectedItem); + RaiseDrawMenu(controller, menu, selectedItem); } } @@ -259,7 +266,10 @@ private static string FormatValues(MenuBase menu, MenuItem menuItem, MenuItem se private static string FormatString(MenuBase menu, MenuItem menuItem, int index) { - var menuValue = menuItem.Values![index]; + if (menuItem.Values == null) + return ""; + + var menuValue = menuItem.Values[index]; if (menuItem.Type != MenuItemType.ChoiceBool) return menuValue.ToString(); @@ -333,4 +343,28 @@ public void AddMenu(CCSPlayerController controller, MenuBase menu, Action