├── .gitattributes ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── UISystem.csproj ├── UISystem.csproj.old ├── UISystem.sln ├── UISystem ├── Common │ ├── ElementsHoverSettings │ │ ├── Dropdown │ │ │ ├── BorderColor.tres │ │ │ ├── HoverSettings.tres │ │ │ ├── Position.tres │ │ │ └── Size.tres │ │ ├── HSlider │ │ │ ├── BackgroundColor.tres │ │ │ ├── FillColor.tres │ │ │ ├── GrabberColor.tres │ │ │ ├── GrabberPosition.tres │ │ │ ├── GrabberSize.tres │ │ │ └── HoverSettings.tres │ │ ├── MenuNavigationButton │ │ │ ├── BorderColor.tres │ │ │ ├── HoverSettings.tres │ │ │ └── Size.tres │ │ └── OptionsButton │ │ │ ├── BorderColor.tres │ │ │ ├── HoverSettings.tres │ │ │ ├── Position.tres │ │ │ └── Size.tres │ ├── Enums │ │ └── ControllerIconsType.cs │ ├── Prefabs │ │ ├── ButtonView.tscn │ │ ├── DropdownView.tscn │ │ ├── HSlider.tscn │ │ └── Variants │ │ │ ├── MenuNavigationButton.tscn │ │ │ └── MenuOptionButtonView.tscn │ └── Views │ │ ├── ViewBase.cs │ │ └── ViewCreator.cs ├── Constants │ ├── ConfigData.cs │ ├── Icons.cs │ ├── InputsData.cs │ ├── KeyboardIcons.cs │ ├── MouseIcons.cs │ ├── PS5Icons.cs │ ├── PopupMessages.cs │ ├── PropertyConstants.cs │ ├── VideoSettings.cs │ └── XboxIcons.cs ├── DefaultScene.tscn ├── Elements │ ├── ElementViews │ │ ├── ButtonView.cs │ │ ├── DropdownView.cs │ │ ├── HSliderView.cs │ │ ├── RebindableKeyButtonView.cs │ │ └── ResizableControlView.cs │ ├── HoverSettings │ │ ├── ButtonHoverSettings.cs │ │ └── HSliderHoverSettings.cs │ ├── Interfaces │ │ ├── IFocusableControl.cs │ │ └── IFocusableUiElement.cs │ └── Structs │ │ └── OptionButtonItem.cs ├── Extensions │ ├── Extensions.cs │ └── TweenExtensions.cs ├── GameInstaller.cs ├── GameSettings.cs ├── Helpers │ └── Fader.cs ├── Hovering │ ├── ColorTweenSettings.cs │ ├── Enums │ │ └── ControlDrawMode.cs │ ├── Interfaces │ │ └── IHoverTweener.cs │ ├── PositionTweenSettings.cs │ ├── SizeTweenSettings.cs │ ├── TweenSettings.cs │ └── TweeningSettings.cs ├── MenuSystem │ ├── 3D │ │ └── GuiPanel3D.cs │ ├── Constants │ │ └── MenuViewsPaths.cs │ ├── Enums │ │ └── MenuType.cs │ ├── MenuBackgroundController.cs │ ├── MenuControllerBase.cs │ ├── MenuView.cs │ ├── Menus │ │ ├── AudioSettings │ │ │ ├── AudioSettingsMenuController.cs │ │ │ ├── AudioSettingsMenuModel.cs │ │ │ └── AudioSettingsMenuView.cs │ │ ├── InGame │ │ │ ├── InGameMenuController.cs │ │ │ ├── InGameMenuModel.cs │ │ │ └── InGameMenuView.cs │ │ ├── InterfaceSettings │ │ │ ├── InterfaceSettingsMenuController.cs │ │ │ ├── InterfaceSettingsMenuModel.cs │ │ │ └── InterfaceSettingsMenuView.cs │ │ ├── Main │ │ │ ├── MainMenuController.cs │ │ │ ├── MainMenuModel.cs │ │ │ └── MainMenuView.cs │ │ ├── Options │ │ │ ├── OptionsMenuController.cs │ │ │ ├── OptionsMenuModel.cs │ │ │ └── OptionsMenuView.cs │ │ ├── Pause │ │ │ ├── PauseMenuController.cs │ │ │ ├── PauseMenuModel.cs │ │ │ └── PauseMenuView.cs │ │ ├── RebindKeys │ │ │ ├── RebindKeysMenuController.cs │ │ │ ├── RebindKeysMenuModel.cs │ │ │ └── RebindKeysMenuView.cs │ │ └── VideoSettings │ │ │ ├── VideoSettingsMenuController.cs │ │ │ ├── VideoSettingsMenuModel.cs │ │ │ └── VideoSettingsMenuView.cs │ ├── Prefabs │ │ ├── 3D │ │ │ ├── ExampleViewportsFor3D.tscn │ │ │ └── GUIPanel3D.tscn │ │ ├── AudioSettingsMenuView.tscn │ │ ├── InGameMenuView.tscn │ │ ├── InterfaceSettingsMenuView.tscn │ │ ├── MainMenuView.tscn │ │ ├── OptionsMenuView.tscn │ │ ├── PauseMenuView.tscn │ │ ├── RebindKeysMenuView.tscn │ │ └── VideoSettingsMenuView.tscn │ └── SettingsMenu │ │ ├── SettingsMenuController.cs │ │ └── SettingsMenuView.cs ├── PhysicalInput │ ├── IRebindInputReceiver.cs │ └── InputProcessor.cs ├── PopupSystem │ ├── Constants │ │ └── PopupViewsPaths.cs │ ├── Enums │ │ ├── PopupResult.cs │ │ └── PopupType.cs │ ├── PopupControllerBase.cs │ ├── PopupView.cs │ ├── Popups │ │ ├── YesNoCancelPopup │ │ │ ├── YesNoCancelPopupController.cs │ │ │ └── YesNoCancelPopupView.cs │ │ ├── YesNoPopup │ │ │ ├── YesNoPopupController.cs │ │ │ └── YesNoPopupView.cs │ │ └── YesPopup │ │ │ ├── YesPopupController.cs │ │ │ └── YesPopupView.cs │ └── Prefabs │ │ ├── YesNoCancelPopupView.tscn │ │ ├── YesNoPopupView.tscn │ │ └── YesPopupView.tscn ├── ScreenFade │ └── ScreenFadeManager.cs ├── Styles │ ├── ButtonShape.tres │ └── DropdownShape.tres ├── Themes │ ├── ButtonsFontTheme.tres │ └── DropdownButtonTheme.tres ├── Transitions │ ├── Enums │ │ ├── HorizontalDirection.cs │ │ └── VerticalDirection.cs │ ├── Extensions │ │ └── TransitionTweenExtensions.cs │ ├── FadeTransition.cs │ ├── Interfaces │ │ └── ITweenableMenuElement.cs │ ├── MainElementDropTransition.cs │ ├── PanelSizeTransition.cs │ └── Structs │ │ └── ResizableControlSettings.cs ├── UIInstaller.tscn └── UiInstaller.cs └── project.godot /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize EOL for all files that Git considers text files. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | 4 | # Godot-specific ignores 5 | .import/ 6 | export.cfg 7 | export_presets.cfg 8 | 9 | # Imported translations (automatically generated from CSV files) 10 | *.translation 11 | 12 | # Mono-specific ignores 13 | .mono/ 14 | data_*/ 15 | mono_crash.*.json 16 | 17 | # Visual Studio cache directory 18 | .vs/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "UISystemCore"] 2 | path = UISystem/Core 3 | url = git@github.com:gamedevserj/UI-System-Core.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 serj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UI-System-Godot 2 | 3 | UI system for Godot that uses Dependency Injection and MVC patterns. 4 | Core of this system is a submodule that can be found here : https://github.com/gamedevserj/UI-System-Core 5 | 6 | ![Video](https://raw.githubusercontent.com/gamedevserj/Images-For-Repo/refs/heads/main/UiSystemGodot/UISystemGodotAnimated.mp4) 7 | 8 | ## Menu system 9 | The repo has some menus created: **Main, Options, Pause, Audio/Video settings, Interface settings, Key rebinding** 10 | 11 | To add new menu: 12 | 1. Add your menu type to the MenuType enum 13 | 2. Create your menu view script that either inherits from MenuView or from SettingsMenuView (it has functionality to reset setting to default via model and reset view to default) 14 | 3. If your view has interactable elements (buttons, sliders, etc.), they should have scripts attached to them that implement IFocusableControl to disable elements during menu transitions. Some of the elements already included in the repo at UISystem/Common/Elements, there are also prefabs for them in the UISystem/Common/Prefabs, so you can use those 15 | 4. Create your menu model script that implements IMenuModel interface (it is just a marker interface) or ISettingsMenuModel (which has methods to save, discard and reset to default) 16 | 5. Create your menu controller script that inherits from MenuControllerBase providing your view and model 17 | 6. In your menu controller implement the MenuType property by providing your menu type and implement SetupElements() 18 | 7. Create path to your view prefab in MenuViewsPaths 19 | 8. Add your menus to the menus array created in the UiInstaller that passes them to the MenusManager 20 | 9. After that you should be able to call _menusManager.ShowMenu(...) to show your new menu 21 | 22 | ### Menu background controller 23 | A simple script that handles menu's background, look at MainMenu and PauseMenu controllers for example. 24 | 25 | ### ℹ️: Example menus notes 26 | 27 | Audio, video, and interface menus are setup to have a popup if some settings were not saved before quitting. Key rebinding menu saves binds when new key is assigned that's why it has empty Save and DiscardChanges methods. If you want to save changes only when pressing save button, you need to make some changes - look at audio/video settings for example how it can be done. 28 | 29 | #### Rebinding menu example 30 | 31 | To create key binding that player can rebind you need to do the following: 32 | 1. Create your actions in InputMap 33 | 2. Create a property in InputsData and add it to the RebindableActions array 34 | 3. Add rebindable button views in the menu view and set them up in the controller using existing buttons as example 35 | 36 | ⚠️ The example rebinding menu uses image names from https://kenney.nl/assets/input-prompts, but they are not included in this repository. You'll need to download them separately. 37 | 38 | ## Popup system 39 | Some of the popups are already setup and some menus already use them. The steps to create a new type of popup are the same as creating a new menu. 40 | If you want to show a popup when some event occurs you can either create an event and subscribe PopupsManager to that event. Or you can add a static Instance property and call it directly, PopupsManager and MenusManager already part of UiInstaller which is a singleton, so you don't need to add it to the list of autoloads. 41 | 42 | ⚠️ If you have interactable elements in your popup they should also implement IFocusableControl to disable them during transition 43 | 44 | ## Screen fade 45 | A simple script that controls fading, call FadeOut() with an optional action as a parameter that you want to happen when screen is completely black. 46 | 47 | ## Transitions 48 | Transition control the way view is shown/hidden. The repo includes few transitions as example. Menu elements should implement ITweenableMenuElement to reset hover before starting transition if transition changes are modifying the same properties as hovering tween. 49 | 50 | ## Hovering 51 | Menu elements have settings resources that allow to customize the way element is displayed when hovered over/focused. 52 | 53 | Follow these steps if text/icons on your buttons jitter when you change size from center 54 | 1. Set content to be in the center and make sure the position is an integer, it is best to have position to be at 0. The easies way to do that - set anchors using the "Full rect" preset, and then move them to center manually 55 | 2. In your size hover settings set values to be even numbers. This is required since resizing from center moves the control by half of the increased size 56 | 3. ResizableControlView needs to be parented to object that is parented to BoxContainer if its global transition is not from top left, otherwise it doesn't behave correctly. 57 | 58 | Use example prefabs in UISystem/Common/Prefabs as a guide for your elements. 59 | 60 | ## 3D 61 | The setup is used from the official example for UI in 3D space from here. The billboard parts were not included. 62 | https://github.com/godotengine/godot-demo-projects/blob/master/viewport/gui_in_3d/gui_3d.gd 63 | 64 | In order to get your menus to appear in 3D space you'll need to set it's parent to be guiPanel3D.menusParent in the controller's constructor in UIInstaller's Init method. 65 | The default setup makes it possible for 3D objects to visually block the UI, acting similarly to Unity's canvas render mode - "world space". If you want it to not be obscured by the world object (and be similar to Unity's canvas render mode "screen space - camera") there is an example scene ExampleViewportsFor3D.tscn with subviewports setup to show how it could be done. 66 | 67 | Popups can also be displayed in 3D, the setup is the same. 68 | 69 | ⚠️ There are two errors that will be displayed when you run the project regarding the Viewport texture, but they don't affect the game as far as I can tell. 70 | You can read about it here https://github.com/godotengine/godot/issues/66247 71 | -------------------------------------------------------------------------------- /UISystem.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | net7.0 5 | net8.0 6 | true 7 | 8 | -------------------------------------------------------------------------------- /UISystem.csproj.old: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | net7.0 5 | net8.0 6 | true 7 | 8 | -------------------------------------------------------------------------------- /UISystem.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2012 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UISystem", "UISystem.csproj", "{2A7C6F3B-D5C5-4A34-B9B1-F06EFE59AA61}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | ExportDebug|Any CPU = ExportDebug|Any CPU 9 | ExportRelease|Any CPU = ExportRelease|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {2A7C6F3B-D5C5-4A34-B9B1-F06EFE59AA61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {2A7C6F3B-D5C5-4A34-B9B1-F06EFE59AA61}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {2A7C6F3B-D5C5-4A34-B9B1-F06EFE59AA61}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU 15 | {2A7C6F3B-D5C5-4A34-B9B1-F06EFE59AA61}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU 16 | {2A7C6F3B-D5C5-4A34-B9B1-F06EFE59AA61}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU 17 | {2A7C6F3B-D5C5-4A34-B9B1-F06EFE59AA61}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/Dropdown/BorderColor.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ColorTweenSettings" load_steps=2 format=3 uid="uid://cwy3443w5wlcn"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/ColorTweenSettings.cs" id="1_3pfhu"] 4 | 5 | [resource] 6 | script = ExtResource("1_3pfhu") 7 | hoverColor = Color(1, 0, 0, 1) 8 | focusColor = Color(1, 0, 0, 1) 9 | focusHoverColor = Color(0, 0, 1, 1) 10 | disabledColor = Color(0.5, 0.5, 0.5, 1) 11 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/Dropdown/HoverSettings.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ButtonHoverSettings" load_steps=5 format=3 uid="uid://b01oed40pvom6"] 2 | 3 | [ext_resource type="Resource" uid="uid://cwy3443w5wlcn" path="res://UISystem/Common/ElementsHoverSettings/Dropdown/BorderColor.tres" id="1_28e0n"] 4 | [ext_resource type="Script" path="res://UISystem/Elements/HoverSettings/ButtonHoverSettings.cs" id="1_hmipj"] 5 | [ext_resource type="Resource" uid="uid://btl2lnwld7ovl" path="res://UISystem/Common/ElementsHoverSettings/Dropdown/Position.tres" id="2_th2t6"] 6 | [ext_resource type="Resource" uid="uid://cv8ab1b50yhh6" path="res://UISystem/Common/ElementsHoverSettings/Dropdown/Size.tres" id="4_4u5j5"] 7 | 8 | [resource] 9 | script = ExtResource("1_hmipj") 10 | duration = 1.0 11 | resetDuration = 0.25 12 | ease = 1 13 | resetEase = 1 14 | transition = 6 15 | resetTransition = 10 16 | sizeChangeSettings = ExtResource("4_4u5j5") 17 | positionChangeSettings = ExtResource("2_th2t6") 18 | borderColorChangeSettings = ExtResource("1_28e0n") 19 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/Dropdown/Position.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="PositionTweenSettings" load_steps=2 format=3 uid="uid://btl2lnwld7ovl"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/PositionTweenSettings.cs" id="1_ht0xw"] 4 | 5 | [resource] 6 | script = ExtResource("1_ht0xw") 7 | changePositionHover = Vector2(-4, -4) 8 | changePositionFocus = Vector2(-8, -8) 9 | changePositionFocusHover = Vector2(-12, -12) 10 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/Dropdown/Size.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="SizeTweenSettings" load_steps=2 format=3 uid="uid://cv8ab1b50yhh6"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/SizeTweenSettings.cs" id="1_2ag5r"] 4 | 5 | [resource] 6 | script = ExtResource("1_2ag5r") 7 | changeSizeHover = Vector2(8, 8) 8 | changeSizeFocus = Vector2(16, 16) 9 | changeSizeFocusHover = Vector2(24, 24) 10 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/HSlider/BackgroundColor.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ColorTweenSettings" load_steps=2 format=3 uid="uid://bfwyewcy7iqck"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/ColorTweenSettings.cs" id="1_u7bf3"] 4 | 5 | [resource] 6 | script = ExtResource("1_u7bf3") 7 | hoverColor = Color(0.721569, 0.721569, 0.721569, 1) 8 | focusColor = Color(0.721569, 0.721569, 0.721569, 1) 9 | focusHoverColor = Color(0.721569, 0.721569, 0.721569, 1) 10 | disabledColor = Color(0.5, 0.5, 0.5, 1) 11 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/HSlider/FillColor.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ColorTweenSettings" load_steps=2 format=3 uid="uid://b4o1g3t6ls11m"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/ColorTweenSettings.cs" id="1_ch53p"] 4 | 5 | [resource] 6 | script = ExtResource("1_ch53p") 7 | hoverColor = Color(0.533333, 0.686275, 1, 1) 8 | focusColor = Color(0.533333, 0.686275, 1, 1) 9 | focusHoverColor = Color(0.533333, 0.686275, 1, 1) 10 | disabledColor = Color(0.5, 0.5, 0.5, 1) 11 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/HSlider/GrabberColor.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ColorTweenSettings" load_steps=2 format=3 uid="uid://bq67mkdlssxod"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/ColorTweenSettings.cs" id="1_iwt2w"] 4 | 5 | [resource] 6 | script = ExtResource("1_iwt2w") 7 | hoverColor = Color(1, 0, 0, 1) 8 | focusColor = Color(1, 0, 0, 1) 9 | focusHoverColor = Color(0, 0, 1, 1) 10 | disabledColor = Color(0.5, 0.5, 0.5, 1) 11 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/HSlider/GrabberPosition.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="PositionTweenSettings" load_steps=2 format=3 uid="uid://bgkxvmu7uv87p"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/PositionTweenSettings.cs" id="1_q0xua"] 4 | 5 | [resource] 6 | script = ExtResource("1_q0xua") 7 | changePositionHover = Vector2(-5, -5) 8 | changePositionFocus = Vector2(-8, -8) 9 | changePositionFocusHover = Vector2(-10, -10) 10 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/HSlider/GrabberSize.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="SizeTweenSettings" load_steps=2 format=3 uid="uid://u66f3lgv02n7"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/SizeTweenSettings.cs" id="1_ms1lf"] 4 | 5 | [resource] 6 | script = ExtResource("1_ms1lf") 7 | changeSizeHover = Vector2(10, 10) 8 | changeSizeFocus = Vector2(16, 16) 9 | changeSizeFocusHover = Vector2(20, 20) 10 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/HSlider/HoverSettings.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="HSliderHoverSettings" load_steps=7 format=3 uid="uid://b85wtfltfajj"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Elements/HoverSettings/HSliderHoverSettings.cs" id="1_bv111"] 4 | [ext_resource type="Resource" uid="uid://bfwyewcy7iqck" path="res://UISystem/Common/ElementsHoverSettings/HSlider/BackgroundColor.tres" id="1_js4mv"] 5 | [ext_resource type="Resource" uid="uid://b4o1g3t6ls11m" path="res://UISystem/Common/ElementsHoverSettings/HSlider/FillColor.tres" id="2_0vjce"] 6 | [ext_resource type="Resource" uid="uid://bq67mkdlssxod" path="res://UISystem/Common/ElementsHoverSettings/HSlider/GrabberColor.tres" id="3_y7pgs"] 7 | [ext_resource type="Resource" uid="uid://bgkxvmu7uv87p" path="res://UISystem/Common/ElementsHoverSettings/HSlider/GrabberPosition.tres" id="4_j158a"] 8 | [ext_resource type="Resource" uid="uid://u66f3lgv02n7" path="res://UISystem/Common/ElementsHoverSettings/HSlider/GrabberSize.tres" id="5_27bgn"] 9 | 10 | [resource] 11 | script = ExtResource("1_bv111") 12 | duration = 1.0 13 | resetDuration = 0.25 14 | ease = 1 15 | resetEase = 1 16 | transition = 6 17 | resetTransition = 10 18 | grabberSizeSettings = ExtResource("5_27bgn") 19 | grabberPositionsSettings = ExtResource("4_j158a") 20 | grabberColorSettings = ExtResource("3_y7pgs") 21 | backgroundColorSettings = ExtResource("1_js4mv") 22 | fillColorSettings = ExtResource("2_0vjce") 23 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/MenuNavigationButton/BorderColor.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ColorTweenSettings" load_steps=2 format=3 uid="uid://dxu5vjhfpd8gb"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/ColorTweenSettings.cs" id="1_o6x7p"] 4 | 5 | [resource] 6 | script = ExtResource("1_o6x7p") 7 | hoverColor = Color(1, 0, 0, 1) 8 | focusColor = Color(1, 0, 0, 1) 9 | focusHoverColor = Color(0, 0, 1, 1) 10 | disabledColor = Color(0.5, 0.5, 0.5, 1) 11 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/MenuNavigationButton/HoverSettings.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ButtonHoverSettings" load_steps=4 format=3 uid="uid://dj5acww1ovp0b"] 2 | 3 | [ext_resource type="Resource" uid="uid://dxu5vjhfpd8gb" path="res://UISystem/Common/ElementsHoverSettings/MenuNavigationButton/BorderColor.tres" id="1_a4tbk"] 4 | [ext_resource type="Script" path="res://UISystem/Elements/HoverSettings/ButtonHoverSettings.cs" id="1_f14t1"] 5 | [ext_resource type="Resource" uid="uid://biq2cqekjljck" path="res://UISystem/Common/ElementsHoverSettings/MenuNavigationButton/Size.tres" id="5_1uo6a"] 6 | 7 | [resource] 8 | script = ExtResource("1_f14t1") 9 | duration = 1.0 10 | resetDuration = 0.25 11 | ease = 1 12 | resetEase = 1 13 | transition = 6 14 | resetTransition = 10 15 | sizeChangeSettings = ExtResource("5_1uo6a") 16 | borderColorChangeSettings = ExtResource("1_a4tbk") 17 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/MenuNavigationButton/Size.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="SizeTweenSettings" load_steps=2 format=3 uid="uid://biq2cqekjljck"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/SizeTweenSettings.cs" id="1_kap6i"] 4 | 5 | [resource] 6 | script = ExtResource("1_kap6i") 7 | changeSizeHover = Vector2(75, 0) 8 | changeSizeFocus = Vector2(100, 0) 9 | changeSizeFocusHover = Vector2(150, 0) 10 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/OptionsButton/BorderColor.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ColorTweenSettings" load_steps=2 format=3 uid="uid://cbowfskilokn"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/ColorTweenSettings.cs" id="1_5ohmr"] 4 | 5 | [resource] 6 | script = ExtResource("1_5ohmr") 7 | hoverColor = Color(1, 0, 0, 1) 8 | focusColor = Color(1, 0, 0, 1) 9 | focusHoverColor = Color(0, 0, 1, 1) 10 | disabledColor = Color(0.5, 0.5, 0.5, 1) 11 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/OptionsButton/HoverSettings.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="ButtonHoverSettings" load_steps=5 format=3 uid="uid://pxdlfq08bkq1"] 2 | 3 | [ext_resource type="Resource" uid="uid://cbowfskilokn" path="res://UISystem/Common/ElementsHoverSettings/OptionsButton/BorderColor.tres" id="1_47ghg"] 4 | [ext_resource type="Script" path="res://UISystem/Elements/HoverSettings/ButtonHoverSettings.cs" id="1_twq4d"] 5 | [ext_resource type="Resource" uid="uid://bb60lv6j7raf8" path="res://UISystem/Common/ElementsHoverSettings/OptionsButton/Position.tres" id="2_pkx3o"] 6 | [ext_resource type="Resource" uid="uid://3df6yhpcwabx" path="res://UISystem/Common/ElementsHoverSettings/OptionsButton/Size.tres" id="4_bwoub"] 7 | 8 | [resource] 9 | script = ExtResource("1_twq4d") 10 | duration = 1.0 11 | resetDuration = 0.25 12 | ease = 1 13 | resetEase = 1 14 | transition = 6 15 | resetTransition = 10 16 | sizeChangeSettings = ExtResource("4_bwoub") 17 | positionChangeSettings = ExtResource("2_pkx3o") 18 | borderColorChangeSettings = ExtResource("1_47ghg") 19 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/OptionsButton/Position.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="PositionTweenSettings" load_steps=2 format=3 uid="uid://bb60lv6j7raf8"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/PositionTweenSettings.cs" id="1_3882p"] 4 | 5 | [resource] 6 | script = ExtResource("1_3882p") 7 | changePositionHover = Vector2(-5, -5) 8 | changePositionFocus = Vector2(-10, -10) 9 | changePositionFocusHover = Vector2(-13, -13) 10 | -------------------------------------------------------------------------------- /UISystem/Common/ElementsHoverSettings/OptionsButton/Size.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" script_class="SizeTweenSettings" load_steps=2 format=3 uid="uid://3df6yhpcwabx"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Hovering/SizeTweenSettings.cs" id="1_bpxue"] 4 | 5 | [resource] 6 | script = ExtResource("1_bpxue") 7 | changeSizeHover = Vector2(10, 10) 8 | changeSizeFocus = Vector2(20, 20) 9 | changeSizeFocusHover = Vector2(26, 26) 10 | -------------------------------------------------------------------------------- /UISystem/Common/Enums/ControllerIconsType.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.Common.Enums; 2 | public enum ControllerIconsType 3 | { 4 | 5 | Xbox = 0, 6 | Ps5 = 1, 7 | 8 | } 9 | -------------------------------------------------------------------------------- /UISystem/Common/Prefabs/ButtonView.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://bvtey7pkj2tdr"] 2 | 3 | [ext_resource type="Theme" uid="uid://bwj1we86ii4gw" path="res://UISystem/Themes/ButtonsFontTheme.tres" id="4_sffel"] 4 | [ext_resource type="StyleBox" uid="uid://d1gy2bt5uinfv" path="res://UISystem/Styles/ButtonShape.tres" id="4_td8np"] 5 | 6 | [node name="ResizableControl" type="Control"] 7 | layout_mode = 3 8 | anchors_preset = 0 9 | offset_right = 450.0 10 | offset_bottom = 90.0 11 | mouse_filter = 2 12 | 13 | [node name="Border" type="PanelContainer" parent="."] 14 | layout_mode = 1 15 | anchors_preset = 15 16 | anchor_right = 1.0 17 | anchor_bottom = 1.0 18 | grow_horizontal = 2 19 | grow_vertical = 2 20 | mouse_filter = 2 21 | theme_override_styles/panel = ExtResource("4_td8np") 22 | 23 | [node name="Control" type="Control" parent="Border"] 24 | layout_mode = 2 25 | mouse_filter = 2 26 | 27 | [node name="InsideColor" type="PanelContainer" parent="Border/Control"] 28 | self_modulate = Color(0, 0, 0, 1) 29 | layout_mode = 1 30 | anchors_preset = -1 31 | anchor_right = 1.0 32 | anchor_bottom = 1.0 33 | offset_left = 5.0 34 | offset_top = 5.0 35 | offset_right = -5.0 36 | offset_bottom = -5.0 37 | grow_horizontal = 2 38 | grow_vertical = 2 39 | mouse_filter = 2 40 | theme_override_styles/panel = ExtResource("4_td8np") 41 | 42 | [node name="LabelMask" type="Control" parent="."] 43 | clip_contents = true 44 | layout_mode = 1 45 | anchors_preset = 15 46 | anchor_right = 1.0 47 | anchor_bottom = 1.0 48 | offset_left = 25.0 49 | offset_top = 5.0 50 | offset_right = -25.0 51 | offset_bottom = -5.0 52 | grow_horizontal = 2 53 | grow_vertical = 2 54 | mouse_filter = 2 55 | 56 | [node name="Label" type="Label" parent="LabelMask"] 57 | layout_mode = 1 58 | anchors_preset = -1 59 | anchor_left = 0.5 60 | anchor_top = 0.5 61 | anchor_right = 0.5 62 | anchor_bottom = 0.5 63 | offset_left = -126.0 64 | offset_top = -40.0 65 | offset_right = 126.0 66 | offset_bottom = 40.0 67 | grow_horizontal = 2 68 | grow_vertical = 2 69 | theme = ExtResource("4_sffel") 70 | text = "TEXT" 71 | horizontal_alignment = 1 72 | vertical_alignment = 1 73 | clip_text = true 74 | text_overrun_behavior = 1 75 | -------------------------------------------------------------------------------- /UISystem/Common/Prefabs/DropdownView.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://b02xnc3swcbfg"] 2 | 3 | [ext_resource type="Theme" uid="uid://p3e6ki5xgue4" path="res://UISystem/Themes/DropdownButtonTheme.tres" id="1_1jsjw"] 4 | [ext_resource type="Script" path="res://UISystem/Elements/ElementViews/DropdownView.cs" id="1_623xw"] 5 | [ext_resource type="Resource" uid="uid://b01oed40pvom6" path="res://UISystem/Common/ElementsHoverSettings/Dropdown/HoverSettings.tres" id="2_6eh7u"] 6 | [ext_resource type="StyleBox" uid="uid://nqg1m8r4efan" path="res://UISystem/Styles/DropdownShape.tres" id="4_uw6i0"] 7 | [ext_resource type="Theme" uid="uid://bwj1we86ii4gw" path="res://UISystem/Themes/ButtonsFontTheme.tres" id="5_1o05n"] 8 | 9 | [node name="DropdownView" type="OptionButton" node_paths=PackedStringArray("resizableControl", "innerColor", "border", "label")] 10 | self_modulate = Color(1, 1, 1, 0) 11 | custom_minimum_size = Vector2(300, 0) 12 | offset_right = 342.0 13 | offset_bottom = 90.0 14 | size_flags_vertical = 3 15 | theme = ExtResource("1_1jsjw") 16 | flat = true 17 | alignment = 1 18 | text_overrun_behavior = 2 19 | clip_text = true 20 | fit_to_longest_item = false 21 | script = ExtResource("1_623xw") 22 | buttonHoverSettings = ExtResource("2_6eh7u") 23 | resizableControl = NodePath("ResizableControl") 24 | innerColor = NodePath("ResizableControl/Border/Control/InsideColor") 25 | border = NodePath("ResizableControl/Border") 26 | label = NodePath("ResizableControl/TextClipper/Label") 27 | 28 | [node name="ResizableControl" type="Control" parent="."] 29 | layout_mode = 1 30 | anchors_preset = 0 31 | offset_right = 342.0 32 | offset_bottom = 90.0 33 | mouse_filter = 2 34 | 35 | [node name="Border" type="PanelContainer" parent="ResizableControl"] 36 | layout_mode = 1 37 | anchors_preset = 15 38 | anchor_right = 1.0 39 | anchor_bottom = 1.0 40 | grow_horizontal = 2 41 | grow_vertical = 2 42 | mouse_filter = 2 43 | theme_override_styles/panel = ExtResource("4_uw6i0") 44 | 45 | [node name="Control" type="Control" parent="ResizableControl/Border"] 46 | layout_mode = 2 47 | mouse_filter = 2 48 | 49 | [node name="InsideColor" type="PanelContainer" parent="ResizableControl/Border/Control"] 50 | self_modulate = Color(0, 0, 0, 1) 51 | layout_mode = 1 52 | anchors_preset = -1 53 | anchor_right = 1.0 54 | anchor_bottom = 1.0 55 | offset_left = 5.0 56 | offset_top = 5.0 57 | offset_right = -5.0 58 | offset_bottom = -5.0 59 | grow_horizontal = 2 60 | grow_vertical = 2 61 | mouse_filter = 2 62 | theme_override_styles/panel = ExtResource("4_uw6i0") 63 | 64 | [node name="TextClipper" type="Control" parent="ResizableControl"] 65 | clip_contents = true 66 | layout_mode = 1 67 | anchors_preset = 15 68 | anchor_right = 1.0 69 | anchor_bottom = 1.0 70 | offset_left = 5.0 71 | offset_top = 5.0 72 | offset_right = -5.00006 73 | offset_bottom = -5.00002 74 | grow_horizontal = 2 75 | grow_vertical = 2 76 | mouse_filter = 2 77 | 78 | [node name="Label" type="Label" parent="ResizableControl/TextClipper"] 79 | layout_mode = 1 80 | anchors_preset = -1 81 | anchor_left = 0.5 82 | anchor_top = 0.5 83 | anchor_right = 0.5 84 | anchor_bottom = 0.5 85 | offset_left = -166.0 86 | offset_top = -40.0 87 | offset_right = 166.0 88 | offset_bottom = 40.0 89 | grow_horizontal = 2 90 | grow_vertical = 2 91 | theme = ExtResource("5_1o05n") 92 | text = "TEXT" 93 | horizontal_alignment = 1 94 | vertical_alignment = 1 95 | -------------------------------------------------------------------------------- /UISystem/Common/Prefabs/HSlider.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://dhxdq3yb0u7i7"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Elements/ElementViews/HSliderView.cs" id="1_yxgxr"] 4 | [ext_resource type="Resource" uid="uid://b85wtfltfajj" path="res://UISystem/Common/ElementsHoverSettings/HSlider/HoverSettings.tres" id="2_yxxn5"] 5 | [ext_resource type="StyleBox" uid="uid://d1gy2bt5uinfv" path="res://UISystem/Styles/ButtonShape.tres" id="3_igwht"] 6 | 7 | [node name="HSlider" type="HSlider" node_paths=PackedStringArray("grabber", "grabberResizableControl", "background", "fill", "resizableControl")] 8 | self_modulate = Color(1, 1, 1, 0) 9 | size_flags_vertical = 3 10 | max_value = 1.0 11 | step = 0.01 12 | value = 0.5 13 | script = ExtResource("1_yxgxr") 14 | hoverSettings = ExtResource("2_yxxn5") 15 | grabber = NodePath("ResizableControl/GrabberPosition") 16 | grabberResizableControl = NodePath("ResizableControl/GrabberPosition/GrabberResizableControl") 17 | background = NodePath("ResizableControl/Background") 18 | fill = NodePath("ResizableControl/Fill") 19 | resizableControl = NodePath("ResizableControl") 20 | 21 | [node name="ResizableControl" type="Control" parent="."] 22 | layout_mode = 1 23 | anchors_preset = 15 24 | anchor_right = 1.0 25 | anchor_bottom = 1.0 26 | grow_horizontal = 2 27 | grow_vertical = 2 28 | mouse_filter = 2 29 | 30 | [node name="Background" type="PanelContainer" parent="ResizableControl"] 31 | self_modulate = Color(0.552941, 0.552941, 0.552941, 1) 32 | layout_mode = 1 33 | anchors_preset = -1 34 | anchor_right = 1.0 35 | anchor_bottom = 1.0 36 | offset_top = 20.0 37 | offset_bottom = -20.0 38 | grow_horizontal = 2 39 | grow_vertical = 2 40 | mouse_filter = 2 41 | theme_override_styles/panel = ExtResource("3_igwht") 42 | 43 | [node name="Fill" type="PanelContainer" parent="ResizableControl"] 44 | layout_mode = 1 45 | anchors_preset = -1 46 | anchor_right = 1.0 47 | anchor_bottom = 1.0 48 | offset_top = 20.0 49 | offset_bottom = -20.0 50 | grow_horizontal = 2 51 | grow_vertical = 2 52 | mouse_filter = 2 53 | theme_override_styles/panel = ExtResource("3_igwht") 54 | 55 | [node name="GrabberPosition" type="Control" parent="ResizableControl"] 56 | self_modulate = Color(0.592157, 0.592157, 0.592157, 1) 57 | layout_mode = 1 58 | anchors_preset = 15 59 | anchor_right = 1.0 60 | anchor_bottom = 1.0 61 | offset_top = 10.0 62 | offset_right = -589.0 63 | offset_bottom = -9.00001 64 | grow_horizontal = 2 65 | grow_vertical = 2 66 | mouse_filter = 2 67 | 68 | [node name="GrabberResizableControl" type="PanelContainer" parent="ResizableControl/GrabberPosition"] 69 | self_modulate = Color(0.592157, 0.592157, 0.592157, 1) 70 | layout_mode = 1 71 | anchors_preset = 15 72 | anchor_right = 1.0 73 | anchor_bottom = 1.0 74 | grow_horizontal = 2 75 | grow_vertical = 2 76 | mouse_filter = 2 77 | theme_override_styles/panel = ExtResource("3_igwht") 78 | -------------------------------------------------------------------------------- /UISystem/Common/Prefabs/Variants/MenuNavigationButton.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://ck4an0jqn373h"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Elements/ElementViews/ButtonView.cs" id="1_tsrqv"] 4 | [ext_resource type="Resource" uid="uid://dj5acww1ovp0b" path="res://UISystem/Common/ElementsHoverSettings/MenuNavigationButton/HoverSettings.tres" id="2_pe4x4"] 5 | [ext_resource type="StyleBox" uid="uid://d1gy2bt5uinfv" path="res://UISystem/Styles/ButtonShape.tres" id="4_6uuwg"] 6 | [ext_resource type="Theme" uid="uid://bwj1we86ii4gw" path="res://UISystem/Themes/ButtonsFontTheme.tres" id="5_osv58"] 7 | 8 | [node name="MenuNavigationButton" type="Button" node_paths=PackedStringArray("resizableControl", "innerColor", "border", "label")] 9 | self_modulate = Color(1, 1, 1, 0) 10 | size_flags_vertical = 3 11 | flat = true 12 | script = ExtResource("1_tsrqv") 13 | buttonHoverSettings = ExtResource("2_pe4x4") 14 | resizableControl = NodePath("ResizableControl") 15 | innerColor = NodePath("ResizableControl/Border/Control/InsideColor") 16 | border = NodePath("ResizableControl/Border") 17 | label = NodePath("ResizableControl/TextClipper/Label") 18 | 19 | [node name="ResizableControl" type="Control" parent="."] 20 | layout_mode = 3 21 | anchors_preset = 0 22 | offset_right = 450.0 23 | offset_bottom = 90.0 24 | mouse_filter = 2 25 | 26 | [node name="Border" type="PanelContainer" parent="ResizableControl"] 27 | layout_mode = 1 28 | anchors_preset = 15 29 | anchor_right = 1.0 30 | anchor_bottom = 1.0 31 | grow_horizontal = 2 32 | grow_vertical = 2 33 | mouse_filter = 2 34 | theme_override_styles/panel = ExtResource("4_6uuwg") 35 | 36 | [node name="Control" type="Control" parent="ResizableControl/Border"] 37 | layout_mode = 2 38 | mouse_filter = 2 39 | 40 | [node name="InsideColor" type="PanelContainer" parent="ResizableControl/Border/Control"] 41 | self_modulate = Color(0, 0, 0, 1) 42 | layout_mode = 1 43 | anchors_preset = -1 44 | anchor_right = 1.0 45 | anchor_bottom = 1.0 46 | offset_left = 5.0 47 | offset_top = 5.0 48 | offset_right = -5.0 49 | offset_bottom = -5.0 50 | grow_horizontal = 2 51 | grow_vertical = 2 52 | mouse_filter = 2 53 | theme_override_styles/panel = ExtResource("4_6uuwg") 54 | 55 | [node name="TextClipper" type="Control" parent="ResizableControl"] 56 | clip_contents = true 57 | layout_mode = 1 58 | anchors_preset = 15 59 | anchor_right = 1.0 60 | anchor_bottom = 1.0 61 | offset_left = 56.0 62 | offset_top = 5.0 63 | offset_right = -25.0 64 | offset_bottom = -5.00001 65 | grow_horizontal = 2 66 | grow_vertical = 2 67 | mouse_filter = 2 68 | theme = ExtResource("5_osv58") 69 | 70 | [node name="Label" type="Label" parent="ResizableControl/TextClipper"] 71 | layout_mode = 1 72 | anchors_preset = -1 73 | anchor_top = 0.5 74 | anchor_bottom = 0.5 75 | offset_top = -40.0 76 | offset_right = 369.0 77 | offset_bottom = 40.0 78 | grow_horizontal = 2 79 | grow_vertical = 2 80 | theme = ExtResource("5_osv58") 81 | vertical_alignment = 1 82 | clip_text = true 83 | text_overrun_behavior = 1 84 | -------------------------------------------------------------------------------- /UISystem/Common/Prefabs/Variants/MenuOptionButtonView.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://b0ifhq3dslldh"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/Elements/ElementViews/ButtonView.cs" id="1_8a4pk"] 4 | [ext_resource type="Resource" uid="uid://pxdlfq08bkq1" path="res://UISystem/Common/ElementsHoverSettings/OptionsButton/HoverSettings.tres" id="2_wpts1"] 5 | [ext_resource type="StyleBox" uid="uid://d1gy2bt5uinfv" path="res://UISystem/Styles/ButtonShape.tres" id="4_e2svh"] 6 | [ext_resource type="Theme" uid="uid://bwj1we86ii4gw" path="res://UISystem/Themes/ButtonsFontTheme.tres" id="5_ru2ho"] 7 | 8 | [node name="OptionButtonView" type="Button" node_paths=PackedStringArray("resizableControl", "innerColor", "border", "label")] 9 | self_modulate = Color(1, 1, 1, 0) 10 | offset_right = 300.0 11 | offset_bottom = 90.0 12 | size_flags_horizontal = 3 13 | size_flags_vertical = 3 14 | flat = true 15 | script = ExtResource("1_8a4pk") 16 | buttonHoverSettings = ExtResource("2_wpts1") 17 | resizableControl = NodePath("ResizableControl") 18 | innerColor = NodePath("ResizableControl/Border/Control/InsideColor") 19 | border = NodePath("ResizableControl/Border") 20 | label = NodePath("ResizableControl/ContentClipper/Label") 21 | 22 | [node name="ResizableControl" type="Control" parent="."] 23 | layout_mode = 1 24 | anchors_preset = 0 25 | offset_right = 300.0 26 | offset_bottom = 90.0 27 | mouse_filter = 2 28 | 29 | [node name="Border" type="PanelContainer" parent="ResizableControl"] 30 | layout_mode = 1 31 | anchors_preset = 15 32 | anchor_right = 1.0 33 | anchor_bottom = 1.0 34 | grow_horizontal = 2 35 | grow_vertical = 2 36 | mouse_filter = 2 37 | theme_override_styles/panel = ExtResource("4_e2svh") 38 | 39 | [node name="Control" type="Control" parent="ResizableControl/Border"] 40 | layout_mode = 2 41 | mouse_filter = 2 42 | 43 | [node name="InsideColor" type="PanelContainer" parent="ResizableControl/Border/Control"] 44 | self_modulate = Color(0, 0, 0, 1) 45 | layout_mode = 1 46 | anchors_preset = -1 47 | anchor_right = 1.0 48 | anchor_bottom = 1.0 49 | offset_left = 5.0 50 | offset_top = 5.0 51 | offset_right = -5.0 52 | offset_bottom = -5.0 53 | grow_horizontal = 2 54 | grow_vertical = 2 55 | mouse_filter = 2 56 | theme_override_styles/panel = ExtResource("4_e2svh") 57 | 58 | [node name="ContentClipper" type="Control" parent="ResizableControl"] 59 | clip_contents = true 60 | layout_mode = 1 61 | anchors_preset = 15 62 | anchor_right = 1.0 63 | anchor_bottom = 1.0 64 | offset_left = 25.0 65 | offset_top = 5.0 66 | offset_right = -25.0 67 | offset_bottom = -5.00001 68 | grow_horizontal = 2 69 | grow_vertical = 2 70 | mouse_filter = 2 71 | 72 | [node name="Label" type="Label" parent="ResizableControl/ContentClipper"] 73 | layout_mode = 1 74 | anchors_preset = -1 75 | anchor_left = 0.5 76 | anchor_top = 0.5 77 | anchor_right = 0.5 78 | anchor_bottom = 0.5 79 | offset_left = -125.0 80 | offset_top = -40.0 81 | offset_right = 125.0 82 | offset_bottom = 40.0 83 | grow_horizontal = 2 84 | grow_vertical = 2 85 | theme = ExtResource("5_ru2ho") 86 | horizontal_alignment = 1 87 | vertical_alignment = 1 88 | -------------------------------------------------------------------------------- /UISystem/Common/Views/ViewBase.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using UISystem.Core.Transitions; 4 | using UISystem.Core.Views; 5 | using UISystem.Elements; 6 | using UISystem.Extensions; 7 | 8 | namespace UISystem.Views; 9 | /// 10 | /// Base class for a window with interactable elements (menu, popup, etc.) 11 | /// 12 | public abstract partial class ViewBase : Control, IView 13 | { 14 | 15 | private IViewTransition _transition; 16 | protected IFocusableControl[] _focusableElements; 17 | 18 | public virtual void Init() 19 | { 20 | _transition = CreateTransition(); 21 | PopulateFocusableElements(); 22 | } 23 | 24 | public void SwitchInteractability(bool enable) 25 | { 26 | if (_focusableElements != null) 27 | { 28 | for (int i = 0; i < _focusableElements.Length; i++) 29 | { 30 | _focusableElements[i].SwitchFocusAvailability(enable); 31 | } 32 | } 33 | } 34 | 35 | public void Show(Action onShown, bool instant = false) 36 | { 37 | SwitchInteractability(false); 38 | Visible = true; 39 | _transition.Show(()=> 40 | { 41 | SwitchInteractability(true); 42 | onShown?.Invoke(); 43 | }, instant); 44 | } 45 | 46 | public void Hide(Action onHidden, bool instant = false) 47 | { 48 | SwitchInteractability(false); 49 | _transition.Hide(() => { 50 | onHidden?.Invoke(); 51 | Visible = false; // need to switch off visibility to allow GuiPanel3D to receive mouse events 52 | }, instant); 53 | } 54 | 55 | public void DestroyView() => this.SafeQueueFree(); 56 | public abstract void FocusElement(); 57 | protected abstract void PopulateFocusableElements(); 58 | protected abstract IViewTransition CreateTransition(); 59 | 60 | } 61 | -------------------------------------------------------------------------------- /UISystem/Common/Views/ViewCreator.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Views; 3 | using UISystem.Extensions; 4 | 5 | namespace UISystem.Views; 6 | internal class ViewCreator : ViewCreator where TView : ViewBase 7 | { 8 | 9 | public override bool IsViewValid => _view.IsValid(); 10 | 11 | public ViewCreator(string prefab, Node parent) : base(prefab, parent) 12 | { } 13 | 14 | public override void DestroyView() => _view.SafeQueueFree(); 15 | 16 | public override TView CreateView() 17 | { 18 | PackedScene loadedPrefab = ResourceLoader.Load(_prefab); 19 | _view = loadedPrefab.Instantiate() as TView; 20 | _view.Init(); 21 | _parent.AddChild(_view); 22 | return _view; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /UISystem/Constants/ConfigData.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Common.Enums; 3 | using static Godot.DisplayServer; 4 | 5 | namespace UISystem.Constants; 6 | public static class ConfigData 7 | { 8 | 9 | public const string ConfigLocation = "user://Config.cfg"; 10 | 11 | public const string AudioSectionName = "AudioSettings"; 12 | public const string MusicVolumeKey = "MusicVolume"; 13 | public const float DefaultMusicVolume = 0.5f; 14 | public const string SfxVolumeKey = "SfxVolume"; 15 | public const float DefaultSfxVolume = 0.5f; 16 | 17 | public const string VideoSectionName = "VideoSettings"; 18 | public const string ResolutionKey = "Resolution"; 19 | public static Vector2I DefaultResolution => ScreenGetSize(); 20 | public const string WindowModeKey = "WindowMode"; 21 | public const WindowMode DefaultWindowMode = WindowMode.ExclusiveFullscreen; 22 | 23 | public const string KeysSectionName = "Keys"; 24 | 25 | public const string InterfaceSectionName = "Interface"; 26 | public const string ControllerIconsKey = "ControllerIcons"; 27 | public const ControllerIconsType DefaultControllerIconsType = ControllerIconsType.Xbox; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /UISystem/Constants/Icons.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Common.Constants; 3 | using UISystem.Common.Enums; 4 | 5 | namespace UISystem.Constants; 6 | public static class Icons 7 | { 8 | 9 | public const string EllipsisImage = "res://UISystem/Textures/Inputs/ellipsis.png"; 10 | 11 | public static string GetIcon(InputEvent inputEvent, ControllerIconsType iconsType) 12 | { 13 | if (inputEvent is InputEventKey key) 14 | { 15 | return GetIcon(key.PhysicalKeycode); 16 | } 17 | else if (inputEvent is InputEventMouseButton mouseButton) 18 | { 19 | return GetIcon(mouseButton.ButtonIndex); 20 | } 21 | if (inputEvent is InputEventJoypadButton inputButton) 22 | { 23 | return GetIcon(inputButton.ButtonIndex, iconsType); 24 | } 25 | else if (inputEvent is InputEventJoypadMotion motion) 26 | { 27 | return GetIcon(motion.Axis, motion.AxisValue, iconsType); 28 | } 29 | else 30 | throw new System.Exception("Couldn't find icon for input type " + inputEvent.GetType()); 31 | } 32 | private static string GetIcon(Key key) => KeyboardIcons.GetIcon(key); 33 | private static string GetIcon(MouseButton button) => MouseIcons.GetIcon(button); 34 | private static string GetIcon(JoyButton button, ControllerIconsType iconsType) => GetIconByControllerType(button, iconsType); 35 | private static string GetIcon(JoyAxis axis, float positive, ControllerIconsType iconsType) => GetIconByControllerType(axis, positive, iconsType); 36 | 37 | 38 | private static string GetIconByControllerType(JoyButton button, ControllerIconsType iconsType) 39 | { 40 | return iconsType switch 41 | { 42 | ControllerIconsType.Xbox => XboxIcons.GetIcon(button), 43 | ControllerIconsType.Ps5 => PS5Icons.GetIcon(button), 44 | _ => XboxIcons.GetIcon(button), 45 | }; 46 | } 47 | 48 | private static string GetIconByControllerType(JoyAxis axis, float positive, ControllerIconsType iconsType) 49 | { 50 | return iconsType switch 51 | { 52 | ControllerIconsType.Xbox => XboxIcons.GetIcon(axis, positive), 53 | ControllerIconsType.Ps5 => PS5Icons.GetIcon(axis, positive), 54 | _ => XboxIcons.GetIcon(axis, positive), 55 | }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /UISystem/Constants/InputsData.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.Core.Constants; 2 | internal class InputsData 3 | { 4 | 5 | public const string ReturnButton = "ReturnToPreviousMenu"; 6 | public const string PauseButton = "PauseButton"; 7 | 8 | public const int KeyboardEventIndex = 0; 9 | public const int JoystickEventIndex = 1; 10 | 11 | public const string MoveLeft = "MoveLeft"; 12 | public const string MoveRight = "MoveRight"; 13 | public const string Jump = "Jump"; 14 | 15 | public static readonly string[] RebindableActions = { MoveLeft, MoveRight, Jump }; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /UISystem/Constants/MouseIcons.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Collections.Generic; 3 | 4 | namespace UISystem.Common.Constants; 5 | public static class MouseIcons 6 | { 7 | private static string ItemsFolder => "res://UISystem/Textures/Inputs/Keyboard/"; 8 | private static readonly Dictionary _keys; 9 | 10 | static MouseIcons() 11 | { 12 | _keys = new Dictionary() 13 | { 14 | {MouseButton.Left, "mouse_left.png" }, 15 | {MouseButton.Right, "mouse_right.png" }, 16 | {MouseButton.Middle, "mouse_scroll.png" }, 17 | {MouseButton.WheelUp, "mouse_scroll_up.png" }, 18 | {MouseButton.WheelDown, "mouse_scroll_down.png" }, 19 | }; 20 | } 21 | 22 | public static string GetIcon(MouseButton button) 23 | { 24 | return ItemsFolder + _keys[button]; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /UISystem/Constants/PS5Icons.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Collections.Generic; 3 | 4 | namespace UISystem.Common.Constants; 5 | public static class PS5Icons 6 | { 7 | private static string ItemsFolder => "res://UISystem/Textures/Inputs/PS5/"; 8 | 9 | private static readonly Dictionary _buttons; 10 | private static readonly Dictionary _triggersPositive; 11 | private static readonly Dictionary _triggersNegative; 12 | 13 | static PS5Icons() 14 | { 15 | _buttons = new Dictionary 16 | { 17 | { JoyButton.DpadLeft, "playstation_dpad_left.png" }, 18 | { JoyButton.DpadUp, "playstation_dpad_up.png" }, 19 | { JoyButton.DpadRight, "playstation_dpad_right.png" }, 20 | { JoyButton.DpadDown, "playstation_dpad_down.png" }, 21 | // cross 22 | { JoyButton.A, "playstation_button_color_cross.png" }, 23 | // circle 24 | { JoyButton.B, "playstation_button_color_circle.png" }, 25 | // square 26 | { JoyButton.X, "playstation_button_color_square.png" }, 27 | // triangle 28 | { JoyButton.Y, "playstation_button_color_triangle.png" }, 29 | // L1 30 | { JoyButton.LeftShoulder, "playstation_trigger_l1_alternative.png" }, 31 | // R1 32 | { JoyButton.RightShoulder, "playstation_trigger_r1_alternative.png" }, 33 | // share 34 | { JoyButton.Misc1, "playstation_button_create.png" }, 35 | // options 36 | { JoyButton.Start, "playstation_button_options.png" }, 37 | // L3 38 | { JoyButton.LeftStick, "playstation_button_l3.png" }, 39 | // R3 40 | { JoyButton.RightStick, "playstation_button_r3.png" }, 41 | }; 42 | 43 | _triggersPositive = new Dictionary 44 | { 45 | {JoyAxis.TriggerLeft, "playstation_trigger_l2_alternative.png" }, 46 | {JoyAxis.TriggerRight, "playstation_trigger_r2_alternative.png" }, 47 | {JoyAxis.LeftX, "playstation_stick_l_right.png" }, 48 | {JoyAxis.LeftY, "playstation_stick_l_down.png" }, 49 | {JoyAxis.RightX, "playstation_stick_r_right.png" }, 50 | {JoyAxis.RightY, "playstation_stick_r_down.png" }, 51 | }; 52 | 53 | _triggersNegative = new Dictionary 54 | { 55 | {JoyAxis.LeftX, "playstation_stick_l_left.png" }, 56 | {JoyAxis.LeftY, "playstation_stick_l_up.png" }, 57 | {JoyAxis.RightX, "playstation_stick_r_left.png" }, 58 | {JoyAxis.RightY, "playstation_stick_r_up.png" }, 59 | }; 60 | 61 | } 62 | 63 | public static string GetIcon(JoyButton button) 64 | { 65 | return ItemsFolder + _buttons[button]; 66 | } 67 | 68 | public static string GetIcon(JoyAxis axis, float positive) 69 | { 70 | string icon = positive > 0 ? _triggersPositive[axis] : _triggersNegative[axis]; 71 | return ItemsFolder + icon; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /UISystem/Constants/PopupMessages.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.Constants; 2 | public static class PopupMessages 3 | { 4 | 5 | public const string QuitGame = "Quit game?"; 6 | public const string SaveChanges = "Save changes before quitting?"; 7 | public const string ResetToDefault = "Reset to default?"; 8 | public const string QuitToMainMenu = "Quit to main menu?"; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /UISystem/Constants/PropertyConstants.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.Constants; 2 | public static class PropertyConstants 3 | { 4 | 5 | // canvas item 6 | public const string Modulate = "modulate"; 7 | public const string SelfModulate = "self_modulate"; 8 | 9 | // control layout 10 | public const string Size = "size"; 11 | public const string Position = "position"; 12 | public const string GlobalPosition = "global_position"; 13 | public const string Rotation = "rotation"; 14 | public const string Scale = "scale"; 15 | public const string PivotOffset = "pivot_offset"; 16 | 17 | // texture rect 18 | public const string Texture = "texture"; 19 | public const string FlipH = "flip_h"; 20 | public const string FlipV = "flip_v"; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /UISystem/Constants/VideoSettings.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using System.Text.RegularExpressions; 4 | using static Godot.DisplayServer; 5 | 6 | namespace UISystem.Constants; 7 | public static class VideoSettings 8 | { 9 | 10 | public static readonly WindowMode[] WindowModeOptions = new WindowMode[] 11 | { 12 | WindowMode.ExclusiveFullscreen, 13 | WindowMode.Fullscreen, 14 | WindowMode.Windowed, 15 | WindowMode.Maximized, 16 | }; 17 | public static readonly string[] WindowModeNames; 18 | 19 | private static readonly Vector2I[] Resolutions16x9 = new Vector2I[] 20 | { 21 | 22 | new (854, 480), 23 | new (960, 540), 24 | new (1280, 720), 25 | new (1366, 768), 26 | new(1600, 900), 27 | new(1920, 1080), 28 | new(2560, 1440), 29 | new(3200, 1800), 30 | new(3840, 2160), 31 | }; 32 | private static readonly string[] ResolutionNames16x9; 33 | 34 | private static readonly Vector2I[] Resolutions16x10 = new Vector2I[] 35 | { 36 | new (1280, 800), 37 | new (1440, 900), 38 | new (1680, 1050), 39 | new (1920, 1200), 40 | new (2560, 1600), 41 | new (3840, 2400), 42 | }; 43 | private static readonly string[] ResolutionNames16x10; 44 | 45 | static VideoSettings() 46 | { 47 | ResolutionNames16x9 = new string[Resolutions16x9.Length]; 48 | for (int i = 0; i < Resolutions16x9.Length; i++) 49 | { 50 | ResolutionNames16x9[i] = GetResolutionName(Resolutions16x9[i]); 51 | } 52 | 53 | ResolutionNames16x10 = new string[Resolutions16x10.Length]; 54 | for (int i = 0; i < Resolutions16x10.Length; i++) 55 | { 56 | ResolutionNames16x10[i] = GetResolutionName(Resolutions16x10[i]); 57 | } 58 | 59 | WindowModeNames = new string[WindowModeOptions.Length]; 60 | for (int i = 0; i < WindowModeOptions.Length; i++) 61 | { 62 | WindowModeNames[i] = Regex.Replace(WindowModeOptions[i].ToString(), "([A-Z])", " $1").Trim(); // to have space in ExclusiveFullscreen 63 | } 64 | } 65 | 66 | public static Vector2I[] GetResolutionsForAspect(double aspect) 67 | { 68 | if (Mathf.IsEqualApprox(aspect, 1.77f)) 69 | return Resolutions16x9; 70 | if (Mathf.IsEqualApprox(aspect, 1.6f)) 71 | return Resolutions16x10; 72 | 73 | return Resolutions16x9; 74 | } 75 | 76 | public static string[] GetResolutionsNamesForAspect(double aspect) 77 | { 78 | if (Mathf.IsEqualApprox(aspect, 1.77f)) 79 | return ResolutionNames16x9; 80 | if (Mathf.IsEqualApprox(aspect, 1.6f)) 81 | return ResolutionNames16x10; 82 | 83 | return ResolutionNames16x9; 84 | } 85 | 86 | public static int GetResolutionIndex(Vector2I resolution, Vector2I[] allResolutions) 87 | { 88 | return Array.IndexOf(allResolutions, resolution); 89 | } 90 | 91 | public static int GetWindwoModeIndex(WindowMode mode) 92 | { 93 | return Array.IndexOf(WindowModeOptions, mode); 94 | } 95 | 96 | private static string GetResolutionName(Vector2I resolution) 97 | { 98 | return resolution.X + "x" + resolution.Y; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /UISystem/Constants/XboxIcons.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Collections.Generic; 3 | 4 | namespace UISystem.Common.Constants; 5 | public static class XboxIcons 6 | { 7 | 8 | private static string ItemsFolder => "res://UISystem/Textures/Inputs/Xbox/"; 9 | 10 | private static readonly Dictionary _buttons; 11 | private static readonly Dictionary _triggersPositive; 12 | private static readonly Dictionary _triggersNegative; 13 | 14 | static XboxIcons() 15 | { 16 | _buttons = new Dictionary 17 | { 18 | { JoyButton.DpadLeft, "xbox_dpad_left.png" }, 19 | { JoyButton.DpadUp, "xbox_dpad_up.png" }, 20 | { JoyButton.DpadRight, "xbox_dpad_right.png" }, 21 | { JoyButton.DpadDown, "xbox_dpad_down.png" }, 22 | { JoyButton.A, "xbox_button_color_a.png" }, 23 | { JoyButton.B, "xbox_button_color_b.png" }, 24 | { JoyButton.X, "xbox_button_color_x.png" }, 25 | { JoyButton.Y, "xbox_button_color_y.png" }, 26 | // L1 27 | { JoyButton.LeftShoulder, "xbox_lb.png" }, 28 | // R1 29 | { JoyButton.RightShoulder, "xbox_rb.png" }, 30 | // share 31 | { JoyButton.Misc1, "xbox_button_share.png" }, 32 | // options 33 | { JoyButton.Start, "xbox_button_menu.png" }, 34 | // L3 35 | { JoyButton.LeftStick, "xbox_ls.png" }, 36 | // R3 37 | { JoyButton.RightStick, "xbox_rs.png" }, 38 | }; 39 | 40 | _triggersPositive = new Dictionary 41 | { 42 | {JoyAxis.TriggerLeft, "xbox_lt.png" }, 43 | {JoyAxis.TriggerRight, "xbox_rt.png" }, 44 | {JoyAxis.LeftX, "xbox_stick_l_right.png" }, 45 | {JoyAxis.LeftY, "xbox_stick_l_down.png" }, 46 | {JoyAxis.RightX, "xbox_stick_r_right.png" }, 47 | {JoyAxis.RightY, "xbox_stick_r_down.png" }, 48 | }; 49 | 50 | _triggersNegative = new Dictionary 51 | { 52 | {JoyAxis.LeftX, "xbox_stick_l_left.png" }, 53 | {JoyAxis.LeftY, "xbox_stick_l_up.png" }, 54 | {JoyAxis.RightX, "xbox_stick_r_left.png" }, 55 | {JoyAxis.RightY, "xbox_stick_r_up.png" }, 56 | }; 57 | 58 | } 59 | 60 | public static string GetIcon(JoyButton button) 61 | { 62 | return ItemsFolder + _buttons[button]; 63 | } 64 | 65 | public static string GetIcon(JoyAxis axis, float positive = 1) 66 | { 67 | string icon = positive > 0 ? _triggersPositive[axis] : _triggersNegative[axis]; 68 | return ItemsFolder + icon; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /UISystem/DefaultScene.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://d17aklpjxkdtf"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/GameInstaller.cs" id="1_kvqrg"] 4 | 5 | [node name="DefaultScene" type="Node2D"] 6 | 7 | [node name="GameInstaller" type="Node" parent="."] 8 | script = ExtResource("1_kvqrg") 9 | -------------------------------------------------------------------------------- /UISystem/Elements/ElementViews/ButtonView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Threading.Tasks; 3 | using UISystem.Elements.HoverSettings; 4 | using UISystem.Hovering; 5 | using UISystem.Transitions.Interfaces; 6 | 7 | namespace UISystem.Elements.ElementViews; 8 | public partial class ButtonView : BaseButton, IFocusableControl, ITweenableMenuElement 9 | { 10 | 11 | [Export] private ButtonHoverSettings buttonHoverSettings; 12 | [Export] private Control resizableControl; 13 | [Export] private Control innerColor; 14 | [Export] private Control border; 15 | [Export] private Label label; 16 | 17 | private IHoverTweener _hoverTweener; 18 | private bool _mouseOver; 19 | private Tween _tween; 20 | 21 | public Control PositionControl => this; 22 | public Control ResizableControl => resizableControl; 23 | 24 | public override async void _EnterTree() 25 | { 26 | if (buttonHoverSettings == null) return; 27 | 28 | await ToSignal(RenderingServer.Singleton, RenderingServerInstance.SignalName.FramePostDraw); 29 | 30 | _hoverTweener = buttonHoverSettings.CreateTweener(resizableControl, innerColor, border, label); 31 | Subscribe(); 32 | } 33 | 34 | public override void _ExitTree() => Unsubscribe(); 35 | 36 | public async Task ResetHover() 37 | { 38 | if (_hoverTweener == null) await Task.CompletedTask; 39 | 40 | _tween?.Kill(); 41 | _tween = GetTree().CreateTween(); 42 | _hoverTweener.Reset(_tween); 43 | await ToSignal(_tween, Tween.SignalName.Finished); 44 | } 45 | 46 | // there is no OnDisabled event in BaseButton, so it should be disabled via this method to change appearance 47 | public void SwitchButton(bool disable) 48 | { 49 | Disabled = disable; 50 | HoverTween(); 51 | } 52 | 53 | private void Subscribe() 54 | { 55 | FocusEntered += OnFocusEntered; 56 | FocusExited += OnFocusExited; 57 | MouseEntered += OnMouseEntered; 58 | MouseExited += OnMouseExited; 59 | } 60 | 61 | private void Unsubscribe() 62 | { 63 | if (buttonHoverSettings == null) return; 64 | FocusEntered -= OnFocusEntered; 65 | FocusExited -= OnFocusExited; 66 | MouseEntered -= OnMouseEntered; 67 | MouseExited -= OnMouseExited; 68 | } 69 | 70 | private void OnMouseEntered() 71 | { 72 | _mouseOver = true; 73 | HoverTween(); 74 | } 75 | private void OnMouseExited() 76 | { 77 | _mouseOver = false; 78 | HoverTween(); 79 | } 80 | 81 | private void OnFocusEntered() => HoverTween(); 82 | private void OnFocusExited() => HoverTween(); 83 | private void HoverTween() 84 | { 85 | if (_hoverTweener == null) return; 86 | 87 | _tween?.Kill(); 88 | _tween = GetTree().CreateTween(); 89 | _hoverTweener.Tween(_tween, GetDrawingMode()); 90 | } 91 | 92 | private ControlDrawMode GetDrawingMode() 93 | { 94 | if (Disabled) return ControlDrawMode.Disabled; 95 | if (HasFocus()) 96 | { 97 | return _mouseOver ? ControlDrawMode.HoverFocus : ControlDrawMode.Focus; 98 | } 99 | else 100 | return _mouseOver ? ControlDrawMode.Hover : ControlDrawMode.Normal; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /UISystem/Elements/ElementViews/DropdownView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Threading.Tasks; 3 | using UISystem.Elements.HoverSettings; 4 | using UISystem.Hovering; 5 | using UISystem.Transitions.Interfaces; 6 | 7 | namespace UISystem.Elements.ElementViews; 8 | public partial class DropdownView : OptionButton, IFocusableControl, ITweenableMenuElement 9 | { 10 | 11 | [Export] private ButtonHoverSettings buttonHoverSettings; 12 | [Export] private Control resizableControl; 13 | [Export] private Control innerColor; 14 | [Export] private Control border; 15 | [Export] private Label label; 16 | 17 | private IHoverTweener _hoverTweener; 18 | private bool _mouseOver; 19 | private Tween _tween; 20 | 21 | public Control PositionControl => this; 22 | public Control ResizableControl => resizableControl; 23 | 24 | public override async void _EnterTree() 25 | { 26 | if (buttonHoverSettings == null) return; 27 | 28 | await ToSignal(RenderingServer.Singleton, RenderingServerInstance.SignalName.FramePostDraw); 29 | 30 | _hoverTweener = buttonHoverSettings.CreateTweener(resizableControl, innerColor, border, label); 31 | Subscribe(); 32 | } 33 | 34 | public override void _ExitTree() => Unsubscribe(); 35 | 36 | public async Task ResetHover() 37 | { 38 | if (_hoverTweener == null) await Task.CompletedTask; 39 | 40 | _tween?.Kill(); 41 | _tween = GetTree().CreateTween(); 42 | _hoverTweener.Reset(_tween); 43 | await ToSignal(_tween, Tween.SignalName.Finished); 44 | } 45 | 46 | // there is no OnDisabled event in BaseButton, so it should be disabled via this method to change appearance 47 | public void SwitchButton(bool disable) 48 | { 49 | Disabled = disable; 50 | HoverTween(); 51 | } 52 | 53 | private void Subscribe() 54 | { 55 | FocusEntered += OnFocusEntered; 56 | FocusExited += OnFocusExited; 57 | MouseEntered += OnMouseEntered; 58 | MouseExited += OnMouseExited; 59 | ItemSelected += UpdateText; 60 | } 61 | 62 | private void Unsubscribe() 63 | { 64 | if (buttonHoverSettings == null) return; 65 | FocusEntered -= OnFocusEntered; 66 | FocusExited -= OnFocusExited; 67 | MouseEntered -= OnMouseEntered; 68 | MouseExited -= OnMouseExited; 69 | ItemSelected -= UpdateText; 70 | } 71 | 72 | // needs to be a separate method to update label when selecting is called from code 73 | // because view awaits one frame before subscribing when entering tree to allow controls to setup their transforms 74 | public void SelectItem(long index) 75 | { 76 | Select((int)index); 77 | UpdateText((int)index); 78 | } 79 | 80 | private void UpdateText(long index) 81 | { 82 | label.Text = GetItemText((int)index); 83 | } 84 | 85 | private void OnMouseEntered() 86 | { 87 | _mouseOver = true; 88 | HoverTween(); 89 | } 90 | private void OnMouseExited() 91 | { 92 | _mouseOver = false; 93 | HoverTween(); 94 | } 95 | 96 | private void OnFocusEntered() => HoverTween(); 97 | private void OnFocusExited() => HoverTween(); 98 | 99 | private void HoverTween() 100 | { 101 | if (_hoverTweener == null) return; 102 | 103 | _tween?.Kill(); 104 | _tween = GetTree().CreateTween(); 105 | _hoverTweener.Tween(_tween, GetDrawingMode()); 106 | } 107 | 108 | private ControlDrawMode GetDrawingMode() 109 | { 110 | if (Disabled) return ControlDrawMode.Disabled; 111 | if (HasFocus()) 112 | { 113 | return _mouseOver ? ControlDrawMode.HoverFocus : ControlDrawMode.Focus; 114 | } 115 | else 116 | return _mouseOver ? ControlDrawMode.Hover : ControlDrawMode.Normal; 117 | } 118 | 119 | 120 | 121 | } 122 | -------------------------------------------------------------------------------- /UISystem/Elements/ElementViews/HSliderView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Threading.Tasks; 3 | using UISystem.Elements.HoverSettings; 4 | using UISystem.Hovering; 5 | using UISystem.Transitions.Interfaces; 6 | 7 | namespace UISystem.Elements.ElementViews; 8 | public partial class HSliderView : HSlider, IFocusableControl, ITweenableMenuElement 9 | { 10 | 11 | [Export] private HSliderHoverSettings hoverSettings; 12 | [Export] private Control grabber; 13 | [Export] private Control grabberResizableControl; 14 | [Export] private Control background; 15 | [Export] private Control fill; 16 | [Export] private Control resizableControl; 17 | 18 | private IHoverTweener _hoverTweener; 19 | private bool _mouseOver; 20 | private bool _isDragging; 21 | private Tween _tween; 22 | 23 | public Control PositionControl => this; 24 | public Control ResizableControl => resizableControl; 25 | 26 | public override async void _EnterTree() 27 | { 28 | if (hoverSettings == null) return; 29 | 30 | await ToSignal(RenderingServer.Singleton, RenderingServerInstance.SignalName.FramePostDraw); 31 | 32 | _hoverTweener = hoverSettings.CreateTweener(grabberResizableControl, background, fill); 33 | Subscribe(); 34 | UpdateSliderVisual(Value); 35 | } 36 | 37 | public override void _ExitTree() => Unsubscribe(); 38 | 39 | public async Task ResetHover() 40 | { 41 | if (_hoverTweener == null) await Task.CompletedTask; 42 | 43 | _tween?.Kill(); 44 | _tween = GetTree().CreateTween(); 45 | _hoverTweener.Reset(_tween); 46 | await ToSignal(_tween, Tween.SignalName.Finished); 47 | } 48 | 49 | public override void _ValueChanged(double newValue) 50 | { 51 | if (hoverSettings == null) return; 52 | 53 | UpdateSliderVisual(newValue); 54 | } 55 | 56 | private void Subscribe() 57 | { 58 | FocusEntered += OnFocusEntered; 59 | FocusExited += OnFocusExited; 60 | MouseEntered += OnMouseEntered; 61 | MouseExited += OnMouseExited; 62 | DragStarted += OnDragStarted; 63 | DragEnded += OnDragEnded; 64 | } 65 | 66 | private void Unsubscribe() 67 | { 68 | if (hoverSettings == null) return; 69 | FocusEntered -= OnFocusEntered; 70 | FocusExited -= OnFocusExited; 71 | MouseEntered -= OnMouseEntered; 72 | MouseExited -= OnMouseExited; 73 | DragStarted -= OnDragStarted; 74 | DragEnded -= OnDragEnded; 75 | } 76 | 77 | private void OnMouseEntered() 78 | { 79 | _mouseOver = true; 80 | HoverTween(); 81 | } 82 | private void OnMouseExited() 83 | { 84 | _mouseOver = false; 85 | HoverTween(); 86 | } 87 | 88 | private void OnFocusEntered() => HoverTween(); 89 | private void OnFocusExited() => HoverTween(); 90 | 91 | private void HoverTween() 92 | { 93 | if (_hoverTweener == null) return; 94 | 95 | _tween?.Kill(); 96 | _tween = GetTree().CreateTween(); 97 | _hoverTweener.Tween(_tween, GetDrawingMode()); 98 | } 99 | 100 | private ControlDrawMode GetDrawingMode() 101 | { 102 | if (HasFocus()) 103 | { 104 | return _mouseOver ? ControlDrawMode.HoverFocus : _isDragging ? ControlDrawMode.HoverFocus : ControlDrawMode.Focus; 105 | } 106 | else 107 | return _mouseOver ? ControlDrawMode.Hover : ControlDrawMode.Normal; 108 | } 109 | 110 | private void OnDragStarted() => _isDragging = true; 111 | 112 | private void OnDragEnded(bool changed) 113 | { 114 | _isDragging = false; 115 | HoverTween(); 116 | } 117 | 118 | private void UpdateSliderVisual(double newValue) 119 | { 120 | float value = (float)newValue; 121 | fill.SetAnchor(Side.Right, value, true); 122 | grabber.Position = new Vector2((background.Size.X * value) - grabber.Size.X * 0.5f, grabber.Position.Y); 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /UISystem/Elements/ElementViews/RebindableKeyButtonView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | 3 | namespace UISystem.Elements.ElementViews; 4 | public partial class RebindableKeyButtonView : ButtonView 5 | { 6 | 7 | [Export] private TextureRect textureRect; 8 | 9 | public TextureRect TextureRect => textureRect; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /UISystem/Elements/ElementViews/ResizableControlView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Threading.Tasks; 3 | using UISystem.Transitions.Interfaces; 4 | 5 | namespace UISystem.Elements.ElementViews; 6 | /// 7 | /// Is used to pass controls containing labels to PanelSizeTransition 8 | /// 9 | public partial class ResizableControlView : Control, ITweenableMenuElement 10 | { 11 | 12 | public Control PositionControl => this; 13 | public Control ResizableControl => this; 14 | 15 | public async Task ResetHover() => await Task.CompletedTask; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /UISystem/Elements/HoverSettings/ButtonHoverSettings.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Hovering; 3 | 4 | namespace UISystem.Elements.HoverSettings; 5 | [GlobalClass] 6 | public partial class ButtonHoverSettings : Resource 7 | { 8 | 9 | [Export] private float duration = 1; 10 | [Export] private float resetDuration = 0.25f; 11 | [Export] private Tween.EaseType ease = Tween.EaseType.Out; 12 | [Export] private Tween.EaseType resetEase = Tween.EaseType.Out; 13 | [Export] private Tween.TransitionType transition = Tween.TransitionType.Elastic; 14 | [Export] private Tween.TransitionType resetTransition = Tween.TransitionType.Back; 15 | [Export] private SizeTweenSettings sizeChangeSettings; 16 | [Export] private PositionTweenSettings positionChangeSettings; 17 | [Export] private ColorTweenSettings borderColorChangeSettings; 18 | [Export] private ColorTweenSettings colorChangeSettings; 19 | [Export] private ColorTweenSettings labelColorChangeSettings; 20 | 21 | public IHoverTweener CreateTweener(Control resizableControl, Control colorTarget, Control borderColorTarget, 22 | Control labelColorTarget) 23 | { 24 | return new ButtonTweenerFacade(new TweeningSettings(duration, resetDuration, ease, resetEase, transition, resetTransition), 25 | resizableControl, sizeChangeSettings, 26 | resizableControl, positionChangeSettings, 27 | colorTarget, colorChangeSettings, 28 | borderColorTarget, borderColorChangeSettings, 29 | labelColorTarget, labelColorChangeSettings); 30 | } 31 | 32 | private class ButtonTweenerFacade : IHoverTweener 33 | { 34 | 35 | private readonly IHoverTweener[] _tweeners; 36 | 37 | public ButtonTweenerFacade(TweeningSettings transitionAndEaseSettings, 38 | Control sizeTarget, SizeTweenSettings sizeSettings, 39 | Control positionTarget, PositionTweenSettings positionSettings, 40 | Control colorTarget, ColorTweenSettings colorSettings, 41 | Control borderColorTarget, ColorTweenSettings borderColorSettings, 42 | Control labelColorTarget, ColorTweenSettings labelColorSettings) 43 | { 44 | _tweeners = new IHoverTweener[] { 45 | sizeSettings?.CreateTweener(sizeTarget, transitionAndEaseSettings), 46 | positionSettings?.CreateTweener(positionTarget, transitionAndEaseSettings), 47 | colorSettings?.CreateTweener(colorTarget, transitionAndEaseSettings), 48 | borderColorSettings?.CreateTweener(borderColorTarget, transitionAndEaseSettings), 49 | labelColorSettings?.CreateTweener(labelColorTarget, transitionAndEaseSettings), 50 | }; 51 | } 52 | 53 | public void Reset(Tween tween) 54 | { 55 | for (int i = 0; i < _tweeners.Length; i++) 56 | { 57 | _tweeners[i]?.Reset(tween); 58 | } 59 | } 60 | 61 | public void Tween(Tween tween, ControlDrawMode mode) 62 | { 63 | for (int i = 0; i < _tweeners.Length; i++) 64 | { 65 | _tweeners[i]?.Tween(tween, mode); 66 | } 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /UISystem/Elements/HoverSettings/HSliderHoverSettings.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Hovering; 3 | 4 | namespace UISystem.Elements.HoverSettings; 5 | [GlobalClass] 6 | public partial class HSliderHoverSettings : Resource 7 | { 8 | 9 | [Export] private float duration = 1; 10 | [Export] private float resetDuration = 0.25f; 11 | [Export] private Tween.EaseType ease = Tween.EaseType.Out; 12 | [Export] private Tween.EaseType resetEase = Tween.EaseType.Out; 13 | [Export] private Tween.TransitionType transition = Tween.TransitionType.Elastic; 14 | [Export] private Tween.TransitionType resetTransition = Tween.TransitionType.Back; 15 | [Export] private SizeTweenSettings grabberSizeSettings; 16 | [Export] private PositionTweenSettings grabberPositionsSettings; 17 | [Export] private ColorTweenSettings grabberColorSettings; 18 | [Export] private ColorTweenSettings backgroundColorSettings; 19 | [Export] private ColorTweenSettings fillColorSettings; 20 | 21 | public IHoverTweener CreateTweener(Control grabberResizableControl, Control background, Control fill) 22 | { 23 | return new HSliderTweenerFacade(new TweeningSettings(duration, resetDuration, ease, resetEase, transition, resetTransition), 24 | grabberResizableControl, grabberSizeSettings, grabberPositionsSettings, grabberColorSettings, 25 | background, backgroundColorSettings, 26 | fill, fillColorSettings); 27 | } 28 | 29 | private class HSliderTweenerFacade : IHoverTweener 30 | { 31 | 32 | private readonly IHoverTweener[] _tweeners; 33 | 34 | public HSliderTweenerFacade(TweeningSettings transitionAndEaseSettings, 35 | Control grabberResizableControl, SizeTweenSettings grabberSizeSettings, PositionTweenSettings grabberPositionsSettings, ColorTweenSettings grabberColorSettings, 36 | Control background, ColorTweenSettings backgroundColorSettings, 37 | Control fill, ColorTweenSettings fillColorSettings) 38 | { 39 | _tweeners = new IHoverTweener[] { 40 | grabberSizeSettings?.CreateTweener(grabberResizableControl, transitionAndEaseSettings), 41 | grabberPositionsSettings?.CreateTweener(grabberResizableControl, transitionAndEaseSettings), 42 | grabberColorSettings?.CreateTweener(grabberResizableControl, transitionAndEaseSettings), 43 | backgroundColorSettings?.CreateTweener(background, transitionAndEaseSettings), 44 | fillColorSettings?.CreateTweener(fill, transitionAndEaseSettings) 45 | }; 46 | } 47 | 48 | public void Reset(Tween tween) 49 | { 50 | for (int i = 0; i < _tweeners.Length; i++) 51 | { 52 | _tweeners[i]?.Reset(tween); 53 | } 54 | } 55 | 56 | public void Tween(Tween tween, ControlDrawMode mode) 57 | { 58 | for (int i = 0; i < _tweeners.Length; i++) 59 | { 60 | _tweeners[i]?.Tween(tween, mode); 61 | } 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /UISystem/Elements/Interfaces/IFocusableControl.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | 3 | namespace UISystem.Elements; 4 | public interface IFocusableControl : IFocusableUiElement 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /UISystem/Elements/Interfaces/IFocusableUiElement.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Extensions; 3 | using static Godot.Control; 4 | 5 | namespace UISystem.Elements; 6 | public interface IFocusableUiElement where T : Control 7 | { 8 | 9 | private T Instance => (T)this; 10 | 11 | void SwitchFocus(bool focus) 12 | { 13 | if (focus) 14 | Instance.GrabFocus(); 15 | else 16 | Instance.ReleaseFocus(); 17 | } 18 | 19 | bool? IsValidElement() 20 | { 21 | return Instance?.IsValid(); 22 | } 23 | 24 | void SwitchFocusAvailability(bool focusable) 25 | { 26 | Instance.FocusMode = focusable ? FocusModeEnum.All : FocusModeEnum.None; 27 | Instance.MouseFilter = focusable ? MouseFilterEnum.Stop : MouseFilterEnum.Ignore; 28 | 29 | if (!focusable && Instance.HasFocus()) 30 | SwitchFocus(false); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /UISystem/Elements/Structs/OptionButtonItem.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.Elements; 2 | public struct OptionButtonItem 3 | { 4 | public string Label; 5 | public int Id; 6 | 7 | public OptionButtonItem(string label, int id) 8 | { 9 | Label = label; 10 | Id = id; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /UISystem/Extensions/Extensions.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Elements; 3 | 4 | namespace UISystem.Extensions 5 | { 6 | public static class Extensions 7 | { 8 | 9 | public static bool IsValid(this T node) where T : GodotObject 10 | { 11 | return node != null 12 | && GodotObject.IsInstanceValid(node) 13 | && !node.IsQueuedForDeletion(); 14 | } 15 | 16 | public static void SafeQueueFree(this Node node) 17 | { 18 | if (node.IsValid()) node.QueueFree(); 19 | } 20 | 21 | public static void AddMultipleItems(this OptionButton optionButton, OptionButtonItem[] items) 22 | { 23 | for (int i = 0; i < items.Length; i++) 24 | { 25 | optionButton.AddItem(items[i].Label, items[i].Id); 26 | } 27 | } 28 | 29 | public static void SetSizeAndPosition(this Control control, Vector2 size, Vector2 position) 30 | { 31 | control.Size = size; 32 | control.Position = position; 33 | } 34 | 35 | public static void HideItem(this CanvasItem item) 36 | { 37 | item.Modulate = new Color(item.Modulate, 0); 38 | } 39 | 40 | public static void ShowItem(this CanvasItem item) 41 | { 42 | item.Modulate = new Color(item.Modulate, 1); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /UISystem/Extensions/TweenExtensions.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Constants; 3 | 4 | namespace UISystem.Extensions; 5 | internal static class TweenExtensions 6 | { 7 | public static Tween TweenControlPosition(this Tween tween, Control target, Vector2 position, float duration) 8 | { 9 | tween.TweenProperty(target, PropertyConstants.Position, position, duration); 10 | return tween; 11 | } 12 | 13 | public static Tween TweenControlGlobalPosition(this Tween tween, Control target, Vector2 position, float duration) 14 | { 15 | tween.TweenProperty(target, PropertyConstants.GlobalPosition, position, duration); 16 | return tween; 17 | } 18 | 19 | public static void TweenModulate(this Tween tween, CanvasItem target, Color color, float duration, bool self = false) 20 | { 21 | if (!self) 22 | tween.TweenProperty(target, PropertyConstants.Modulate, color, duration); 23 | else 24 | tween.TweenProperty(target, PropertyConstants.SelfModulate, color, duration); 25 | } 26 | 27 | public static Tween TweenAlpha(this Tween tween, CanvasItem target, float alpha, float duration, bool self = false) 28 | { 29 | if (!self) 30 | tween.TweenProperty(target, PropertyConstants.Modulate, new Color(target.Modulate, alpha), duration); 31 | else 32 | tween.TweenProperty(target, PropertyConstants.SelfModulate, new Color(target.SelfModulate, alpha), duration); 33 | return tween; 34 | } 35 | 36 | public static Tween TweenControlSize(this Tween tween, Control target, Vector2 size, float duration) 37 | { 38 | tween.TweenProperty(target, PropertyConstants.Size, size, duration); 39 | return tween; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /UISystem/GameInstaller.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Constants; 3 | 4 | namespace UISystem; 5 | public partial class GameInstaller : Node 6 | { 7 | 8 | public override void _Ready() 9 | { 10 | var config = new ConfigFile(); 11 | Error err = config.Load(ConfigData.ConfigLocation); 12 | GameSettings settings = new(config); 13 | 14 | UiInstaller.Instance.Init(settings); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /UISystem/Helpers/Fader.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using UISystem.Constants; 4 | 5 | namespace UISystem.Helpers; 6 | public static class Fader 7 | { 8 | 9 | private const float TransitionDuration = 0.25f; 10 | 11 | public static void Init(Control target) 12 | { 13 | target.Modulate = new Color(target.Modulate, 0); 14 | } 15 | 16 | public static void Show(SceneTree tree, Control target, Action onComplete = null, bool instant = false) 17 | { 18 | var targetColor = new Color(target.Modulate, 1); 19 | if (instant) 20 | { 21 | InstantChange(target, targetColor, onComplete); 22 | return; 23 | } 24 | 25 | TweenColor(tree, target, targetColor, onComplete); 26 | } 27 | 28 | public static void Hide(SceneTree tree, Control target, Action onComplete = null, bool instant = false) 29 | { 30 | var targetColor = new Color(target.Modulate, 0); 31 | if (instant) 32 | { 33 | InstantChange(target, targetColor, onComplete); 34 | return; 35 | } 36 | 37 | TweenColor(tree, target, targetColor, onComplete); 38 | } 39 | 40 | private static void TweenColor(SceneTree tree, Control target, Color targetColor, Action onComplete = null) 41 | { 42 | Tween tween = tree.CreateTween(); 43 | tween.SetPauseMode(Tween.TweenPauseMode.Process); 44 | tween.TweenProperty(target, PropertyConstants.Modulate, targetColor, TransitionDuration); 45 | tween.TweenCallback(Callable.From(() => onComplete?.Invoke())); 46 | } 47 | 48 | private static void InstantChange(Control target, Color targetColor, Action onComplete = null) 49 | { 50 | target.Modulate = targetColor; 51 | onComplete?.Invoke(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /UISystem/Hovering/ColorTweenSettings.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Extensions; 3 | 4 | namespace UISystem.Hovering; 5 | [GlobalClass] 6 | public partial class ColorTweenSettings : TweenSettings 7 | { 8 | 9 | [Export] private Color hoverColor = new(1, 1, 1, 1); 10 | [Export] private Color focusColor = new(1, 1, 1, 1); 11 | [Export] private Color focusHoverColor = new(1, 1, 1, 1); 12 | [Export] private Color disabledColor = new(0.5f, 0.5f, 0.5f, 1); 13 | 14 | protected override Color HoverValue => hoverColor; 15 | protected override Color FocusValue => focusColor; 16 | protected override Color FocusHoverValue => focusHoverColor; 17 | protected override Color DisabledValue => disabledColor; 18 | 19 | public IHoverTweener CreateTweener(Control target, TweeningSettings transitionAndEaseSettings, bool parallel = true) 20 | => new ColorTweener(target, target.SelfModulate, transitionAndEaseSettings, this, parallel); 21 | 22 | protected partial class ColorTweener : Tweener 23 | { 24 | 25 | private Color _originalValue; 26 | protected override Color NormalValue => _originalValue; 27 | 28 | public ColorTweener(Control target, Color originalValue, TweeningSettings transitionAndEaseSettings, 29 | TweenSettings settings, bool parallel) 30 | : base(target, transitionAndEaseSettings, settings, parallel) 31 | { 32 | _originalValue = originalValue; 33 | } 34 | 35 | protected override void Tween(Tween tween, Color value) 36 | { 37 | base.Tween(tween, value); 38 | if(_parallel) 39 | tween.Parallel().TweenModulate(_target, value, _transitionAndEaseSettings.Duration, true); 40 | else 41 | tween.TweenModulate(_target, value, _transitionAndEaseSettings.Duration, true); 42 | } 43 | 44 | public override void Reset(Tween tween) 45 | { 46 | base.Reset(tween); 47 | if(_parallel) 48 | tween.Parallel().TweenModulate(_target, _originalValue, _transitionAndEaseSettings.ResetDuration, true); 49 | else 50 | tween.TweenModulate(_target, _originalValue, _transitionAndEaseSettings.ResetDuration, true); 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /UISystem/Hovering/Enums/ControlDrawMode.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.Hovering; 2 | public enum ControlDrawMode 3 | { 4 | Normal = 0, 5 | Hover = 1, 6 | Focus = 2, 7 | HoverFocus = 3, 8 | Disabled = 4, 9 | } 10 | -------------------------------------------------------------------------------- /UISystem/Hovering/Interfaces/IHoverTweener.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | 3 | namespace UISystem.Hovering; 4 | public interface IHoverTweener 5 | { 6 | 7 | void Tween(Tween tween, ControlDrawMode mode); 8 | void Reset(Tween tween); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /UISystem/Hovering/PositionTweenSettings.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Extensions; 3 | 4 | namespace UISystem.Hovering; 5 | [GlobalClass] 6 | public partial class PositionTweenSettings : TweenSettings 7 | { 8 | 9 | [Export] private Vector2 changePositionHover = new(0, 0); 10 | [Export] private Vector2 changePositionFocus = new(0, 0); 11 | [Export] private Vector2 changePositionFocusHover = new(0, 0); 12 | 13 | protected override Vector2 NormalValue => Vector2.Zero; 14 | protected override Vector2 HoverValue => changePositionHover; 15 | protected override Vector2 FocusValue => changePositionFocus; 16 | protected override Vector2 FocusHoverValue => changePositionFocusHover; 17 | protected override Vector2 DisabledValue => Vector2.Zero; 18 | 19 | public IHoverTweener CreateTweener(Control target, TweeningSettings transitionAndEaseSettings, bool parallel = true) => 20 | new PositionTweener(target, target.Position, transitionAndEaseSettings, this, parallel); 21 | 22 | private class PositionTweener : Tweener 23 | { 24 | 25 | private Vector2 _originalValue; 26 | 27 | public PositionTweener(Control target, Vector2 originalValue, TweeningSettings transitionAndEaseSettings, 28 | TweenSettings settings, bool parallel) 29 | : base(target, transitionAndEaseSettings, settings, parallel) 30 | { 31 | _originalValue = originalValue; 32 | } 33 | 34 | protected override void Tween(Tween tween, Vector2 value) 35 | { 36 | base.Tween(tween, value); 37 | if (_parallel) 38 | tween.Parallel().TweenControlPosition(_target, _originalValue + value, _transitionAndEaseSettings.Duration); 39 | else 40 | tween.TweenControlPosition(_target, _originalValue + value, _transitionAndEaseSettings.Duration); 41 | } 42 | 43 | public override void Reset(Tween tween) 44 | { 45 | base.Reset(tween); 46 | if (_parallel) 47 | tween.Parallel().TweenControlPosition(_target, _originalValue, _transitionAndEaseSettings.ResetDuration); 48 | else 49 | tween.TweenControlPosition(_target, _originalValue, _transitionAndEaseSettings.ResetDuration); 50 | } 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /UISystem/Hovering/SizeTweenSettings.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Extensions; 3 | 4 | namespace UISystem.Hovering; 5 | [GlobalClass] 6 | public partial class SizeTweenSettings : TweenSettings 7 | { 8 | 9 | [Export] private Vector2 changeSizeHover = new(0, 0); 10 | [Export] private Vector2 changeSizeFocus = new(0, 0); 11 | [Export] private Vector2 changeSizeFocusHover = new(0, 0); 12 | 13 | protected override Vector2 NormalValue => Vector2.Zero; 14 | protected override Vector2 HoverValue => changeSizeHover; 15 | protected override Vector2 FocusValue => changeSizeFocus; 16 | protected override Vector2 FocusHoverValue => changeSizeFocusHover; 17 | protected override Vector2 DisabledValue => Vector2.Zero; 18 | 19 | 20 | public IHoverTweener CreateTweener(Control target, TweeningSettings transitionAndEaseSettings, bool parallel = true) 21 | => new SizeTweener(target, target.Size, transitionAndEaseSettings, this, parallel); 22 | 23 | private class SizeTweener : Tweener 24 | { 25 | 26 | private Vector2 _originalValue; 27 | 28 | public SizeTweener(Control target, Vector2 originalSize, TweeningSettings transitionAndEaseSettings, 29 | TweenSettings settings, bool parallel) 30 | : base(target, transitionAndEaseSettings, settings, parallel) 31 | { 32 | _originalValue = originalSize; 33 | } 34 | 35 | protected override void Tween(Tween tween, Vector2 value) 36 | { 37 | base.Tween(tween, value); 38 | if (_parallel) 39 | tween.Parallel().TweenControlSize(_target, _originalValue + value, _transitionAndEaseSettings.Duration); 40 | else 41 | tween.TweenControlSize(_target, _originalValue + value, _transitionAndEaseSettings.Duration); 42 | } 43 | 44 | public override void Reset(Tween tween) 45 | { 46 | base.Reset(tween); 47 | if (_parallel) 48 | tween.Parallel().TweenControlSize(_target, _originalValue, _transitionAndEaseSettings.ResetDuration); 49 | else 50 | tween.TweenControlSize(_target, _originalValue, _transitionAndEaseSettings.ResetDuration); 51 | } 52 | 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /UISystem/Hovering/TweenSettings.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | 3 | namespace UISystem.Hovering; 4 | public abstract partial class TweenSettings : Resource 5 | { 6 | 7 | protected virtual T NormalValue { get; } 8 | protected abstract T HoverValue { get; } 9 | protected abstract T FocusValue { get; } 10 | protected abstract T FocusHoverValue { get; } 11 | protected abstract T DisabledValue { get; } 12 | 13 | protected abstract class Tweener : IHoverTweener 14 | { 15 | 16 | protected readonly Control _target; 17 | protected readonly bool _parallel; 18 | protected readonly TweenSettings _settings; 19 | protected readonly TweeningSettings _transitionAndEaseSettings; 20 | 21 | protected virtual T NormalValue => _settings.NormalValue; 22 | 23 | public Tweener(Control target, TweeningSettings transitionAndEaseSettings, TweenSettings settings, 24 | bool parallel) 25 | { 26 | _target = target; 27 | _parallel = parallel; 28 | _settings = settings; 29 | _transitionAndEaseSettings = transitionAndEaseSettings; 30 | } 31 | 32 | public void Tween(Tween tween, ControlDrawMode mode) 33 | { 34 | Tween(tween, SelectValue(mode)); 35 | } 36 | 37 | public virtual void Reset(Tween tween) 38 | { 39 | tween.SetEase(_transitionAndEaseSettings.ResetEase).SetTrans(_transitionAndEaseSettings.ResetTransition); 40 | } 41 | 42 | protected virtual void Tween(Tween tween, T value) 43 | { 44 | tween.SetEase(_transitionAndEaseSettings.Ease).SetTrans(_transitionAndEaseSettings.Transition); 45 | } 46 | 47 | private T SelectValue(ControlDrawMode mode) => mode switch 48 | { 49 | ControlDrawMode.Normal => NormalValue, 50 | ControlDrawMode.Hover => _settings.HoverValue, 51 | ControlDrawMode.Focus => _settings.FocusValue, 52 | ControlDrawMode.HoverFocus => _settings.FocusHoverValue, 53 | ControlDrawMode.Disabled => _settings.DisabledValue, 54 | _ => _settings.NormalValue, 55 | }; 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /UISystem/Hovering/TweeningSettings.cs: -------------------------------------------------------------------------------- 1 | using static Godot.Tween; 2 | 3 | namespace UISystem.Hovering; 4 | public struct TweeningSettings 5 | { 6 | 7 | public float Duration = 1f; 8 | public float ResetDuration = 0.25f; 9 | public EaseType Ease = EaseType.Out; 10 | public EaseType ResetEase = EaseType.Out; 11 | public TransitionType Transition = TransitionType.Elastic; 12 | public TransitionType ResetTransition = TransitionType.Back; 13 | 14 | public TweeningSettings(float duration, float resetDuration, 15 | EaseType ease, EaseType resetEase, TransitionType transition, TransitionType resetTransition) 16 | { 17 | Duration = duration; 18 | ResetDuration = resetDuration; 19 | Ease = ease; 20 | ResetEase = resetEase; 21 | Transition = transition; 22 | ResetTransition = resetTransition; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/3D/GuiPanel3D.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | 3 | namespace UISystem.MenuSystem; 4 | /// 5 | /// this code is translated from gdscript 6 | /// https://github.com/godotengine/godot-demo-projects/blob/master/viewport/gui_in_3d/gui_3d.gd 7 | /// I didn't bother including method for billboard display 8 | /// 9 | public partial class GuiPanel3D : Node 10 | { 11 | 12 | [Export] private SubViewport subViewport; 13 | [Export] private MeshInstance3D quad; 14 | [Export] private Area3D area3d; 15 | [Export] private Control menusParent; 16 | [Export] private Control popupsParent; 17 | 18 | private bool _isMouseInside; 19 | private Vector2 _lastEventPosition2D; 20 | private float _lastEventTime = -1; 21 | 22 | public SubViewport SubViewport => subViewport; 23 | public Control MenusParent => menusParent; 24 | public Control PopupsParent => popupsParent; 25 | 26 | // Called when the node enters the scene tree for the first time. 27 | public override void _Ready() 28 | { 29 | area3d.MouseEntered += MouseEnteredArea; 30 | area3d.MouseExited += MouseExitedArea; 31 | area3d.InputEvent += MouseInputEvent; 32 | } 33 | 34 | private void MouseEnteredArea() => _isMouseInside = true; 35 | private void MouseExitedArea() => _isMouseInside = false; 36 | 37 | private void MouseInputEvent(Node camera, InputEvent @event, Vector3 eventPosition, Vector3 normal, long shapeIndex) 38 | { 39 | if (@event is not InputEventMouse mouseEvent) 40 | return; 41 | 42 | // Get mesh size to detect edges and make conversions. This code only support PlaneMesh and QuadMesh. 43 | var quadMeshSize = (quad.Mesh as QuadMesh).Size; 44 | 45 | // Event position in Area3D in world coordinate space. 46 | var eventPosition3D = eventPosition; 47 | 48 | // Current time in seconds since engine start. 49 | var now = Time.GetTicksMsec() / 1000.0f; 50 | 51 | // Convert position to a coordinate space relative to the Area3D node. 52 | // NOTE: affine_inverse accounts for the Area3D node's scale, rotation, and position in the scene! 53 | eventPosition3D = quad.GlobalTransform.AffineInverse() * eventPosition3D; 54 | 55 | // TODO: Adapt to bilboard mode or avoid completely. 56 | 57 | Vector2 eventPosition2D = new(); 58 | 59 | if (_isMouseInside) 60 | { 61 | // Convert the relative event position from 3D to 2D. 62 | eventPosition2D = new Vector2(eventPosition3D.X, -eventPosition3D.Y); 63 | 64 | // Right now the event position's range is the following: (-quad_size/2) -> (quad_size/2) 65 | // We need to convert it into the following range: -0.5 -> 0.5 66 | eventPosition2D.X /= quadMeshSize.X; 67 | eventPosition2D.Y /= quadMeshSize.Y; 68 | // Then we need to convert it into the following range: 0 -> 1 69 | eventPosition2D.X += 0.5f; 70 | eventPosition2D.Y += 0.5f; 71 | 72 | // Finally, we convert the position to the following range: 0 -> viewport.size 73 | eventPosition2D.X *= subViewport.Size.X; 74 | eventPosition2D.Y *= subViewport.Size.Y; 75 | // We need to do these conversions so the event's position is in the viewport's coordinate system. 76 | } 77 | else if (!_lastEventPosition2D.IsEqualApprox(Vector2.Zero)) 78 | { 79 | // Fall back to the last known event position. 80 | eventPosition2D = _lastEventPosition2D; 81 | } 82 | 83 | // Set the event's position and global position. 84 | mouseEvent.Position = eventPosition2D; 85 | mouseEvent.GlobalPosition = eventPosition2D; 86 | 87 | // Calculate the relative event distance. 88 | if (@event is InputEventMouseMotion) 89 | { 90 | var motion = @event as InputEventMouseMotion; 91 | //# If there is not a stored previous position, then we'll assume there is no relative motion. 92 | if (_lastEventPosition2D.IsEqualApprox(Vector2.Zero)) 93 | { 94 | motion.Relative = Vector2.Zero; 95 | //# If there is a stored previous position, then we'll calculate the relative position by subtracting 96 | //# the previous position from the new position. This will give us the distance the event traveled from prev_pos. 97 | } 98 | else 99 | { 100 | motion.Relative = eventPosition2D - _lastEventPosition2D; 101 | motion.Velocity = motion.Relative / (now - _lastEventTime); 102 | } 103 | } 104 | else if (@event is InputEventScreenDrag) 105 | { 106 | var motion = @event as InputEventScreenDrag; 107 | //# If there is not a stored previous position, then we'll assume there is no relative motion. 108 | if (_lastEventPosition2D.IsEqualApprox(Vector2.Zero)) 109 | { 110 | motion.Relative = Vector2.Zero; 111 | //# If there is a stored previous position, then we'll calculate the relative position by subtracting 112 | //# the previous position from the new position. This will give us the distance the event traveled from prev_pos. 113 | } 114 | else 115 | { 116 | motion.Relative = eventPosition2D - _lastEventPosition2D; 117 | motion.Velocity = motion.Relative / (now - _lastEventTime); 118 | } 119 | } 120 | 121 | //# Update last_event_pos2D with the position we just calculated. 122 | _lastEventPosition2D = eventPosition2D; 123 | 124 | //# Update last_event_time to current time. 125 | _lastEventTime = now; 126 | 127 | //# Finally, send the processed input event to the viewport. 128 | subViewport.PushInput(@event); 129 | } 130 | } -------------------------------------------------------------------------------- /UISystem/MenuSystem/Constants/MenuViewsPaths.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UISystem.MenuSystem.Constants; 4 | internal partial class MenuViewsPaths 5 | { 6 | 7 | private const string Folder = "res://UISystem/MenuSystem/Prefabs/"; 8 | 9 | private const string Main = Folder + "MainMenuView.tscn"; 10 | private const string InGame = Folder + "InGameMenuView.tscn"; 11 | private const string Pause = Folder + "PauseMenuView.tscn"; 12 | private const string Options = Folder + "OptionsMenuView.tscn"; 13 | private const string AudioSettings = Folder + "AudioSettingsMenuView.tscn"; 14 | private const string VideoSettings = Folder + "VideoSettingsMenuView.tscn"; 15 | private const string RebindKeys = Folder + "RebindKeysMenuView.tscn"; 16 | private const string InterfaceSettings = Folder + "InterfaceSettingsMenuView.tscn"; 17 | 18 | public static readonly Dictionary Paths = new() 19 | { 20 | { MenuType.Main, Main }, 21 | { MenuType.InGame, InGame }, 22 | { MenuType.Pause, Pause }, 23 | { MenuType.Options, Options }, 24 | { MenuType.AudioSettings, AudioSettings }, 25 | { MenuType.VideoSettings, VideoSettings }, 26 | { MenuType.RebindKeys, RebindKeys }, 27 | { MenuType.InterfaceSettings, InterfaceSettings }, 28 | }; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Enums/MenuType.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.MenuSystem; 2 | internal enum MenuType 3 | { 4 | Main = 0, 5 | InGame = 1, 6 | Pause = 2, 7 | Options = 3, 8 | AudioSettings = 4, 9 | VideoSettings = 5, 10 | RebindKeys = 6, 11 | InterfaceSettings = 7, 12 | } 13 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/MenuBackgroundController.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Helpers; 3 | 4 | namespace UISystem.MenuSystem; 5 | public class MenuBackgroundController 6 | { 7 | 8 | private readonly SceneTree _sceneTree; 9 | private readonly TextureRect _background; 10 | 11 | public MenuBackgroundController(SceneTree sceneTree, TextureRect background) 12 | { 13 | _sceneTree = sceneTree; 14 | _background = background; 15 | } 16 | 17 | public void SetBackgroundColor(Color backgroundColor) => _background.Modulate = new Color(backgroundColor, 1); 18 | 19 | public void ShowBackground(bool instant) => Fader.Show(_sceneTree, _background, null, instant); 20 | 21 | public void HideBackground(bool instant) => Fader.Hide(_sceneTree, _background, null, instant); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/MenuControllerBase.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Core.MenuSystem; 2 | using UISystem.Core.Views; 3 | using UISystem.Elements; 4 | 5 | namespace UISystem.MenuSystem; 6 | // just a base class to adapt generic controller to Godot's specific parameters 7 | // so that there is no need to specify IMenuModel, InputEvent, IFocusableControl for every controller 8 | internal abstract class MenuControllerBase 9 | : MenuController 10 | where TViewCreator : IViewCreator 11 | where TView : IMenuView 12 | { 13 | protected MenuControllerBase(TViewCreator viewCreator, IMenuModel model, IMenusManager menusManager) : base(viewCreator, model, menusManager) 14 | { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/MenuView.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Core.MenuSystem; 2 | using UISystem.Elements; 3 | using UISystem.Views; 4 | 5 | namespace UISystem.MenuSystem; 6 | public abstract partial class MenuView : ViewBase, IMenuView 7 | { 8 | 9 | private IFocusableControl _lastSelectedElement; 10 | protected abstract IFocusableControl DefaultSelectedElement { get; } 11 | 12 | public override void FocusElement() 13 | { 14 | if (_lastSelectedElement?.IsValidElement() == true) 15 | { 16 | _lastSelectedElement.SwitchFocus(true); 17 | } 18 | else if (DefaultSelectedElement?.IsValidElement() == true) 19 | { 20 | DefaultSelectedElement.SwitchFocus(true); 21 | } 22 | } 23 | 24 | public void SetLastSelectedElement(IFocusableControl lastSelectedElement) 25 | { 26 | _lastSelectedElement = lastSelectedElement; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/AudioSettings/AudioSettingsMenuController.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.MenuSystem; 3 | using UISystem.Core.PopupSystem; 4 | using UISystem.Core.Views; 5 | using UISystem.MenuSystem.Models; 6 | using UISystem.MenuSystem.SettingsMenu; 7 | using UISystem.MenuSystem.Views; 8 | using UISystem.PopupSystem; 9 | 10 | namespace UISystem.MenuSystem.Controllers; 11 | internal class AudioSettingsMenuController : SettingsMenuController, AudioSettingsMenuView, AudioSettingsMenuModel> 12 | { 13 | 14 | public override MenuType Type => MenuType.AudioSettings; 15 | 16 | public AudioSettingsMenuController(IViewCreator viewCreator, AudioSettingsMenuModel model, 17 | IMenusManager menusManager, IPopupsManager popupsManager) : base(viewCreator, model, menusManager, popupsManager) 18 | { } 19 | 20 | protected override void SetupElements() 21 | { 22 | base.SetupElements(); 23 | SetupMusicSlider(); 24 | SetupSfxSlider(); 25 | _view.SaveSettingsButton.ButtonDown += OnSaveSettingsButtonDown; 26 | } 27 | 28 | private void OnSaveSettingsButtonDown() 29 | { 30 | _model.SaveSettings(); 31 | _view.SetLastSelectedElement(_view.SaveSettingsButton); 32 | } 33 | 34 | private void SetupMusicSlider() 35 | { 36 | _view.MusicSlider.SetValueNoSignal(_model.MusicVolume); 37 | _view.MusicSlider.DragEnded += OnMusicSliderDragEnded; 38 | _view.MusicSlider.DragStarted += OnMusicSliderDragStarted; 39 | } 40 | 41 | private void OnMusicSliderDragEnded(bool dragEnded) 42 | { 43 | if (dragEnded) 44 | _model.MusicVolume = (float)_view.MusicSlider.Value; 45 | } 46 | 47 | private void OnMusicSliderDragStarted() 48 | { 49 | _model.MusicVolume = (float)_view.MusicSlider.Value; 50 | _view.SetLastSelectedElement(_view.MusicSlider); 51 | } 52 | 53 | private void SetupSfxSlider() 54 | { 55 | _view.SfxSlider.SetValueNoSignal(_model.SfxVolume); 56 | _view.SfxSlider.DragEnded += OnSfxSliderDragEnded; 57 | _view.SfxSlider.DragStarted += OnSfxSliderDragStarted; 58 | } 59 | 60 | private void OnSfxSliderDragEnded(bool dragEnded) 61 | { 62 | if (dragEnded) 63 | _model.SfxVolume = (float)_view.SfxSlider.Value; 64 | } 65 | 66 | private void OnSfxSliderDragStarted() 67 | { 68 | _model.SfxVolume = (float)_view.SfxSlider.Value; 69 | _view.SetLastSelectedElement(_view.SfxSlider); 70 | } 71 | 72 | protected override void ResetViewToDefault() 73 | { 74 | _view.MusicSlider.SetValue(_model.MusicVolume); 75 | _view.SfxSlider.SetValue(_model.SfxVolume); 76 | _view.SetLastSelectedElement(_view.ResetButton); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/AudioSettings/AudioSettingsMenuModel.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Constants; 2 | using UISystem.Core.MenuSystem; 3 | 4 | namespace UISystem.MenuSystem.Models; 5 | public class AudioSettingsMenuModel : ISettingsMenuModel 6 | { 7 | 8 | private float _lastMusicVolume; 9 | private float _lastSfxVolume; 10 | 11 | private readonly GameSettings _settings; 12 | 13 | public bool HasUnappliedSettings => MusicVolume != _lastMusicVolume || SfxVolume != _lastSfxVolume; 14 | public float MusicVolume { get => _settings.MusicVolume; set => _settings.MusicVolume = value; } 15 | public float SfxVolume { get => _settings.SfxVolume; set => _settings.SfxVolume = value; } 16 | 17 | public AudioSettingsMenuModel(GameSettings settings) 18 | { 19 | _settings = settings; 20 | RememberLastSavedSettings(); 21 | } 22 | 23 | public void ResetToDefault() 24 | { 25 | MusicVolume = ConfigData.DefaultMusicVolume; 26 | SfxVolume = ConfigData.DefaultSfxVolume; 27 | SaveSettings(); 28 | } 29 | 30 | public void SaveSettings() 31 | { 32 | RememberLastSavedSettings(); 33 | _settings.SaveAudioSettings(); 34 | } 35 | 36 | public void DiscardChanges() 37 | { 38 | MusicVolume = _lastMusicVolume; 39 | SfxVolume = _lastSfxVolume; 40 | } 41 | 42 | private void RememberLastSavedSettings() 43 | { 44 | _lastMusicVolume = MusicVolume; 45 | _lastSfxVolume = SfxVolume; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/AudioSettings/AudioSettingsMenuView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Elements; 4 | using UISystem.Elements.ElementViews; 5 | using UISystem.MenuSystem.SettingsMenu; 6 | using UISystem.Transitions; 7 | using UISystem.Transitions.Interfaces; 8 | 9 | namespace UISystem.MenuSystem.Views; 10 | public partial class AudioSettingsMenuView : SettingsMenuView 11 | { 12 | 13 | [Export] private ResizableControlView resizableControlMusic; // label container 14 | [Export] private HSliderView musicSlider; 15 | [Export] private ResizableControlView resizableControlSfx; // label container 16 | [Export] private HSliderView sfxSlider; 17 | [Export] private ButtonView saveSettingsButton; 18 | [Export] private Control panel; 19 | 20 | public HSliderView MusicSlider => musicSlider; 21 | public HSliderView SfxSlider => sfxSlider; 22 | public ButtonView SaveSettingsButton => saveSettingsButton; 23 | public Control Panel => panel; 24 | public ResizableControlView ResizableControlMusic => resizableControlMusic; 25 | public ResizableControlView ResizableControlSfx => resizableControlSfx; 26 | protected override IViewTransition CreateTransition() 27 | { 28 | return new PanelSizeTransition(this, FadeObjectsContainer, Panel, 29 | new ITweenableMenuElement[] { ReturnButton, SaveSettingsButton, ResetButton, 30 | MusicSlider, SfxSlider, ResizableControlMusic, ResizableControlSfx }); 31 | } 32 | protected override void PopulateFocusableElements() 33 | { 34 | _focusableElements = new IFocusableControl[] { MusicSlider, SfxSlider, SaveSettingsButton, ResetButton, ReturnButton }; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/InGame/InGameMenuController.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.MenuSystem; 3 | using UISystem.Core.Views; 4 | using UISystem.MenuSystem.Views; 5 | 6 | namespace UISystem.MenuSystem.Controllers; 7 | internal class InGameMenuController : MenuControllerBase, InGameMenuView> 8 | { 9 | 10 | public override MenuType Type => MenuType.InGame; 11 | 12 | public InGameMenuController(IViewCreator viewCreator, IMenuModel model, IMenusManager menusManager) : base(viewCreator, model, menusManager) 13 | { } 14 | 15 | public override void OnPauseButtonDown() 16 | { 17 | _menusManager.ShowMenu(MenuType.Pause); 18 | } 19 | 20 | protected override void SetupElements() 21 | { 22 | 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/InGame/InGameMenuModel.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Core.MenuSystem; 2 | 3 | namespace UISystem.MenuSystem.Models; 4 | public class InGameMenuModel : IMenuModel 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/InGame/InGameMenuView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Elements; 4 | using UISystem.Transitions; 5 | 6 | namespace UISystem.MenuSystem.Views; 7 | public partial class InGameMenuView : MenuView 8 | { 9 | 10 | [Export] private Control fadeObjectsContainer; 11 | 12 | public Control FadeObjectsContainer => fadeObjectsContainer; 13 | 14 | protected override IFocusableControl DefaultSelectedElement => null; 15 | 16 | protected override IViewTransition CreateTransition() 17 | { 18 | return new FadeTransition(FadeObjectsContainer); 19 | } 20 | 21 | protected override void PopulateFocusableElements() 22 | { } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/InterfaceSettings/InterfaceSettingsMenuController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UISystem.Common.Enums; 3 | using UISystem.Core.MenuSystem; 4 | using UISystem.Core.PopupSystem; 5 | using UISystem.Core.Views; 6 | using UISystem.Elements; 7 | using UISystem.Extensions; 8 | using UISystem.MenuSystem.Models; 9 | using UISystem.MenuSystem.SettingsMenu; 10 | using UISystem.MenuSystem.Views; 11 | using UISystem.PopupSystem; 12 | 13 | namespace UISystem.MenuSystem.Controllers; 14 | internal class InterfaceSettingsMenuController : SettingsMenuController, InterfaceSettingsMenuView, InterfaceSettingsMenuModel> 15 | { 16 | 17 | private readonly int _controllerIconsNumber; 18 | public override MenuType Type => MenuType.InterfaceSettings; 19 | 20 | public InterfaceSettingsMenuController(IViewCreator viewCreator, InterfaceSettingsMenuModel model, 21 | IMenusManager menusManager, IPopupsManager popupsManager) 22 | : base(viewCreator, model, menusManager, popupsManager) 23 | { 24 | _controllerIconsNumber = Enum.GetNames(typeof(ControllerIconsType)).Length; 25 | } 26 | 27 | protected override void SetupElements() 28 | { 29 | SetupControllerIconsDropdown(); 30 | base.SetupElements(); 31 | _view.SaveSettingsButton.ButtonDown += OnSaveSettingsButtonDown; 32 | } 33 | 34 | private void OnSaveSettingsButtonDown() 35 | { 36 | _model.SaveSettings(); 37 | _view.SetLastSelectedElement(_view.SaveSettingsButton); 38 | } 39 | 40 | private void SetupControllerIconsDropdown() 41 | { 42 | OptionButtonItem[] items = new OptionButtonItem[_controllerIconsNumber]; 43 | for (int i = 0; i < items.Length; i++) 44 | { 45 | var name = ((ControllerIconsType)i).ToString(); 46 | items[i] = new OptionButtonItem(name, i); 47 | } 48 | _view.ControllerIconsDropdown.AddMultipleItems(items); 49 | _view.ControllerIconsDropdown.ItemSelected += SelectControllerIconsType; 50 | _view.ControllerIconsDropdown.SelectItem((int)_model.ControllerIconsType); 51 | } 52 | 53 | private void SelectControllerIconsType(long index) 54 | { 55 | _model.SelectIconType((int)index); 56 | _view.SetLastSelectedElement(_view.ControllerIconsDropdown); 57 | } 58 | 59 | protected override void ResetViewToDefault() 60 | { 61 | _view.ControllerIconsDropdown.SelectItem((int)_model.ControllerIconsType); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/InterfaceSettings/InterfaceSettingsMenuModel.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Common.Enums; 2 | using UISystem.Constants; 3 | using UISystem.Core.MenuSystem; 4 | 5 | namespace UISystem.MenuSystem.Models; 6 | public class InterfaceSettingsMenuModel : ISettingsMenuModel 7 | { 8 | 9 | private ControllerIconsType _lastIconsType; 10 | 11 | private readonly GameSettings _settings; 12 | 13 | public bool HasUnappliedSettings => _settings.ControllerIconsType != _lastIconsType; 14 | public ControllerIconsType ControllerIconsType { get => _settings.ControllerIconsType; set => _settings.ControllerIconsType = value; } 15 | 16 | public InterfaceSettingsMenuModel(GameSettings settings) 17 | { 18 | _settings = settings; 19 | RememberLastSavedSettings(); 20 | } 21 | 22 | public void SelectIconType(int index) 23 | { 24 | ControllerIconsType = (ControllerIconsType)index; 25 | } 26 | 27 | public void SaveSettings() 28 | { 29 | RememberLastSavedSettings(); 30 | _settings.SaveInterfaceSettings(); 31 | } 32 | 33 | public void DiscardChanges() 34 | { 35 | ControllerIconsType = _lastIconsType; 36 | } 37 | 38 | public void ResetToDefault() 39 | { 40 | ControllerIconsType = ConfigData.DefaultControllerIconsType; 41 | SaveSettings(); 42 | } 43 | 44 | private void RememberLastSavedSettings() 45 | { 46 | _lastIconsType = ControllerIconsType; 47 | } 48 | 49 | } 50 | 51 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/InterfaceSettings/InterfaceSettingsMenuView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Elements; 4 | using UISystem.Elements.ElementViews; 5 | using UISystem.MenuSystem.SettingsMenu; 6 | using UISystem.Transitions; 7 | using UISystem.Transitions.Interfaces; 8 | 9 | namespace UISystem.MenuSystem.Views; 10 | public partial class InterfaceSettingsMenuView : SettingsMenuView 11 | { 12 | 13 | [Export] private DropdownView controllerIconsDropdown; 14 | [Export] private ButtonView saveSettingsButton; 15 | [Export] private Control panel; 16 | 17 | public ButtonView SaveSettingsButton => saveSettingsButton; 18 | public DropdownView ControllerIconsDropdown => controllerIconsDropdown; 19 | public Control Panel => panel; 20 | protected override IViewTransition CreateTransition() 21 | { 22 | return new PanelSizeTransition(this, FadeObjectsContainer, Panel, 23 | new ITweenableMenuElement[] { ReturnButton, ControllerIconsDropdown, SaveSettingsButton, ResetButton }); 24 | } 25 | protected override void PopulateFocusableElements() 26 | { 27 | _focusableElements = new IFocusableControl[] { ReturnButton, ControllerIconsDropdown, SaveSettingsButton, ResetButton }; 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/Main/MainMenuController.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using UISystem.Constants; 4 | using UISystem.Core.MenuSystem; 5 | using UISystem.Core.PopupSystem; 6 | using UISystem.Core.Views; 7 | using UISystem.MenuSystem.Views; 8 | using UISystem.PopupSystem; 9 | using UISystem.ScreenFade; 10 | 11 | namespace UISystem.MenuSystem.Controllers; 12 | internal class MainMenuController : MenuControllerBase, MainMenuView> 13 | { 14 | 15 | public override MenuType Type => MenuType.Main; 16 | 17 | private readonly SceneTree _sceneTree; 18 | private readonly IPopupsManager _popupsManager; 19 | private readonly MenuBackgroundController _menuBackgroundController; 20 | private readonly ScreenFadeManager _screenFadeManager; 21 | 22 | public MainMenuController(IViewCreator viewCreator, IMenuModel model, IMenusManager menusManager, 23 | SceneTree sceneTree, IPopupsManager popupsManager, ScreenFadeManager screenFadeManager, MenuBackgroundController menuBackgroundController) 24 | : base(viewCreator, model, menusManager) 25 | { 26 | _sceneTree = sceneTree; 27 | _popupsManager = popupsManager; 28 | _screenFadeManager = screenFadeManager; 29 | _menuBackgroundController = menuBackgroundController; 30 | } 31 | 32 | public override void Show(Action onComplete = null, bool instant = false) 33 | { 34 | base.Show(onComplete, instant); 35 | _menuBackgroundController.ShowBackground(instant); 36 | } 37 | 38 | public override void Hide(StackingType stackingType, Action onComplete = null, bool instant = false) 39 | { 40 | base.Hide(stackingType, onComplete, instant); 41 | if (stackingType != StackingType.Add) 42 | _menuBackgroundController.HideBackground(instant); 43 | } 44 | 45 | protected override void SetupElements() 46 | { 47 | _view.PlayButton.ButtonDown += PressedPlay; 48 | _view.OptionsButton.ButtonDown += PressedOptions; 49 | _view.QuitButton.ButtonDown += PressedQuit; 50 | } 51 | 52 | public override void OnReturnButtonDown() 53 | { 54 | if (CanReturnToPreviousMenu) 55 | ShowQuitPopup(); 56 | } 57 | 58 | private void PressedPlay() 59 | { 60 | _view.SetLastSelectedElement(_view.PlayButton); 61 | _screenFadeManager.FadeOut(() => 62 | { 63 | _menusManager.ShowMenu(MenuType.InGame, StackingType.Clear, instant: true); 64 | }); 65 | } 66 | 67 | private void PressedOptions() 68 | { 69 | _view.SetLastSelectedElement(_view.OptionsButton); 70 | _menusManager.ShowMenu(MenuType.Options); 71 | } 72 | 73 | private void PressedQuit() 74 | { 75 | _view.SetLastSelectedElement(_view.QuitButton); 76 | ShowQuitPopup(); 77 | } 78 | 79 | private void ShowQuitPopup() 80 | { 81 | SwitchInteractability(false); 82 | _popupsManager.ShowPopup(PopupType.YesNo, PopupMessages.QuitGame, (result) => 83 | { 84 | if (result == PopupResult.Yes) 85 | _sceneTree.Quit(); 86 | else if (result == PopupResult.No) 87 | SwitchInteractability(true); 88 | }); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/Main/MainMenuModel.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Core.MenuSystem; 2 | 3 | namespace UISystem.MenuSystem.Models; 4 | public class MainMenuModel : IMenuModel 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/Main/MainMenuView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Elements; 4 | using UISystem.Elements.ElementViews; 5 | using UISystem.Transitions; 6 | 7 | namespace UISystem.MenuSystem.Views; 8 | public partial class MainMenuView : MenuView 9 | { 10 | 11 | [Export] private ButtonView playButton; 12 | [Export] private ButtonView optionsButton; 13 | [Export] private ButtonView quitButton; 14 | [Export] private Control fadeObjectsContainer; 15 | 16 | public ButtonView PlayButton => playButton; 17 | public ButtonView OptionsButton => optionsButton; 18 | public ButtonView QuitButton => quitButton; 19 | public Control FadeObjectsContainer => fadeObjectsContainer; 20 | 21 | protected override IFocusableControl DefaultSelectedElement => PlayButton; 22 | 23 | protected override IViewTransition CreateTransition() 24 | { 25 | return new MainElementDropTransition(this, FadeObjectsContainer, PlayButton, new[] { OptionsButton, QuitButton }); 26 | } 27 | 28 | protected override void PopulateFocusableElements() 29 | { 30 | _focusableElements = new IFocusableControl[] { PlayButton, OptionsButton, QuitButton }; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/Options/OptionsMenuController.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.MenuSystem; 3 | using UISystem.Core.Views; 4 | using UISystem.MenuSystem.Views; 5 | 6 | namespace UISystem.MenuSystem.Controllers; 7 | internal class OptionsMenuController : MenuControllerBase, OptionsMenuView> 8 | { 9 | public override MenuType Type => MenuType.Options; 10 | public OptionsMenuController(IViewCreator viewCreator, IMenuModel model, IMenusManager menusManager) : base(viewCreator, model, menusManager) 11 | { } 12 | 13 | protected override void SetupElements() 14 | { 15 | _view.ReturnButton.ButtonDown += OnReturnButtonDown; 16 | _view.AudioSettingsButton.ButtonDown += OnAudioSettingsButtonDown; 17 | _view.VideoSettingsButton.ButtonDown += OnVideoSettingsButtonDown; 18 | _view.RebindKeysButton.ButtonDown += OnRebindKeysButtonDown; 19 | _view.InterfaceSettingsButton.ButtonDown += OnInterfaceSettingsButtonDown; 20 | } 21 | 22 | private void OnAudioSettingsButtonDown() 23 | { 24 | _view.SetLastSelectedElement(_view.AudioSettingsButton); 25 | _menusManager.ShowMenu(MenuType.AudioSettings); 26 | } 27 | 28 | private void OnVideoSettingsButtonDown() 29 | { 30 | _view.SetLastSelectedElement(_view.VideoSettingsButton); 31 | _menusManager.ShowMenu(MenuType.VideoSettings); 32 | } 33 | 34 | private void OnRebindKeysButtonDown() 35 | { 36 | _view.SetLastSelectedElement(_view.RebindKeysButton); 37 | _menusManager.ShowMenu(MenuType.RebindKeys); 38 | } 39 | 40 | private void OnInterfaceSettingsButtonDown() 41 | { 42 | _view.SetLastSelectedElement(_view.InterfaceSettingsButton); 43 | _menusManager.ShowMenu(MenuType.InterfaceSettings); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/Options/OptionsMenuModel.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Core.MenuSystem; 2 | 3 | namespace UISystem.MenuSystem.Models; 4 | public class OptionsMenuModel : IMenuModel 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/Options/OptionsMenuView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Elements; 4 | using UISystem.Elements.ElementViews; 5 | using UISystem.Transitions; 6 | 7 | namespace UISystem.MenuSystem.Views; 8 | public partial class OptionsMenuView : MenuView 9 | { 10 | 11 | [Export] private ButtonView interfaceSettingsButton; 12 | [Export] private ButtonView audioSettingsButton; 13 | [Export] private ButtonView videoSettingsButton; 14 | [Export] private ButtonView rebindKeysButton; 15 | [Export] private ButtonView returnButton; 16 | [Export] private Control fadeObjectsContainer; 17 | 18 | public ButtonView ReturnButton => returnButton; 19 | public ButtonView InterfaceSettingsButton => interfaceSettingsButton; 20 | public ButtonView AudioSettingsButton => audioSettingsButton; 21 | public ButtonView VideoSettingsButton => videoSettingsButton; 22 | public ButtonView RebindKeysButton => rebindKeysButton; 23 | public Control FadeObjectsContainer => fadeObjectsContainer; 24 | 25 | protected override IFocusableControl DefaultSelectedElement => InterfaceSettingsButton; 26 | 27 | protected override IViewTransition CreateTransition() 28 | { 29 | return new MainElementDropTransition(this, FadeObjectsContainer, InterfaceSettingsButton, 30 | new[] { ReturnButton, AudioSettingsButton, VideoSettingsButton, RebindKeysButton }); 31 | } 32 | protected override void PopulateFocusableElements() 33 | { 34 | _focusableElements = new IFocusableControl[] { ReturnButton, AudioSettingsButton, VideoSettingsButton, 35 | RebindKeysButton, InterfaceSettingsButton }; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/Pause/PauseMenuController.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using UISystem.Constants; 4 | using UISystem.Core.MenuSystem; 5 | using UISystem.Core.PopupSystem; 6 | using UISystem.Core.Views; 7 | using UISystem.MenuSystem.Views; 8 | using UISystem.PopupSystem; 9 | using UISystem.ScreenFade; 10 | 11 | namespace UISystem.MenuSystem.Controllers; 12 | internal class PauseMenuController : MenuControllerBase, PauseMenuView> 13 | { 14 | 15 | public override MenuType Type => MenuType.Pause; 16 | 17 | private readonly IPopupsManager _popupsManager; 18 | private readonly ScreenFadeManager _screenFadeManager; 19 | private readonly MenuBackgroundController _menuBackgroundController; 20 | 21 | public PauseMenuController(IViewCreator viewCreator, IMenuModel model, IMenusManager menusManager, 22 | IPopupsManager popupsManager, ScreenFadeManager screenFadeManager, MenuBackgroundController menuBackgroundController) 23 | : base(viewCreator, model, menusManager) 24 | { 25 | _popupsManager = popupsManager; 26 | _screenFadeManager = screenFadeManager; 27 | _menuBackgroundController = menuBackgroundController; 28 | } 29 | 30 | public override void Show(Action onComplete = null, bool instant = false) 31 | { 32 | base.Show(onComplete, instant); 33 | _menuBackgroundController.ShowBackground(instant); 34 | } 35 | 36 | public override void Hide(StackingType stackingType, Action onComplete = null, bool instant = false) 37 | { 38 | base.Hide(stackingType, () => 39 | { 40 | if (stackingType != StackingType.Add) 41 | _menuBackgroundController.HideBackground(instant); 42 | 43 | onComplete?.Invoke(); 44 | }, instant); 45 | } 46 | 47 | protected override void SetupElements() 48 | { 49 | _view.ResumeGameButton.ButtonDown += OnReturnButtonDown; 50 | _view.OptionsButton.ButtonDown += PressedOptions; 51 | _view.ReturnToMainMenuButton.ButtonDown += PressedReturn; 52 | } 53 | 54 | private void PressedOptions() 55 | { 56 | _view.SetLastSelectedElement(_view.OptionsButton); 57 | _menusManager.ShowMenu(MenuType.Options); 58 | } 59 | 60 | private void PressedReturn() 61 | { 62 | _view.SetLastSelectedElement(_view.ReturnToMainMenuButton); 63 | SwitchInteractability(false); 64 | 65 | _popupsManager.ShowPopup(PopupType.YesNo, PopupMessages.QuitToMainMenu, (result) => 66 | { 67 | if (result == PopupResult.Yes) 68 | { 69 | _screenFadeManager.FadeOut(() => 70 | { 71 | _menusManager.ShowMenu(MenuType.Main, StackingType.Clear, null, true); 72 | }); 73 | } 74 | else if (result == PopupResult.No) 75 | { 76 | SwitchInteractability(true); 77 | } 78 | }); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/Pause/PauseMenuModel.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Core.MenuSystem; 2 | 3 | namespace UISystem.MenuSystem.Models; 4 | public class PauseMenuModel : IMenuModel 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/Pause/PauseMenuView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Core.Views; 4 | using UISystem.Elements; 5 | using UISystem.Elements.ElementViews; 6 | using UISystem.Transitions; 7 | 8 | namespace UISystem.MenuSystem.Views; 9 | public partial class PauseMenuView : MenuView 10 | { 11 | 12 | [Export] private ButtonView resumeGameButton; 13 | [Export] private ButtonView optionsButton; 14 | [Export] private ButtonView returnToMainMenuButton; 15 | [Export] private Control fadeObjectsContainer; 16 | 17 | public ButtonView ResumeGameButton => resumeGameButton; 18 | public ButtonView OptionsButton => optionsButton; 19 | public ButtonView ReturnToMainMenuButton => returnToMainMenuButton; 20 | public Control FadeObjectsContainer => fadeObjectsContainer; 21 | 22 | protected override IFocusableControl DefaultSelectedElement => ResumeGameButton; 23 | 24 | protected override IViewTransition CreateTransition() 25 | { 26 | return new MainElementDropTransition(this, FadeObjectsContainer, ResumeGameButton, new[] { OptionsButton, ReturnToMainMenuButton }); 27 | } 28 | 29 | protected override void PopulateFocusableElements() 30 | { 31 | _focusableElements = new IFocusableControl[] { ResumeGameButton, OptionsButton, ReturnToMainMenuButton }; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/RebindKeys/RebindKeysMenuController.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Constants; 3 | using UISystem.Core.Constants; 4 | using UISystem.Core.MenuSystem; 5 | using UISystem.Core.PopupSystem; 6 | using UISystem.Core.Views; 7 | using UISystem.Elements; 8 | using UISystem.Elements.ElementViews; 9 | using UISystem.MenuSystem.Models; 10 | using UISystem.MenuSystem.SettingsMenu; 11 | using UISystem.MenuSystem.Views; 12 | using UISystem.PhysicalInput; 13 | using UISystem.PopupSystem; 14 | 15 | namespace UISystem.MenuSystem.Controllers; 16 | internal class RebindKeysMenuController 17 | : SettingsMenuController, RebindKeysMenuView, RebindKeysMenuModel>, IRebindInputReceiver 18 | { 19 | 20 | public override MenuType Type => MenuType.RebindKeys; 21 | 22 | public RebindKeysMenuController(IViewCreator viewCreator, RebindKeysMenuModel model, 23 | IMenusManager menusManager, IPopupsManager popupsManager) 24 | : base(viewCreator, model, menusManager, popupsManager) 25 | { } 26 | 27 | public void OnAnyButtonDown(InputEvent inputEvent) 28 | { 29 | if (_model.IsRebinding) 30 | _model.RebindKey(inputEvent); 31 | } 32 | 33 | public override void OnReturnButtonDown() 34 | { 35 | if (!_model.IsRebinding) 36 | base.OnReturnButtonDown(); 37 | } 38 | 39 | private void UpdateButtonView(RebindableKeyButtonView button, string action, int index) 40 | { 41 | var actionEvent = InputMap.ActionGetEvents(action)[index]; 42 | button.TextureRect.Texture = (Texture2D)GD.Load(Icons.GetIcon(actionEvent, _model.IconsType)); 43 | } 44 | 45 | private void OnButtonDown(RebindableKeyButtonView button, string action, int index) 46 | { 47 | button.TextureRect.Texture = (Texture2D)GD.Load(Icons.EllipsisImage); 48 | _view.SetLastSelectedElement(button); 49 | SwitchInteractability(false); 50 | 51 | _model.StartRebinding(action, index, () => 52 | { 53 | SwitchRebindingButtonFocusability(button, true); 54 | UpdateButtonView(button, action, index); 55 | SwitchInteractability(true); 56 | }); 57 | } 58 | 59 | private void SwitchRebindingButtonFocusability(IFocusableControl button, bool allowFocus) 60 | { 61 | SwitchInteractability(allowFocus); 62 | if (allowFocus) 63 | { 64 | _view.GetViewport().SetInputAsHandled(); 65 | _view.SetLastSelectedElement(button); 66 | } 67 | } 68 | 69 | protected override void SetupElements() 70 | { 71 | _view.ReturnButton.ButtonDown += OnReturnButtonDown; 72 | _view.ResetButton.ButtonDown += OnResetToDefaultButtonDown; 73 | 74 | _view.MoveLeft.ButtonDown += () => 75 | OnButtonDown(_view.MoveLeft, InputsData.MoveLeft, InputsData.KeyboardEventIndex); 76 | _view.MoveLeftJoystick.ButtonDown += () => 77 | OnButtonDown(_view.MoveLeftJoystick, InputsData.MoveLeft, InputsData.JoystickEventIndex); 78 | 79 | _view.MoveRight.ButtonDown += () => 80 | OnButtonDown(_view.MoveRight, InputsData.MoveRight, InputsData.KeyboardEventIndex); 81 | _view.MoveRightJoystick.ButtonDown += () => 82 | OnButtonDown(_view.MoveRightJoystick, InputsData.MoveRight, InputsData.JoystickEventIndex); 83 | 84 | _view.Jump.ButtonDown += () => 85 | OnButtonDown(_view.Jump, InputsData.Jump, InputsData.KeyboardEventIndex); 86 | _view.JumpJoystick.ButtonDown += () => 87 | OnButtonDown(_view.JumpJoystick, InputsData.Jump, InputsData.JoystickEventIndex); 88 | 89 | UpdateAllButtonViews(); 90 | } 91 | 92 | private void UpdateAllButtonViews() 93 | { 94 | string action = InputsData.MoveLeft; 95 | UpdateButtonView(_view.MoveLeft, action, InputsData.KeyboardEventIndex); 96 | UpdateButtonView(_view.MoveLeftJoystick, action, InputsData.JoystickEventIndex); 97 | 98 | action = InputsData.MoveRight; 99 | UpdateButtonView(_view.MoveRight, action, InputsData.KeyboardEventIndex); 100 | UpdateButtonView(_view.MoveRightJoystick, action, InputsData.JoystickEventIndex); 101 | 102 | action = InputsData.Jump; 103 | UpdateButtonView(_view.Jump, action, InputsData.KeyboardEventIndex); 104 | UpdateButtonView(_view.JumpJoystick, action, InputsData.JoystickEventIndex); 105 | 106 | } 107 | 108 | protected override void ResetViewToDefault() 109 | { 110 | UpdateAllButtonViews(); 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/RebindKeys/RebindKeysMenuModel.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using Godot.Collections; 3 | using System; 4 | using UISystem.Common.Enums; 5 | using UISystem.Core.Constants; 6 | using UISystem.Core.MenuSystem; 7 | 8 | namespace UISystem.MenuSystem.Models; 9 | public class RebindKeysMenuModel : ISettingsMenuModel 10 | { 11 | 12 | private bool _isRebinding; 13 | private string _currentlyRebindingAction; 14 | private int _currentlyRebindingEventIndex; // 0 - for keyboard, 1 - for joystick 15 | private Action _onFinishedRebinding; 16 | private readonly GameSettings _settings; 17 | 18 | public bool IsRebinding => _isRebinding; 19 | 20 | public bool HasUnappliedSettings => false; 21 | public ControllerIconsType IconsType => _settings.ControllerIconsType; 22 | 23 | public RebindKeysMenuModel(GameSettings settings) 24 | { 25 | _settings = settings; 26 | } 27 | 28 | public void ResetToDefault() 29 | { 30 | _settings.ResetInputMapToDefault(); 31 | } 32 | 33 | /// 34 | /// Starts the process of rebinding a key 35 | /// 36 | /// Action to rebind 37 | /// 0 - keyboard, 1 - joystick 38 | /// 39 | public void StartRebinding(string action, int index = 0, Action onFinishedRebinding = null) 40 | { 41 | _onFinishedRebinding = onFinishedRebinding; 42 | _currentlyRebindingEventIndex = index; 43 | _currentlyRebindingAction = action; 44 | _isRebinding = true; 45 | } 46 | 47 | public void RebindKey(InputEvent key) 48 | { 49 | if (IsCancellingRebinding(key)) 50 | { 51 | EndRebinding(); 52 | return; 53 | } 54 | 55 | Array currentEvents = InputMap.ActionGetEvents(_currentlyRebindingAction); 56 | // rebinding only if input comes from corresponding device and it is not the same event as existing events 57 | // in case there are alternative events (like wasd/arrows) 58 | // TODO: maybe switch the current existing main/alt events when it is defined in different index 59 | if (!IsInputFromCorrectDevice(key) || IsEventDefinedInDifferentIndex(key, currentEvents)) 60 | { 61 | return; 62 | } 63 | 64 | currentEvents[_currentlyRebindingEventIndex] = key; 65 | _settings.SaveInputActionKey(_currentlyRebindingAction, currentEvents); 66 | 67 | EndRebinding(); 68 | } 69 | 70 | private static bool IsCancellingRebinding(InputEvent key) 71 | { 72 | bool cancel = false; 73 | if (key is InputEventKey kbPress) 74 | { 75 | if (kbPress.Keycode == Key.Escape) 76 | cancel = true; 77 | } 78 | else if (key is InputEventJoypadButton button) 79 | { 80 | if (button.ButtonIndex == JoyButton.Start) 81 | { 82 | cancel = true; 83 | } 84 | } 85 | return cancel; 86 | } 87 | 88 | private void EndRebinding() 89 | { 90 | _currentlyRebindingAction = ""; 91 | _isRebinding = false; 92 | _onFinishedRebinding?.Invoke(); 93 | } 94 | 95 | private bool IsInputFromCorrectDevice(InputEvent key) 96 | { 97 | return IsInputFromKeyboardMouse(key) || IsInputFromJoystick(key); 98 | } 99 | 100 | private bool IsInputFromKeyboardMouse(InputEvent key) 101 | { 102 | return (key is InputEventKey || key is InputEventMouseButton) 103 | && _currentlyRebindingEventIndex == InputsData.KeyboardEventIndex; 104 | } 105 | 106 | private bool IsInputFromJoystick(InputEvent key) 107 | { 108 | return (key is InputEventJoypadButton || key is InputEventJoypadMotion) // motion included because L2 and R2 are considered motion 109 | && _currentlyRebindingEventIndex == InputsData.JoystickEventIndex; 110 | } 111 | 112 | private bool IsEventDefinedInDifferentIndex(InputEvent key, Array currentEvents) 113 | { 114 | bool result = true; 115 | var eventToCheck = currentEvents[_currentlyRebindingEventIndex]; 116 | 117 | for (int i = 0; i < currentEvents.Count; i++) 118 | { 119 | if (key.IsMatch(eventToCheck)) // the same key that was before rebinding 120 | { 121 | result = false; 122 | break; 123 | } 124 | else if (key.IsMatch(currentEvents[i])) 125 | { 126 | break; 127 | } 128 | else if (!key.IsMatch(currentEvents[i]) && i == currentEvents.Count - 1) 129 | { 130 | result = false; 131 | } 132 | } 133 | 134 | return result; 135 | } 136 | 137 | public void SaveSettings() 138 | { 139 | // is not implemented in this setup 140 | // saving happens when player presses a key 141 | // if you want to change it - store the actions that player tried to rebind and save/discard them when the button is pressed 142 | } 143 | 144 | public void DiscardChanges() 145 | { 146 | // is not implemented in this setup 147 | // saving happens when player presses a key 148 | // if you want to change it - store the actions that player tried to rebind and save/discard them when the button is pressed 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/RebindKeys/RebindKeysMenuView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Elements; 4 | using UISystem.Elements.ElementViews; 5 | using UISystem.MenuSystem.SettingsMenu; 6 | using UISystem.Transitions; 7 | using UISystem.Transitions.Interfaces; 8 | 9 | namespace UISystem.MenuSystem.Views; 10 | public partial class RebindKeysMenuView : SettingsMenuView 11 | { 12 | 13 | [Export] private RebindableKeyButtonView moveLeft; 14 | [Export] private RebindableKeyButtonView moveLeftJoystick; 15 | [Export] private RebindableKeyButtonView moveRight; 16 | [Export] private RebindableKeyButtonView moveRightJoystick; 17 | [Export] private RebindableKeyButtonView jump; 18 | [Export] private RebindableKeyButtonView jumpJoystick; 19 | [Export] private Control panel; 20 | [Export] private ResizableControlView moveLeftLabelResizableControl; 21 | [Export] private ResizableControlView moveRightLabelResizableControl; 22 | [Export] private ResizableControlView jumpLabelResizableControl; 23 | 24 | public RebindableKeyButtonView MoveLeft => moveLeft; 25 | public RebindableKeyButtonView MoveLeftJoystick => moveLeftJoystick; 26 | public RebindableKeyButtonView MoveRight => moveRight; 27 | public RebindableKeyButtonView MoveRightJoystick => moveRightJoystick; 28 | public RebindableKeyButtonView Jump => jump; 29 | public RebindableKeyButtonView JumpJoystick => jumpJoystick; 30 | public Control Panel => panel; 31 | public ResizableControlView MoveLeftLabelResizableControl => moveLeftLabelResizableControl; 32 | public ResizableControlView MoveRightLabelResizableControl => moveRightLabelResizableControl; 33 | public ResizableControlView JumpLabelResizableControl => jumpLabelResizableControl; 34 | 35 | protected override IViewTransition CreateTransition() 36 | { 37 | return new PanelSizeTransition(this, FadeObjectsContainer, Panel, 38 | new ITweenableMenuElement[] { ReturnButton, ResetButton, 39 | MoveLeft, MoveLeftJoystick, MoveRight, MoveRightJoystick, Jump, JumpJoystick, 40 | MoveLeftLabelResizableControl, MoveRightLabelResizableControl, JumpLabelResizableControl}); 41 | } 42 | 43 | protected override void PopulateFocusableElements() 44 | { 45 | _focusableElements = new IFocusableControl[] 46 | { MoveLeft, MoveLeftJoystick, MoveRight, MoveRightJoystick, Jump, JumpJoystick, ResetButton, ReturnButton }; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/VideoSettings/VideoSettingsMenuController.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using UISystem.Core.MenuSystem; 3 | using UISystem.Core.PopupSystem; 4 | using UISystem.Core.Views; 5 | using UISystem.Elements; 6 | using UISystem.Extensions; 7 | using UISystem.MenuSystem.Models; 8 | using UISystem.MenuSystem.SettingsMenu; 9 | using UISystem.MenuSystem.Views; 10 | using UISystem.PopupSystem; 11 | 12 | namespace UISystem.MenuSystem.Controllers; 13 | internal class VideoSettingsMenuController : SettingsMenuController, VideoSettingsMenuView, VideoSettingsMenuModel> 14 | { 15 | 16 | public override MenuType Type => MenuType.VideoSettings; 17 | 18 | public VideoSettingsMenuController(IViewCreator viewCreator, VideoSettingsMenuModel model, 19 | IMenusManager menusManager, IPopupsManager popupsManager) : base(viewCreator, model, menusManager, popupsManager) 20 | { } 21 | 22 | protected override void SetupElements() 23 | { 24 | base.SetupElements(); 25 | SetupWindowModeDropdown(); 26 | SetupResolutionDropdown(); 27 | _view.SaveSettingsButton.ButtonDown += _model.SaveSettings; 28 | } 29 | 30 | private void SetupWindowModeDropdown() 31 | { 32 | var windowModeNames = _model.GetWindowModeOptionNames(); 33 | OptionButtonItem[] items = new OptionButtonItem[windowModeNames.Length]; 34 | for (int i = 0; i < items.Length; i++) 35 | { 36 | var name = Regex.Replace(windowModeNames[i].ToString(), "([A-Z])", " $1").Trim(); // to have space in ExclusiveFullscreen 37 | items[i] = new OptionButtonItem(name, i); 38 | } 39 | _view.WindowModeDropdown.AddMultipleItems(items); 40 | _view.WindowModeDropdown.SelectItem(_model.CurrenWindowModeIndex); 41 | _view.WindowModeDropdown.ItemSelected += OnWindowModeDropdownSelect; 42 | } 43 | 44 | private void SetupResolutionDropdown() 45 | { 46 | var resolutionNames = _model.GetAvailableResolutionNames(); 47 | OptionButtonItem[] items = new OptionButtonItem[resolutionNames.Length]; 48 | for (int i = 0; i < items.Length; i++) 49 | { 50 | items[i] = new OptionButtonItem(resolutionNames[i], i); 51 | } 52 | 53 | _view.ResolutionDropdown.AddMultipleItems(items); 54 | // if player resizes window, there won't be any matching resolutions 55 | // this is to prevent dropdown being empty and show some value 56 | int index = _model.CurrentResolutionIndex > 0 ? _model.CurrentResolutionIndex : 0; 57 | _view.ResolutionDropdown.SelectItem(index); 58 | _view.ResolutionDropdown.ItemSelected += OnResolutionDropdownSelect; 59 | } 60 | 61 | private void OnResolutionDropdownSelect(long index) 62 | { 63 | _model.SelectResolution((int)index); 64 | } 65 | 66 | private void OnWindowModeDropdownSelect(long index) 67 | { 68 | _model.SelectWindowMode((int)index); 69 | } 70 | 71 | protected override void ResetViewToDefault() 72 | { 73 | _view.WindowModeDropdown.SelectItem(_model.CurrenWindowModeIndex); 74 | _view.ResolutionDropdown.SelectItem(_model.CurrentResolutionIndex); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/VideoSettings/VideoSettingsMenuModel.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Constants; 3 | using UISystem.Core.MenuSystem; 4 | using static Godot.DisplayServer; 5 | 6 | namespace UISystem.MenuSystem.Models; 7 | public class VideoSettingsMenuModel : ISettingsMenuModel 8 | { 9 | 10 | private Vector2I _lastResolution; 11 | private WindowMode _lastWindowMode; 12 | 13 | private readonly GameSettings _settings; 14 | 15 | public int CurrentResolutionIndex => VideoSettings.GetResolutionIndex(_settings.Resolution, GetAvailableResolutions()); 16 | public int CurrenWindowModeIndex => VideoSettings.GetWindwoModeIndex(_settings.WindowMode); 17 | public bool HasUnappliedSettings => CurrentWindowSize != _lastResolution || _settings.WindowMode != _lastWindowMode; 18 | 19 | private static float Aspect => (float)ScreenGetSize().X / ScreenGetSize().Y; 20 | private static Vector2I CurrentWindowSize => WindowGetSize(); // to allow saving resized window 21 | 22 | public VideoSettingsMenuModel(GameSettings settings) 23 | { 24 | _settings = settings; 25 | SetVideoParameters(); 26 | RememberLastSavedSettings(); 27 | } 28 | 29 | public void SelectWindowMode(int index) 30 | { 31 | SetWindowMode(VideoSettings.WindowModeOptions[index]); 32 | } 33 | 34 | public void SelectResolution(int index) 35 | { 36 | SetResolution(GetAvailableResolutions()[index]); 37 | } 38 | 39 | public string[] GetWindowModeOptionNames() 40 | { 41 | return VideoSettings.WindowModeNames; 42 | } 43 | 44 | public string[] GetAvailableResolutionNames() 45 | { 46 | return VideoSettings.GetResolutionsNamesForAspect(Aspect); 47 | } 48 | 49 | public void SaveSettings() 50 | { 51 | if (_settings.WindowMode == WindowMode.Windowed) 52 | _settings.Resolution = CurrentWindowSize; 53 | 54 | RememberLastSavedSettings(); 55 | _settings.SaveVideoSettings(); 56 | } 57 | 58 | public void DiscardChanges() 59 | { 60 | _settings.Resolution = _lastResolution; 61 | _settings.WindowMode = _lastWindowMode; 62 | SetVideoParameters(); 63 | } 64 | 65 | public void ResetToDefault() 66 | { 67 | _settings.Resolution = ConfigData.DefaultResolution; 68 | _settings.WindowMode = ConfigData.DefaultWindowMode; 69 | SetVideoParameters(); 70 | SaveSettings(); 71 | } 72 | 73 | private void SetVideoParameters() 74 | { 75 | SetResolution(_settings.Resolution); 76 | SetWindowMode(_settings.WindowMode); 77 | } 78 | 79 | private static Vector2I[] GetAvailableResolutions() 80 | { 81 | return VideoSettings.GetResolutionsForAspect(Aspect); 82 | } 83 | 84 | private void SetResolution(Vector2I resolution) 85 | { 86 | _settings.Resolution = resolution; 87 | WindowSetSize(resolution); 88 | } 89 | 90 | private void SetWindowMode(WindowMode mode) 91 | { 92 | _settings.WindowMode = mode; 93 | WindowSetMode(mode); 94 | 95 | // if you change resolution in fullscreen, then change window mode - window will not have the resolution that was selected 96 | // this is to prevent that 97 | if (mode == WindowMode.Windowed) 98 | WindowSetSize(_settings.Resolution); 99 | } 100 | 101 | private void RememberLastSavedSettings() 102 | { 103 | _lastResolution = _settings.Resolution; 104 | _lastWindowMode = _settings.WindowMode; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Menus/VideoSettings/VideoSettingsMenuView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Elements; 4 | using UISystem.Elements.ElementViews; 5 | using UISystem.MenuSystem.SettingsMenu; 6 | using UISystem.Transitions; 7 | using UISystem.Transitions.Interfaces; 8 | 9 | namespace UISystem.MenuSystem.Views; 10 | public partial class VideoSettingsMenuView : SettingsMenuView 11 | { 12 | 13 | [Export] private DropdownView windowModeDropdown; 14 | [Export] private DropdownView resolutionDropdown; 15 | [Export] private ButtonView saveSettingsButton; 16 | [Export] private Control panel; 17 | 18 | public DropdownView WindowModeDropdown => windowModeDropdown; 19 | public DropdownView ResolutionDropdown => resolutionDropdown; 20 | public ButtonView SaveSettingsButton => saveSettingsButton; 21 | public Control Panel => panel; 22 | protected override IViewTransition CreateTransition() 23 | { 24 | return new PanelSizeTransition(this, FadeObjectsContainer, Panel, 25 | new ITweenableMenuElement[] { ReturnButton, ResolutionDropdown, WindowModeDropdown, SaveSettingsButton, ResetButton }); 26 | } 27 | 28 | protected override void PopulateFocusableElements() 29 | { 30 | _focusableElements = new IFocusableControl[] 31 | { WindowModeDropdown, ResolutionDropdown, SaveSettingsButton, ResetButton, ReturnButton }; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Prefabs/3D/ExampleViewportsFor3D.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://dfulud7842pwx"] 2 | 3 | [sub_resource type="BoxMesh" id="BoxMesh_a25ns"] 4 | 5 | [sub_resource type="PlaneMesh" id="PlaneMesh_iydxc"] 6 | 7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_s50vo"] 8 | albedo_color = Color(1, 0, 0, 1) 9 | 10 | [node name="Node3D" type="Node3D"] 11 | 12 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] 13 | transform = Transform3D(0.7449, -0.482396, 0.460889, 0.283804, 0.854296, 0.43547, -0.603804, -0.193579, 0.773271, -3.19938, 1.89428, 2.07768) 14 | light_energy = 3.369 15 | 16 | [node name="Geometry" type="Node3D" parent="."] 17 | 18 | [node name="MeshInstance3D" type="MeshInstance3D" parent="Geometry"] 19 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -3.72722) 20 | mesh = SubResource("BoxMesh_a25ns") 21 | skeleton = NodePath("") 22 | 23 | [node name="MeshInstance3D4" type="MeshInstance3D" parent="Geometry"] 24 | transform = Transform3D(7.92, 0, 0, 0, 7.92, 0, 0, 0, 7.92, 0, -0.575879, 0.118362) 25 | mesh = SubResource("PlaneMesh_iydxc") 26 | skeleton = NodePath("") 27 | 28 | [node name="MeshInstance3D3" type="MeshInstance3D" parent="Geometry"] 29 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.1833, 0, -1.97564) 30 | mesh = SubResource("BoxMesh_a25ns") 31 | skeleton = NodePath("") 32 | 33 | [node name="MeshInstance3D2" type="MeshInstance3D" parent="."] 34 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.6119, 4.76838e-07, -2.4489) 35 | layers = 2 36 | mesh = SubResource("BoxMesh_a25ns") 37 | skeleton = NodePath("../SubViewportContainer/UISubViewport") 38 | surface_material_override/0 = SubResource("StandardMaterial3D_s50vo") 39 | 40 | [node name="SubViewportContainer" type="SubViewportContainer" parent="."] 41 | offset_right = 40.0 42 | offset_bottom = 40.0 43 | 44 | [node name="WorldSubViewport" type="SubViewport" parent="SubViewportContainer"] 45 | handle_input_locally = false 46 | canvas_cull_mask = 4294967065 47 | size = Vector2i(1920, 1080) 48 | render_target_update_mode = 4 49 | 50 | [node name="Camera3D" type="Camera3D" parent="SubViewportContainer/WorldSubViewport"] 51 | transform = Transform3D(0.691627, 0, 0.722255, 0, 1, 0, -0.722255, 0, 0.691627, 2.31398, -2.38419e-07, 1.35524) 52 | cull_mask = 1 53 | 54 | [node name="UISubViewport" type="SubViewport" parent="SubViewportContainer"] 55 | transparent_bg = true 56 | handle_input_locally = false 57 | canvas_cull_mask = 4293918722 58 | size = Vector2i(1920, 1080) 59 | render_target_update_mode = 4 60 | 61 | [node name="Camera3D2" type="Camera3D" parent="SubViewportContainer/UISubViewport"] 62 | transform = Transform3D(0.691627, 0, 0.722255, 0, 1, 0, -0.722255, 0, 0.691627, 2.31398, -2.38419e-07, 1.35524) 63 | cull_mask = 2 64 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Prefabs/3D/GUIPanel3D.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://cq5278lo5txm8"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/MenuSystem/3D/GuiPanel3D.cs" id="1_s31ks"] 4 | 5 | [sub_resource type="QuadMesh" id="1"] 6 | size = Vector2(1.6, 0.9) 7 | 8 | [sub_resource type="ViewportTexture" id="ViewportTexture_m3af8"] 9 | viewport_path = NodePath("SubViewport") 10 | 11 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_a2rca"] 12 | resource_local_to_scene = true 13 | transparency = 1 14 | shading_mode = 0 15 | albedo_texture = SubResource("ViewportTexture_m3af8") 16 | 17 | [sub_resource type="BoxShape3D" id="4"] 18 | size = Vector3(1.6, 0.9, 0.1) 19 | 20 | [node name="GUIPanel3D" type="Node3D" node_paths=PackedStringArray("subViewport", "quad", "area3d", "menusParent", "popupsParent")] 21 | process_mode = 3 22 | script = ExtResource("1_s31ks") 23 | subViewport = NodePath("SubViewport") 24 | quad = NodePath("Quad") 25 | area3d = NodePath("Quad/Area3D") 26 | menusParent = NodePath("SubViewport/MenusParent") 27 | popupsParent = NodePath("SubViewport/PopupsParent") 28 | 29 | [node name="SubViewport" type="SubViewport" parent="."] 30 | transparent_bg = true 31 | gui_embed_subwindows = true 32 | canvas_cull_mask = 4293918722 33 | size = Vector2i(1920, 1080) 34 | render_target_update_mode = 4 35 | 36 | [node name="MenusParent" type="Control" parent="SubViewport"] 37 | light_mask = 2 38 | visibility_layer = 2 39 | layout_mode = 3 40 | anchors_preset = 0 41 | offset_right = 1920.0 42 | offset_bottom = 1080.0 43 | mouse_filter = 2 44 | 45 | [node name="PopupsParent" type="Control" parent="SubViewport"] 46 | light_mask = 2 47 | visibility_layer = 2 48 | layout_mode = 3 49 | anchors_preset = 0 50 | offset_right = 1920.0 51 | offset_bottom = 1080.0 52 | mouse_filter = 2 53 | 54 | [node name="Quad" type="MeshInstance3D" parent="."] 55 | layers = 2 56 | mesh = SubResource("1") 57 | surface_material_override/0 = SubResource("StandardMaterial3D_a2rca") 58 | 59 | [node name="Area3D" type="Area3D" parent="Quad"] 60 | collision_layer = 2 61 | collision_mask = 2 62 | input_capture_on_drag = true 63 | 64 | [node name="CollisionShape3D" type="CollisionShape3D" parent="Quad/Area3D"] 65 | shape = SubResource("4") 66 | 67 | [node name="UICamera3D" type="Camera3D" parent="."] 68 | transform = Transform3D(0.897081, 0, -0.441866, 0, 1, 0, 0.441866, 0, 0.897081, -0.560406, 5.96046e-08, 0.88008) 69 | cull_mask = 2 70 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Prefabs/InGameMenuView.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://cfy7wvjugk741"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/MenuSystem/Menus/InGame/InGameMenuView.cs" id="1_yoo8i"] 4 | 5 | [node name="InGameMenuView" type="Control" node_paths=PackedStringArray("fadeObjectsContainer")] 6 | light_mask = 2 7 | visibility_layer = 2 8 | layout_mode = 3 9 | anchors_preset = 15 10 | anchor_right = 1.0 11 | anchor_bottom = 1.0 12 | grow_horizontal = 2 13 | grow_vertical = 2 14 | script = ExtResource("1_yoo8i") 15 | fadeObjectsContainer = NodePath("Container") 16 | 17 | [node name="Container" type="Control" parent="."] 18 | light_mask = 2 19 | visibility_layer = 2 20 | layout_mode = 1 21 | anchors_preset = 15 22 | anchor_right = 1.0 23 | anchor_bottom = 1.0 24 | grow_horizontal = 2 25 | grow_vertical = 2 26 | 27 | [node name="Label" type="Label" parent="Container"] 28 | light_mask = 2 29 | visibility_layer = 2 30 | layout_mode = 1 31 | anchors_preset = 5 32 | anchor_left = 0.5 33 | anchor_right = 0.5 34 | offset_left = -150.0 35 | offset_right = 150.0 36 | offset_bottom = 78.0 37 | grow_horizontal = 2 38 | theme_override_font_sizes/font_size = 40 39 | text = "InGame menu" 40 | horizontal_alignment = 1 41 | vertical_alignment = 1 42 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Prefabs/MainMenuView.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://dlummbpn4khpc"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/MenuSystem/Menus/Main/MainMenuView.cs" id="1_qlhqn"] 4 | [ext_resource type="PackedScene" uid="uid://ck4an0jqn373h" path="res://UISystem/Common/Prefabs/Variants/MenuNavigationButton.tscn" id="2_ox1c7"] 5 | 6 | [node name="MainMenuView" type="Control" node_paths=PackedStringArray("playButton", "optionsButton", "quitButton", "fadeObjectsContainer")] 7 | light_mask = 2 8 | visibility_layer = 2 9 | layout_mode = 3 10 | anchors_preset = 15 11 | anchor_right = 1.0 12 | anchor_bottom = 1.0 13 | grow_horizontal = 2 14 | grow_vertical = 2 15 | script = ExtResource("1_qlhqn") 16 | playButton = NodePath("Container/ButtonsContainer/PlayButton") 17 | optionsButton = NodePath("Container/ButtonsContainer/OptionsButton") 18 | quitButton = NodePath("Container/ButtonsContainer/QuitButton") 19 | fadeObjectsContainer = NodePath("Container") 20 | 21 | [node name="Container" type="Control" parent="."] 22 | light_mask = 2 23 | visibility_layer = 2 24 | clip_contents = true 25 | layout_mode = 1 26 | anchors_preset = 15 27 | anchor_right = 1.0 28 | anchor_bottom = 1.0 29 | grow_horizontal = 2 30 | grow_vertical = 2 31 | 32 | [node name="Label" type="Label" parent="Container"] 33 | light_mask = 2 34 | visibility_layer = 2 35 | layout_mode = 1 36 | anchors_preset = 5 37 | anchor_left = 0.5 38 | anchor_right = 0.5 39 | offset_left = -150.0 40 | offset_right = 150.0 41 | offset_bottom = 78.0 42 | grow_horizontal = 2 43 | theme_override_font_sizes/font_size = 40 44 | text = "Main menu" 45 | horizontal_alignment = 1 46 | vertical_alignment = 1 47 | 48 | [node name="ButtonsContainer" type="VBoxContainer" parent="Container"] 49 | light_mask = 2 50 | visibility_layer = 2 51 | layout_mode = 1 52 | anchors_preset = -1 53 | anchor_left = 0.0910583 54 | anchor_top = 0.530556 55 | anchor_right = 0.404 56 | anchor_bottom = 0.882 57 | offset_left = 0.167999 58 | offset_right = -0.680054 59 | offset_bottom = 0.439941 60 | grow_horizontal = 2 61 | theme_override_constants/separation = 10 62 | metadata/_edit_use_anchors_ = true 63 | 64 | [node name="PlayButton" parent="Container/ButtonsContainer" instance=ExtResource("2_ox1c7")] 65 | light_mask = 2 66 | visibility_layer = 2 67 | layout_mode = 2 68 | 69 | [node name="ResizableControl" parent="Container/ButtonsContainer/PlayButton" index="0"] 70 | light_mask = 2 71 | visibility_layer = 2 72 | layout_mode = 1 73 | anchors_preset = 15 74 | anchor_right = 1.0 75 | anchor_bottom = 1.0 76 | offset_right = 0.0 77 | offset_bottom = 0.0 78 | grow_horizontal = 2 79 | grow_vertical = 2 80 | 81 | [node name="Border" parent="Container/ButtonsContainer/PlayButton/ResizableControl" index="0"] 82 | light_mask = 2 83 | visibility_layer = 2 84 | 85 | [node name="Control" parent="Container/ButtonsContainer/PlayButton/ResizableControl/Border" index="0"] 86 | light_mask = 2 87 | visibility_layer = 2 88 | 89 | [node name="InsideColor" parent="Container/ButtonsContainer/PlayButton/ResizableControl/Border/Control" index="0"] 90 | light_mask = 2 91 | visibility_layer = 2 92 | 93 | [node name="TextClipper" parent="Container/ButtonsContainer/PlayButton/ResizableControl" index="1"] 94 | light_mask = 2 95 | visibility_layer = 2 96 | 97 | [node name="Label" parent="Container/ButtonsContainer/PlayButton/ResizableControl/TextClipper" index="0"] 98 | light_mask = 2 99 | visibility_layer = 2 100 | text = "PLAY" 101 | 102 | [node name="OptionsButton" parent="Container/ButtonsContainer" instance=ExtResource("2_ox1c7")] 103 | light_mask = 2 104 | visibility_layer = 2 105 | layout_mode = 2 106 | 107 | [node name="ResizableControl" parent="Container/ButtonsContainer/OptionsButton" index="0"] 108 | light_mask = 2 109 | visibility_layer = 2 110 | layout_mode = 1 111 | anchors_preset = 15 112 | anchor_right = 1.0 113 | anchor_bottom = 1.0 114 | offset_right = 0.0 115 | offset_bottom = 0.0 116 | grow_horizontal = 2 117 | grow_vertical = 2 118 | 119 | [node name="Border" parent="Container/ButtonsContainer/OptionsButton/ResizableControl" index="0"] 120 | light_mask = 2 121 | visibility_layer = 2 122 | 123 | [node name="Control" parent="Container/ButtonsContainer/OptionsButton/ResizableControl/Border" index="0"] 124 | light_mask = 2 125 | visibility_layer = 2 126 | 127 | [node name="InsideColor" parent="Container/ButtonsContainer/OptionsButton/ResizableControl/Border/Control" index="0"] 128 | light_mask = 2 129 | visibility_layer = 2 130 | 131 | [node name="TextClipper" parent="Container/ButtonsContainer/OptionsButton/ResizableControl" index="1"] 132 | light_mask = 2 133 | visibility_layer = 2 134 | 135 | [node name="Label" parent="Container/ButtonsContainer/OptionsButton/ResizableControl/TextClipper" index="0"] 136 | light_mask = 2 137 | visibility_layer = 2 138 | text = "OPTIONS" 139 | 140 | [node name="QuitButton" parent="Container/ButtonsContainer" instance=ExtResource("2_ox1c7")] 141 | light_mask = 2 142 | visibility_layer = 2 143 | layout_mode = 2 144 | 145 | [node name="ResizableControl" parent="Container/ButtonsContainer/QuitButton" index="0"] 146 | light_mask = 2 147 | visibility_layer = 2 148 | layout_mode = 1 149 | anchors_preset = 15 150 | anchor_right = 1.0 151 | anchor_bottom = 1.0 152 | offset_right = 0.0 153 | offset_bottom = 0.0 154 | grow_horizontal = 2 155 | grow_vertical = 2 156 | 157 | [node name="Border" parent="Container/ButtonsContainer/QuitButton/ResizableControl" index="0"] 158 | light_mask = 2 159 | visibility_layer = 2 160 | 161 | [node name="Control" parent="Container/ButtonsContainer/QuitButton/ResizableControl/Border" index="0"] 162 | light_mask = 2 163 | visibility_layer = 2 164 | 165 | [node name="InsideColor" parent="Container/ButtonsContainer/QuitButton/ResizableControl/Border/Control" index="0"] 166 | light_mask = 2 167 | visibility_layer = 2 168 | 169 | [node name="TextClipper" parent="Container/ButtonsContainer/QuitButton/ResizableControl" index="1"] 170 | light_mask = 2 171 | visibility_layer = 2 172 | 173 | [node name="Label" parent="Container/ButtonsContainer/QuitButton/ResizableControl/TextClipper" index="0"] 174 | light_mask = 2 175 | visibility_layer = 2 176 | text = "QUIT" 177 | 178 | [editable path="Container/ButtonsContainer/PlayButton"] 179 | [editable path="Container/ButtonsContainer/OptionsButton"] 180 | [editable path="Container/ButtonsContainer/QuitButton"] 181 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/Prefabs/PauseMenuView.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://bs7t6acp3yhci"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/MenuSystem/Menus/Pause/PauseMenuView.cs" id="1_wuqlt"] 4 | [ext_resource type="PackedScene" uid="uid://ck4an0jqn373h" path="res://UISystem/Common/Prefabs/Variants/MenuNavigationButton.tscn" id="2_gndws"] 5 | 6 | [node name="PauseMenuView" type="Control" node_paths=PackedStringArray("resumeGameButton", "optionsButton", "returnToMainMenuButton", "fadeObjectsContainer")] 7 | light_mask = 2 8 | visibility_layer = 2 9 | layout_mode = 3 10 | anchors_preset = 15 11 | anchor_right = 1.0 12 | anchor_bottom = 1.0 13 | grow_horizontal = 2 14 | grow_vertical = 2 15 | script = ExtResource("1_wuqlt") 16 | resumeGameButton = NodePath("Container/VBoxContainer/ResumeButton") 17 | optionsButton = NodePath("Container/VBoxContainer/OptionsButton") 18 | returnToMainMenuButton = NodePath("Container/VBoxContainer/ReturnToMainMenuButton") 19 | fadeObjectsContainer = NodePath("Container") 20 | 21 | [node name="Container" type="Control" parent="."] 22 | light_mask = 2 23 | visibility_layer = 2 24 | layout_mode = 1 25 | anchors_preset = 15 26 | anchor_right = 1.0 27 | anchor_bottom = 1.0 28 | grow_horizontal = 2 29 | grow_vertical = 2 30 | 31 | [node name="Label" type="Label" parent="Container"] 32 | light_mask = 2 33 | visibility_layer = 2 34 | layout_mode = 1 35 | anchors_preset = 5 36 | anchor_left = 0.5 37 | anchor_right = 0.5 38 | offset_left = -150.0 39 | offset_right = 150.0 40 | offset_bottom = 78.0 41 | grow_horizontal = 2 42 | theme_override_font_sizes/font_size = 40 43 | text = "Pause menu" 44 | horizontal_alignment = 1 45 | vertical_alignment = 1 46 | 47 | [node name="VBoxContainer" type="VBoxContainer" parent="Container"] 48 | light_mask = 2 49 | visibility_layer = 2 50 | layout_mode = 1 51 | anchors_preset = -1 52 | anchor_left = 0.0910583 53 | anchor_top = 0.530556 54 | anchor_right = 0.404 55 | anchor_bottom = 0.882 56 | offset_left = 0.167999 57 | offset_right = -0.680054 58 | offset_bottom = 0.439941 59 | grow_horizontal = 2 60 | theme_override_constants/separation = 10 61 | metadata/_edit_use_anchors_ = true 62 | 63 | [node name="ResumeButton" parent="Container/VBoxContainer" instance=ExtResource("2_gndws")] 64 | light_mask = 2 65 | visibility_layer = 2 66 | layout_mode = 2 67 | 68 | [node name="ResizableControl" parent="Container/VBoxContainer/ResumeButton" index="0"] 69 | light_mask = 2 70 | visibility_layer = 2 71 | layout_mode = 1 72 | anchors_preset = 15 73 | anchor_right = 1.0 74 | anchor_bottom = 1.0 75 | offset_right = 0.0 76 | offset_bottom = 0.0 77 | grow_horizontal = 2 78 | grow_vertical = 2 79 | 80 | [node name="Border" parent="Container/VBoxContainer/ResumeButton/ResizableControl" index="0"] 81 | light_mask = 2 82 | visibility_layer = 2 83 | 84 | [node name="Control" parent="Container/VBoxContainer/ResumeButton/ResizableControl/Border" index="0"] 85 | light_mask = 2 86 | visibility_layer = 2 87 | 88 | [node name="InsideColor" parent="Container/VBoxContainer/ResumeButton/ResizableControl/Border/Control" index="0"] 89 | light_mask = 2 90 | visibility_layer = 2 91 | 92 | [node name="TextClipper" parent="Container/VBoxContainer/ResumeButton/ResizableControl" index="1"] 93 | light_mask = 2 94 | visibility_layer = 2 95 | 96 | [node name="Label" parent="Container/VBoxContainer/ResumeButton/ResizableControl/TextClipper" index="0"] 97 | light_mask = 2 98 | visibility_layer = 2 99 | text = "RESUME" 100 | 101 | [node name="OptionsButton" parent="Container/VBoxContainer" instance=ExtResource("2_gndws")] 102 | light_mask = 2 103 | visibility_layer = 2 104 | layout_mode = 2 105 | 106 | [node name="ResizableControl" parent="Container/VBoxContainer/OptionsButton" index="0"] 107 | light_mask = 2 108 | visibility_layer = 2 109 | layout_mode = 1 110 | anchors_preset = 15 111 | anchor_right = 1.0 112 | anchor_bottom = 1.0 113 | offset_right = 0.0 114 | offset_bottom = 0.0 115 | grow_horizontal = 2 116 | grow_vertical = 2 117 | 118 | [node name="Border" parent="Container/VBoxContainer/OptionsButton/ResizableControl" index="0"] 119 | light_mask = 2 120 | visibility_layer = 2 121 | 122 | [node name="Control" parent="Container/VBoxContainer/OptionsButton/ResizableControl/Border" index="0"] 123 | light_mask = 2 124 | visibility_layer = 2 125 | 126 | [node name="InsideColor" parent="Container/VBoxContainer/OptionsButton/ResizableControl/Border/Control" index="0"] 127 | light_mask = 2 128 | visibility_layer = 2 129 | 130 | [node name="TextClipper" parent="Container/VBoxContainer/OptionsButton/ResizableControl" index="1"] 131 | light_mask = 2 132 | visibility_layer = 2 133 | 134 | [node name="Label" parent="Container/VBoxContainer/OptionsButton/ResizableControl/TextClipper" index="0"] 135 | light_mask = 2 136 | visibility_layer = 2 137 | text = "OPTIONS" 138 | 139 | [node name="ReturnToMainMenuButton" parent="Container/VBoxContainer" instance=ExtResource("2_gndws")] 140 | light_mask = 2 141 | visibility_layer = 2 142 | layout_mode = 2 143 | 144 | [node name="ResizableControl" parent="Container/VBoxContainer/ReturnToMainMenuButton" index="0"] 145 | light_mask = 2 146 | visibility_layer = 2 147 | layout_mode = 1 148 | anchors_preset = 15 149 | anchor_right = 1.0 150 | anchor_bottom = 1.0 151 | offset_right = 0.0 152 | offset_bottom = 0.0 153 | grow_horizontal = 2 154 | grow_vertical = 2 155 | 156 | [node name="Border" parent="Container/VBoxContainer/ReturnToMainMenuButton/ResizableControl" index="0"] 157 | light_mask = 2 158 | visibility_layer = 2 159 | 160 | [node name="Control" parent="Container/VBoxContainer/ReturnToMainMenuButton/ResizableControl/Border" index="0"] 161 | light_mask = 2 162 | visibility_layer = 2 163 | 164 | [node name="InsideColor" parent="Container/VBoxContainer/ReturnToMainMenuButton/ResizableControl/Border/Control" index="0"] 165 | light_mask = 2 166 | visibility_layer = 2 167 | 168 | [node name="TextClipper" parent="Container/VBoxContainer/ReturnToMainMenuButton/ResizableControl" index="1"] 169 | light_mask = 2 170 | visibility_layer = 2 171 | 172 | [node name="Label" parent="Container/VBoxContainer/ReturnToMainMenuButton/ResizableControl/TextClipper" index="0"] 173 | light_mask = 2 174 | visibility_layer = 2 175 | text = "MAIN MENU" 176 | 177 | [editable path="Container/VBoxContainer/ResumeButton"] 178 | [editable path="Container/VBoxContainer/OptionsButton"] 179 | [editable path="Container/VBoxContainer/ReturnToMainMenuButton"] 180 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/SettingsMenu/SettingsMenuController.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Constants; 2 | using UISystem.Core.MenuSystem; 3 | using UISystem.Core.PopupSystem; 4 | using UISystem.Core.Views; 5 | using UISystem.Elements; 6 | using UISystem.PopupSystem; 7 | 8 | namespace UISystem.MenuSystem.SettingsMenu; 9 | internal abstract class SettingsMenuController 10 | : MenuController 11 | where TViewCreator : IViewCreator 12 | where TView : SettingsMenuView 13 | where TModel : ISettingsMenuModel 14 | { 15 | 16 | protected readonly IPopupsManager _popupsManager; 17 | 18 | protected SettingsMenuController(TViewCreator viewCreator, TModel model, IMenusManager menusManager, 19 | IPopupsManager popupsManager) : base(viewCreator, model, menusManager) 20 | { 21 | _popupsManager = popupsManager; 22 | } 23 | 24 | protected abstract void ResetViewToDefault(); 25 | 26 | protected override void SetupElements() 27 | { 28 | _view.ReturnButton.ButtonDown += OnReturnButtonDown; 29 | _view.ResetButton.ButtonDown += OnResetToDefaultButtonDown; 30 | } 31 | 32 | public override void OnReturnButtonDown() 33 | { 34 | if (_model.HasUnappliedSettings) 35 | { 36 | _view.SetLastSelectedElement(_view.ReturnButton); 37 | CanReceivePhysicalInput = false; 38 | SwitchInteractability(false); 39 | _popupsManager.ShowPopup(PopupType.YesNoCancel, PopupMessages.SaveChanges, (result) => 40 | { 41 | OnReturnToPreviousMenuPopupClosed(result); 42 | CanReceivePhysicalInput = true; 43 | }); 44 | } 45 | else 46 | { 47 | base.OnReturnButtonDown(); 48 | } 49 | } 50 | 51 | protected void OnReturnToPreviousMenuPopupClosed(PopupResult result) 52 | { 53 | switch (result) 54 | { 55 | case PopupResult.No: 56 | _model.DiscardChanges(); 57 | base.OnReturnButtonDown(); 58 | break; 59 | case PopupResult.Yes: 60 | _model.SaveSettings(); 61 | base.OnReturnButtonDown(); 62 | break; 63 | case PopupResult.Cancel: 64 | SwitchInteractability(true); 65 | break; 66 | default: 67 | SwitchInteractability(true); 68 | break; 69 | } 70 | } 71 | 72 | protected virtual void OnResetToDefaultButtonDown() 73 | { 74 | _view.SetLastSelectedElement(_view.ResetButton); 75 | SwitchInteractability(false); 76 | _popupsManager.ShowPopup(PopupType.YesNo, PopupMessages.ResetToDefault, (result) => 77 | { 78 | if (result == PopupResult.Yes) 79 | { 80 | _model.ResetToDefault(); 81 | ResetViewToDefault(); 82 | } 83 | SwitchInteractability(true); 84 | }); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /UISystem/MenuSystem/SettingsMenu/SettingsMenuView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Elements; 3 | using UISystem.Elements.ElementViews; 4 | 5 | namespace UISystem.MenuSystem.SettingsMenu; 6 | public abstract partial class SettingsMenuView : MenuView 7 | { 8 | 9 | [Export] protected Control fadeObjectsContainer; 10 | [Export] private ButtonView returnButton; 11 | [Export] private ButtonView resetButton; 12 | 13 | public Control FadeObjectsContainer => fadeObjectsContainer; 14 | public ButtonView ReturnButton => returnButton; 15 | public ButtonView ResetButton => resetButton; 16 | 17 | protected override IFocusableControl DefaultSelectedElement => ReturnButton; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /UISystem/PhysicalInput/IRebindInputReceiver.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.PhysicalInput; 3 | 4 | namespace UISystem.PhysicalInput; 5 | public interface IRebindInputReceiver : IInputReceiver 6 | { 7 | 8 | void OnAnyButtonDown(InputEvent inputEvent); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /UISystem/PhysicalInput/InputProcessor.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Constants; 3 | using UISystem.Core.MenuSystem; 4 | using UISystem.Core.PhysicalInput; 5 | using UISystem.Core.PopupSystem; 6 | using UISystem.MenuSystem; 7 | using UISystem.PopupSystem; 8 | 9 | namespace UISystem.PhysicalInput; 10 | internal class InputProcessor : IInputProcessor 11 | { 12 | 13 | private IInputReceiver _menuInputReceiver; 14 | private IInputReceiver _popupInputReceiver; 15 | private IInputReceiver _activeReceiver; 16 | private IRebindInputReceiver _rebindInputReceiver; 17 | 18 | public InputProcessor() 19 | { 20 | MenusManager.OnControllerSwitch += OnMenuControllerSwitch; 21 | PopupsManager.OnControllerSwitch += OnPopupControllerSwitch; 22 | } 23 | ~InputProcessor() 24 | { 25 | MenusManager.OnControllerSwitch -= OnMenuControllerSwitch; 26 | PopupsManager.OnControllerSwitch -= OnPopupControllerSwitch; 27 | } 28 | 29 | public void ProcessInput(InputEvent inputEvent) 30 | { 31 | if (_activeReceiver == null || !_activeReceiver.CanReceivePhysicalInput) 32 | return; 33 | 34 | if (inputEvent.IsActionPressed(InputsData.ReturnButton)) 35 | _activeReceiver.OnReturnButtonDown(); 36 | 37 | if (inputEvent.IsActionPressed(InputsData.PauseButton)) 38 | _activeReceiver.OnPauseButtonDown(); 39 | 40 | if (inputEvent.IsPressed()) 41 | _rebindInputReceiver?.OnAnyButtonDown(inputEvent); 42 | } 43 | 44 | private void OnPopupControllerSwitch(IInputReceiver inputReceiver) 45 | { 46 | _popupInputReceiver = inputReceiver; 47 | _activeReceiver = _popupInputReceiver ?? _menuInputReceiver; 48 | } 49 | 50 | private void OnMenuControllerSwitch(IInputReceiver inputReceiver) 51 | { 52 | _activeReceiver = _menuInputReceiver = inputReceiver; 53 | if (_activeReceiver is IRebindInputReceiver rebindInputReceiver) 54 | _rebindInputReceiver = rebindInputReceiver; 55 | else 56 | _rebindInputReceiver = null; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Constants/PopupViewsPaths.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UISystem.PopupSystem.Constants; 4 | public static class PopupViewsPaths 5 | { 6 | 7 | private const string Folder = "res://UISystem/PopupSystem/Prefabs/"; 8 | 9 | private const string Yes = Folder + "YesPopupView.tscn"; 10 | private const string YesNo = Folder + "YesNoPopupView.tscn"; 11 | private const string YesNoCancel = Folder + "YesNoCancelPopupView.tscn"; 12 | 13 | public static readonly Dictionary Paths = new() 14 | { 15 | { PopupType.Yes, Yes }, 16 | { PopupType.YesNo, YesNo }, 17 | { PopupType.YesNoCancel, YesNoCancel }, 18 | }; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Enums/PopupResult.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.PopupSystem; 2 | internal enum PopupResult 3 | { 4 | No = 0, 5 | Yes = 1, 6 | Cancel = 2, 7 | } 8 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Enums/PopupType.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.PopupSystem; 2 | public enum PopupType 3 | { 4 | Yes = 0, 5 | YesNo = 1, 6 | YesNoCancel = 2, 7 | } 8 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/PopupControllerBase.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.PopupSystem; 3 | using UISystem.Core.Views; 4 | 5 | namespace UISystem.PopupSystem; 6 | // just a base class to adapt generic controller to Godot's specific parameters 7 | // so that there is no need to specify InputEvent for every controller 8 | internal abstract class PopupControllerBase : PopupController 9 | where TViewCreator : IViewCreator 10 | where TView : IPopupView 11 | { 12 | protected PopupControllerBase(TViewCreator viewCreator, IPopupsManager popupsManager) : base(viewCreator, popupsManager) 13 | { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/PopupView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.PopupSystem; 3 | using UISystem.Elements; 4 | using UISystem.Elements.ElementViews; 5 | using UISystem.Views; 6 | 7 | namespace UISystem.PopupSystem; 8 | public abstract partial class PopupView : ViewBase, IPopupView 9 | { 10 | 11 | [Export] protected Control fadeObjectsContainer; 12 | [Export] protected Control panel; 13 | [Export] private Label messageLabel; 14 | [Export] protected ResizableControlView messageMask; 15 | 16 | public Control FadeObjectsContainer => fadeObjectsContainer; 17 | public Control Panel => panel; 18 | public Label Message { set => messageLabel = value; } 19 | public ResizableControlView MessageMask => messageMask; 20 | public abstract IFocusableControl DefaultSelectedElement { get; } 21 | 22 | public override void FocusElement() 23 | { 24 | if (DefaultSelectedElement?.IsValidElement() == true) 25 | { 26 | DefaultSelectedElement.SwitchFocus(true); 27 | } 28 | } 29 | 30 | public void SetMessage(string message) 31 | { 32 | messageLabel.Text = message; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Popups/YesNoCancelPopup/YesNoCancelPopupController.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Core.PopupSystem; 2 | using UISystem.Core.Views; 3 | using UISystem.PopupSystem.Popups.Views; 4 | 5 | namespace UISystem.PopupSystem.Popups.Controllers; 6 | internal class YesNoCancelPopupController : PopupControllerBase, YesNoCancelPopupView> 7 | { 8 | 9 | public override PopupType Type => PopupType.YesNoCancel; 10 | public override PopupResult PressedReturnPopupResult => PopupResult.Cancel; 11 | 12 | public YesNoCancelPopupController(IViewCreator viewCreator, IPopupsManager popupsManager) : base(viewCreator, popupsManager) 13 | { } 14 | 15 | protected override void SetupElements() 16 | { 17 | _view.YesButton.ButtonDown += () => _popupsManager.HidePopup(PopupResult.Yes); 18 | _view.NoButton.ButtonDown += () => _popupsManager.HidePopup(PopupResult.No); 19 | _view.CancelButton.ButtonDown += () => _popupsManager.HidePopup(PopupResult.Cancel); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Popups/YesNoCancelPopup/YesNoCancelPopupView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Elements; 4 | using UISystem.Elements.ElementViews; 5 | using UISystem.Transitions; 6 | using UISystem.Transitions.Interfaces; 7 | 8 | namespace UISystem.PopupSystem.Popups.Views; 9 | internal partial class YesNoCancelPopupView : PopupView 10 | { 11 | 12 | [Export] protected ButtonView yesButton; 13 | [Export] private ButtonView noButton; 14 | [Export] private ButtonView cancelButton; 15 | 16 | public ButtonView YesButton => yesButton; 17 | public ButtonView NoButton => noButton; 18 | public ButtonView CancelButton => cancelButton; 19 | 20 | public override IFocusableControl DefaultSelectedElement => CancelButton; 21 | protected override IViewTransition CreateTransition() 22 | { 23 | return new PanelSizeTransition(this, FadeObjectsContainer, Panel, 24 | new ITweenableMenuElement[] { YesButton, NoButton, CancelButton, MessageMask }); 25 | } 26 | protected override void PopulateFocusableElements() 27 | { 28 | _focusableElements = new IFocusableControl[] { YesButton, NoButton, CancelButton }; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Popups/YesNoPopup/YesNoPopupController.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Core.PopupSystem; 2 | using UISystem.Core.Views; 3 | using UISystem.PopupSystem.Popups.Views; 4 | 5 | namespace UISystem.PopupSystem.Popups.Controllers; 6 | internal class YesNoPopupController : PopupControllerBase, YesNoPopupView> 7 | { 8 | public override PopupType Type => PopupType.YesNo; 9 | public override PopupResult PressedReturnPopupResult => PopupResult.No; 10 | 11 | public YesNoPopupController(IViewCreator viewCreator, IPopupsManager popupsManager) : base(viewCreator, popupsManager) 12 | { } 13 | 14 | protected override void SetupElements() 15 | { 16 | _view.YesButton.ButtonDown += () => _popupsManager.HidePopup(PopupResult.Yes); 17 | _view.NoButton.ButtonDown += () => _popupsManager.HidePopup(PopupResult.No); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Popups/YesNoPopup/YesNoPopupView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Elements; 4 | using UISystem.Elements.ElementViews; 5 | using UISystem.Transitions; 6 | using UISystem.Transitions.Interfaces; 7 | 8 | namespace UISystem.PopupSystem.Popups.Views; 9 | internal partial class YesNoPopupView : PopupView 10 | { 11 | 12 | [Export] protected ButtonView yesButton; 13 | [Export] private ButtonView noButton; 14 | 15 | public ButtonView YesButton => yesButton; 16 | public ButtonView NoButton => noButton; 17 | 18 | public override IFocusableControl DefaultSelectedElement => NoButton; 19 | protected override IViewTransition CreateTransition() 20 | { 21 | return new PanelSizeTransition(this, FadeObjectsContainer, Panel, 22 | new ITweenableMenuElement[] { YesButton, NoButton, MessageMask }); 23 | } 24 | 25 | protected override void PopulateFocusableElements() 26 | { 27 | _focusableElements = new IFocusableControl[] { YesButton, NoButton }; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Popups/YesPopup/YesPopupController.cs: -------------------------------------------------------------------------------- 1 | using UISystem.Core.PopupSystem; 2 | using UISystem.Core.Views; 3 | using UISystem.PopupSystem.Popups.Views; 4 | 5 | namespace UISystem.PopupSystem.Popups.Controllers; 6 | internal class YesPopupController : PopupControllerBase, YesPopupView> 7 | { 8 | 9 | public override PopupType Type => PopupType.Yes; 10 | public override PopupResult PressedReturnPopupResult => PopupResult.Yes; 11 | 12 | public YesPopupController(IViewCreator viewCreator, IPopupsManager popupsManager) : base(viewCreator, popupsManager) 13 | { } 14 | 15 | protected override void SetupElements() 16 | { 17 | _view.YesButton.ButtonDown += () => _popupsManager.HidePopup(PopupResult.Yes); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Popups/YesPopup/YesPopupView.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.Transitions; 3 | using UISystem.Core.Views; 4 | using UISystem.Elements; 5 | using UISystem.Elements.ElementViews; 6 | using UISystem.Transitions.Interfaces; 7 | using UISystem.Transitions; 8 | 9 | namespace UISystem.PopupSystem.Popups.Views; 10 | internal partial class YesPopupView : PopupView 11 | { 12 | 13 | [Export] protected ButtonView yesButton; 14 | 15 | public ButtonView YesButton => yesButton; 16 | public override IFocusableControl DefaultSelectedElement => YesButton; 17 | 18 | protected override IViewTransition CreateTransition() 19 | { 20 | return new PanelSizeTransition(this, FadeObjectsContainer, Panel, new ITweenableMenuElement[] { YesButton, MessageMask }); 21 | } 22 | 23 | protected override void PopulateFocusableElements() 24 | { 25 | _focusableElements = new IFocusableControl[] { YesButton }; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /UISystem/PopupSystem/Prefabs/YesPopupView.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://4mgylfwefvrf"] 2 | 3 | [ext_resource type="Theme" uid="uid://bwj1we86ii4gw" path="res://UISystem/Themes/ButtonsFontTheme.tres" id="2_g8fkn"] 4 | [ext_resource type="PackedScene" uid="uid://b0ifhq3dslldh" path="res://UISystem/Common/Prefabs/Variants/MenuOptionButtonView.tscn" id="2_vcy83"] 5 | [ext_resource type="Script" path="res://UISystem/Elements/ElementViews/ResizableControlView.cs" id="3_7xdby"] 6 | [ext_resource type="Script" path="res://UISystem/PopupSystem/Popups/YesPopup/YesPopupView.cs" id="4_rbuno"] 7 | 8 | [sub_resource type="CanvasTexture" id="CanvasTexture_guta3"] 9 | 10 | [node name="YesPopup" type="Control" node_paths=PackedStringArray("yesButton", "messageMask", "fadeObjectsContainer", "panel", "messageLabel")] 11 | light_mask = 2 12 | visibility_layer = 2 13 | z_index = 30 14 | layout_mode = 3 15 | anchors_preset = 15 16 | anchor_right = 1.0 17 | anchor_bottom = 1.0 18 | grow_horizontal = 2 19 | grow_vertical = 2 20 | script = ExtResource("4_rbuno") 21 | yesButton = NodePath("FadeObjectContainer/Outline/Color/ButtonsContainer/YesButton") 22 | messageMask = NodePath("FadeObjectContainer/Outline/Color/VBoxContainer/TextMask") 23 | fadeObjectsContainer = NodePath("FadeObjectContainer") 24 | panel = NodePath("FadeObjectContainer/Outline") 25 | messageLabel = NodePath("FadeObjectContainer/Outline/Color/VBoxContainer/TextMask/Message") 26 | 27 | [node name="FadeObjectContainer" type="Control" parent="."] 28 | light_mask = 2 29 | visibility_layer = 2 30 | layout_mode = 1 31 | anchors_preset = 15 32 | anchor_right = 1.0 33 | anchor_bottom = 1.0 34 | grow_horizontal = 2 35 | grow_vertical = 2 36 | 37 | [node name="Outline" type="TextureRect" parent="FadeObjectContainer"] 38 | light_mask = 2 39 | visibility_layer = 2 40 | layout_mode = 1 41 | anchors_preset = -1 42 | anchor_left = 0.05 43 | anchor_top = 0.269 44 | anchor_right = 0.95 45 | anchor_bottom = 0.731 46 | offset_left = 0.447998 47 | offset_top = -0.312012 48 | offset_right = -0.447998 49 | offset_bottom = 0.311951 50 | grow_horizontal = 2 51 | grow_vertical = 2 52 | texture = SubResource("CanvasTexture_guta3") 53 | metadata/_edit_use_anchors_ = true 54 | 55 | [node name="Color" type="TextureRect" parent="FadeObjectContainer/Outline"] 56 | self_modulate = Color(0, 0, 0, 1) 57 | light_mask = 2 58 | visibility_layer = 2 59 | clip_contents = true 60 | layout_mode = 1 61 | anchors_preset = -1 62 | anchor_right = 1.0 63 | anchor_bottom = 1.0 64 | offset_left = 5.0 65 | offset_top = 5.0 66 | offset_right = -5.0 67 | offset_bottom = -5.0 68 | grow_horizontal = 2 69 | grow_vertical = 2 70 | texture = SubResource("CanvasTexture_guta3") 71 | 72 | [node name="VBoxContainer" type="VBoxContainer" parent="FadeObjectContainer/Outline/Color"] 73 | light_mask = 2 74 | visibility_layer = 2 75 | clip_contents = true 76 | layout_mode = 0 77 | offset_left = 91.0 78 | offset_top = 28.0 79 | offset_right = 1626.0 80 | offset_bottom = 298.0 81 | mouse_filter = 2 82 | theme = ExtResource("2_g8fkn") 83 | metadata/_edit_use_anchors_ = true 84 | 85 | [node name="TextMask" type="Control" parent="FadeObjectContainer/Outline/Color/VBoxContainer"] 86 | light_mask = 2 87 | visibility_layer = 2 88 | clip_contents = true 89 | layout_mode = 2 90 | size_flags_vertical = 3 91 | mouse_filter = 2 92 | script = ExtResource("3_7xdby") 93 | 94 | [node name="Message" type="Label" parent="FadeObjectContainer/Outline/Color/VBoxContainer/TextMask"] 95 | light_mask = 2 96 | visibility_layer = 2 97 | layout_mode = 1 98 | anchors_preset = -1 99 | anchor_left = 0.5 100 | anchor_top = 0.5 101 | anchor_right = 0.5 102 | anchor_bottom = 0.5 103 | offset_left = -767.5 104 | offset_top = -135.0 105 | offset_right = 767.5 106 | offset_bottom = 135.0 107 | grow_horizontal = 2 108 | grow_vertical = 2 109 | mouse_filter = 0 110 | theme = ExtResource("2_g8fkn") 111 | text = "Message" 112 | horizontal_alignment = 1 113 | vertical_alignment = 1 114 | autowrap_mode = 2 115 | 116 | [node name="ButtonsContainer" type="HBoxContainer" parent="FadeObjectContainer/Outline/Color"] 117 | light_mask = 2 118 | visibility_layer = 2 119 | layout_mode = 1 120 | anchors_preset = -1 121 | anchor_left = 0.356 122 | anchor_top = 0.721 123 | anchor_right = 0.644 124 | anchor_bottom = 0.941 125 | offset_left = -0.289063 126 | offset_top = -0.990051 127 | offset_right = -0.815063 128 | offset_bottom = -0.698517 129 | theme_override_constants/separation = 25 130 | 131 | [node name="YesButton" parent="FadeObjectContainer/Outline/Color/ButtonsContainer" instance=ExtResource("2_vcy83")] 132 | light_mask = 2 133 | visibility_layer = 2 134 | layout_mode = 2 135 | 136 | [node name="ResizableControl" parent="FadeObjectContainer/Outline/Color/ButtonsContainer/YesButton" index="0"] 137 | light_mask = 2 138 | visibility_layer = 2 139 | anchors_preset = 15 140 | anchor_right = 1.0 141 | anchor_bottom = 1.0 142 | offset_right = 0.0 143 | offset_bottom = 0.0 144 | grow_horizontal = 2 145 | grow_vertical = 2 146 | 147 | [node name="Border" parent="FadeObjectContainer/Outline/Color/ButtonsContainer/YesButton/ResizableControl" index="0"] 148 | light_mask = 2 149 | visibility_layer = 2 150 | 151 | [node name="Control" parent="FadeObjectContainer/Outline/Color/ButtonsContainer/YesButton/ResizableControl/Border" index="0"] 152 | light_mask = 2 153 | visibility_layer = 2 154 | 155 | [node name="InsideColor" parent="FadeObjectContainer/Outline/Color/ButtonsContainer/YesButton/ResizableControl/Border/Control" index="0"] 156 | light_mask = 2 157 | visibility_layer = 2 158 | 159 | [node name="ContentClipper" parent="FadeObjectContainer/Outline/Color/ButtonsContainer/YesButton/ResizableControl" index="1"] 160 | light_mask = 2 161 | visibility_layer = 2 162 | 163 | [node name="Label" parent="FadeObjectContainer/Outline/Color/ButtonsContainer/YesButton/ResizableControl/ContentClipper" index="0"] 164 | light_mask = 2 165 | visibility_layer = 2 166 | offset_left = -222.5 167 | offset_top = -48.5 168 | offset_right = 222.5 169 | offset_bottom = 49.5 170 | text = "OK" 171 | 172 | [editable path="FadeObjectContainer/Outline/Color/ButtonsContainer/YesButton"] 173 | -------------------------------------------------------------------------------- /UISystem/ScreenFade/ScreenFadeManager.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using UISystem.Helpers; 4 | 5 | namespace UISystem.ScreenFade; 6 | public partial class ScreenFadeManager : TextureRect 7 | { 8 | 9 | private bool _isFading; 10 | 11 | public void FadeOut(Action onFadeOutComplete = null) 12 | { 13 | if (_isFading) 14 | return; 15 | 16 | _isFading = true; 17 | MouseFilter = MouseFilterEnum.Stop; 18 | 19 | Fader.Show(GetTree(), this, () => 20 | { 21 | onFadeOutComplete?.Invoke(); 22 | 23 | Fader.Hide(GetTree(), this, () => 24 | { 25 | _isFading = false; 26 | MouseFilter = MouseFilterEnum.Ignore; 27 | }); 28 | }); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /UISystem/Styles/ButtonShape.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="StyleBoxFlat" format=3 uid="uid://d1gy2bt5uinfv"] 2 | 3 | [resource] 4 | bg_color = Color(1, 1, 1, 1) 5 | skew = Vector2(0.5, 0) 6 | -------------------------------------------------------------------------------- /UISystem/Styles/DropdownShape.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="StyleBoxFlat" format=3 uid="uid://nqg1m8r4efan"] 2 | 3 | [resource] 4 | bg_color = Color(1, 1, 1, 1) 5 | -------------------------------------------------------------------------------- /UISystem/Themes/ButtonsFontTheme.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Theme" format=3 uid="uid://bwj1we86ii4gw"] 2 | 3 | [resource] 4 | default_font_size = 55 5 | -------------------------------------------------------------------------------- /UISystem/Themes/DropdownButtonTheme.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Theme" load_steps=8 format=3 uid="uid://p3e6ki5xgue4"] 2 | 3 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_q8loe"] 4 | bg_color = Color(0, 0, 0, 1) 5 | border_width_left = 5 6 | border_width_top = 5 7 | border_width_right = 5 8 | border_width_bottom = 5 9 | border_color = Color(1, 1, 1, 1) 10 | 11 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_rei7m"] 12 | bg_color = Color(0, 0, 0, 1) 13 | border_width_left = 5 14 | border_width_top = 5 15 | border_width_right = 5 16 | border_width_bottom = 5 17 | border_color = Color(1, 1, 1, 1) 18 | 19 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5glav"] 20 | bg_color = Color(0, 0, 0, 1) 21 | border_width_left = 5 22 | border_width_top = 5 23 | border_width_right = 5 24 | border_width_bottom = 5 25 | border_color = Color(1, 1, 1, 1) 26 | 27 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_an3sj"] 28 | bg_color = Color(0, 0, 0, 1) 29 | border_width_left = 5 30 | border_width_top = 5 31 | border_width_right = 5 32 | border_width_bottom = 5 33 | border_color = Color(1, 1, 1, 1) 34 | 35 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_oecyl"] 36 | bg_color = Color(0, 0, 0, 1) 37 | border_width_left = 5 38 | border_width_top = 5 39 | border_width_right = 5 40 | border_width_bottom = 5 41 | border_color = Color(1, 1, 1, 1) 42 | 43 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_c86d3"] 44 | bg_color = Color(0, 0, 0, 1) 45 | border_width_left = 5 46 | border_width_top = 5 47 | border_width_right = 5 48 | border_width_bottom = 5 49 | border_color = Color(1, 0, 0, 1) 50 | 51 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8eh15"] 52 | bg_color = Color(0, 0, 0, 1) 53 | border_width_left = 5 54 | border_width_top = 5 55 | border_width_right = 5 56 | border_width_bottom = 5 57 | 58 | [resource] 59 | default_font_size = 55 60 | Button/styles/disabled = SubResource("StyleBoxFlat_q8loe") 61 | Button/styles/focus = SubResource("StyleBoxFlat_rei7m") 62 | Button/styles/hover = SubResource("StyleBoxFlat_5glav") 63 | Button/styles/normal = SubResource("StyleBoxFlat_an3sj") 64 | Button/styles/pressed = SubResource("StyleBoxFlat_oecyl") 65 | PopupMenu/styles/hover = SubResource("StyleBoxFlat_c86d3") 66 | PopupMenu/styles/panel = SubResource("StyleBoxFlat_8eh15") 67 | -------------------------------------------------------------------------------- /UISystem/Transitions/Enums/HorizontalDirection.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.Transitions.Enums; 2 | public enum HorizontalDirection 3 | { 4 | FromLeft = 0, 5 | FromCenter = 1, 6 | FromRight = 2, 7 | } 8 | -------------------------------------------------------------------------------- /UISystem/Transitions/Enums/VerticalDirection.cs: -------------------------------------------------------------------------------- 1 | namespace UISystem.Transitions.Enums; 2 | public enum VerticalDirection 3 | { 4 | FromTop = 0, 5 | FromCenter = 1, 6 | FromBottom = 2, 7 | } 8 | -------------------------------------------------------------------------------- /UISystem/Transitions/Extensions/TransitionTweenExtensions.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Extensions; 3 | using UISystem.Transitions.Enums; 4 | using UISystem.Transitions.Extensions; 5 | using UISystem.Transitions.Structs; 6 | 7 | namespace UISystem.Transitions.Extensions; 8 | public static class TransitionTweenExtensions 9 | { 10 | 11 | // for transitions that scale object to center 12 | public static void TweenControlSize(this Tween tween, bool parallel, Control target, Vector2 size, float duration, 13 | ResizableControlSettings settings) 14 | { 15 | if (parallel) 16 | tween.Parallel().TweenControlSize(target, size, duration); 17 | else 18 | tween.TweenControlSize(target, size, duration); 19 | 20 | float multiplierX = GetHorizontalMultiplier(settings.HorizontalDirection); 21 | float multiplierY = GetVerticalMultiplier(settings.VerticalDirection); 22 | Vector2 sizeDifference = size - settings.OriginalSize; 23 | Vector2 position = settings.OriginalPosition - sizeDifference * new Vector2(multiplierX, multiplierY); 24 | 25 | // in order to change size properly when direction is set to center or bottom/right, it needs to be parallel 26 | tween.Parallel().TweenControlPosition(target, position, duration); 27 | } 28 | 29 | private static float GetHorizontalMultiplier(HorizontalDirection direction) => direction switch 30 | { 31 | HorizontalDirection.FromLeft => 0, 32 | HorizontalDirection.FromCenter => 0.5f, 33 | HorizontalDirection.FromRight => 1, 34 | _ => 0, 35 | }; 36 | 37 | private static float GetVerticalMultiplier(VerticalDirection direction) => direction switch 38 | { 39 | VerticalDirection.FromTop => 0, 40 | VerticalDirection.FromCenter => 0.5f, 41 | VerticalDirection.FromBottom => 1, 42 | _ => 0, 43 | }; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /UISystem/Transitions/FadeTransition.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using UISystem.Core.Transitions; 4 | using UISystem.Helpers; 5 | 6 | namespace UISystem.Transitions; 7 | public class FadeTransition : IViewTransition 8 | { 9 | 10 | private SceneTree _sceneTree; 11 | private SceneTree SceneTree 12 | { 13 | get 14 | { 15 | _sceneTree ??= _target.GetTree(); 16 | return _sceneTree; 17 | } 18 | } 19 | private readonly Control _target; 20 | 21 | public FadeTransition(Control target) 22 | { 23 | _target = target; 24 | Fader.Init(_target); 25 | } 26 | 27 | public void Hide(Action onHidden, bool instant) 28 | { 29 | if(instant) 30 | { 31 | _target.Modulate = new Color(_target.Modulate, 0); 32 | onHidden?.Invoke(); 33 | return; 34 | } 35 | Fader.Hide(SceneTree, _target, onHidden, instant); 36 | } 37 | 38 | public void Show(Action onShown, bool instant) 39 | { 40 | // should always hide before showing because awaiting for parameters shows menu for a split second 41 | _target.Modulate = new Color(_target.Modulate, 0); 42 | 43 | if (instant) 44 | { 45 | _target.Modulate = new Color(_target.Modulate, 1); 46 | onShown?.Invoke(); 47 | return; 48 | } 49 | Fader.Show(SceneTree, _target, onShown, instant); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /UISystem/Transitions/Interfaces/ITweenableMenuElement.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System.Threading.Tasks; 3 | 4 | namespace UISystem.Transitions.Interfaces; 5 | public interface ITweenableMenuElement 6 | { 7 | 8 | Control PositionControl { get; } 9 | Control ResizableControl { get; } 10 | Task ResetHover(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /UISystem/Transitions/PanelSizeTransition.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using System.Threading.Tasks; 4 | using UISystem.Core.Transitions; 5 | using UISystem.Extensions; 6 | using UISystem.Transitions.Enums; 7 | using UISystem.Transitions.Extensions; 8 | using UISystem.Transitions.Interfaces; 9 | using UISystem.Transitions.Structs; 10 | 11 | namespace UISystem.Transitions; 12 | public class PanelSizeTransition : IViewTransition 13 | { 14 | 15 | private const float FadeDuration = 0.1f; 16 | protected const float PanelDuration = 0.2f; 17 | protected const float ElementsDuration = 0.1f; 18 | 19 | private SceneTree _sceneTree; 20 | private bool _initializedParameters; 21 | 22 | private ResizableControlSettings _panelSizeSettings; 23 | private ResizableControlSettings[] _elementsSizeSettings; 24 | 25 | private readonly Control _caller; 26 | private readonly Control _fadeObjectsContainer; 27 | private readonly Control _panel; 28 | private readonly ITweenableMenuElement[] _elements; 29 | private readonly float _panelDuration; 30 | private readonly float _elementsDuration; 31 | 32 | private SceneTree SceneTree 33 | { 34 | get 35 | { 36 | _sceneTree ??= _caller.GetTree(); 37 | return _sceneTree; 38 | } 39 | } 40 | 41 | public PanelSizeTransition(Control caller, Control fadeObjectsContainer, Control panel, ITweenableMenuElement[] resizableControls, 42 | float panelDuration = PanelDuration, float elementsDuration = ElementsDuration) 43 | { 44 | _caller = caller; 45 | _fadeObjectsContainer = fadeObjectsContainer; 46 | _panel = panel; 47 | _elements = resizableControls; 48 | _panelDuration = panelDuration; 49 | _elementsDuration = elementsDuration; 50 | } 51 | 52 | public async void Hide(Action onHidden, bool instant) 53 | { 54 | if (instant) 55 | { 56 | _fadeObjectsContainer.HideItem(); 57 | onHidden?.Invoke(); 58 | return; 59 | } 60 | 61 | var tasks = new Task[_elements.Length]; 62 | for (int i = 0; i < tasks.Length; i++) 63 | { 64 | tasks[i] = _elements[i].ResetHover(); 65 | } 66 | await Task.WhenAll(tasks); 67 | 68 | Tween tween = SceneTree.CreateTween(); 69 | tween.SetPauseMode(Tween.TweenPauseMode.Process); 70 | 71 | tween.SetEase(Tween.EaseType.Out); 72 | tween.SetTrans(Tween.TransitionType.Linear); 73 | for (int i = 0; i < _elements.Length; i++) 74 | { 75 | tween.TweenControlSize(true, _elements[i].ResizableControl, Vector2.Zero, _elementsDuration, _elementsSizeSettings[i]); 76 | } 77 | tween.TweenCallback(Callable.From(() => 78 | { 79 | for (int i = 0; i < _elements.Length; i++) 80 | { 81 | _elements[i].ResizableControl.HideItem(); 82 | } 83 | })); 84 | 85 | tween.SetEase(Tween.EaseType.In); 86 | tween.SetTrans(Tween.TransitionType.Back); 87 | tween.TweenControlSize(false, _panel, Vector2.Zero, _panelDuration, _panelSizeSettings); 88 | 89 | tween.SetTrans(Tween.TransitionType.Quad); 90 | tween.TweenAlpha(_fadeObjectsContainer, 0, FadeDuration); 91 | tween.Finished += () => onHidden?.Invoke(); 92 | } 93 | 94 | public async void Show(Action onShown, bool instant) 95 | { 96 | // should always hide before showing because awaiting for parameters shows menu for a split second 97 | _fadeObjectsContainer.HideItem(); 98 | 99 | if (!_initializedParameters) 100 | await InitElementParameters(); 101 | 102 | if (instant) 103 | { 104 | _panel.Size = _panelSizeSettings.OriginalSize; 105 | for (int i = 0; i < _elements.Length; i++) 106 | { 107 | _elements[i].ResizableControl.Size = _elementsSizeSettings[i].OriginalSize; 108 | _elements[i].ResizableControl.Position = _elementsSizeSettings[i].OriginalPosition; 109 | } 110 | _fadeObjectsContainer.ShowItem(); 111 | onShown?.Invoke(); 112 | return; 113 | } 114 | 115 | _panel.SetSizeAndPosition(Vector2.Zero, _panelSizeSettings.CenterPosition); 116 | for (int i = 0; i < _elements.Length; i++) 117 | { 118 | _elements[i].ResizableControl.SetSizeAndPosition(Vector2.Zero, _elementsSizeSettings[i].CenterPosition); 119 | } 120 | 121 | Tween tween = SceneTree.CreateTween(); 122 | tween.SetPauseMode(Tween.TweenPauseMode.Process); 123 | 124 | tween.SetEase(Tween.EaseType.In); 125 | tween.SetTrans(Tween.TransitionType.Linear); 126 | 127 | tween.TweenAlpha(_fadeObjectsContainer, 1, FadeDuration); 128 | tween.TweenControlSize(false, _panel, _panelSizeSettings.OriginalSize, _panelDuration, _panelSizeSettings); 129 | for (int i = 0; i < _elements.Length; i++) 130 | { 131 | bool parallel = i != 0; 132 | tween.TweenControlSize(parallel, _elements[i].ResizableControl, _elementsSizeSettings[i].OriginalSize, _elementsDuration, _elementsSizeSettings[i]); 133 | } 134 | tween.Finished += () => onShown?.Invoke(); 135 | } 136 | 137 | private async Task InitElementParameters() 138 | { 139 | await _caller.ToSignal(RenderingServer.Singleton, RenderingServerInstance.SignalName.FramePostDraw); 140 | 141 | _elementsSizeSettings = new ResizableControlSettings[_elements.Length]; 142 | var horizontalDirection = HorizontalDirection.FromCenter; 143 | var verticalDirection = VerticalDirection.FromCenter; 144 | 145 | _panelSizeSettings = new(_panel.Position, _panel.Size, horizontalDirection, verticalDirection); 146 | for (int i = 0; i < _elements.Length; i++) 147 | { 148 | _elementsSizeSettings[i] = new(_elements[i].ResizableControl.Position, _elements[i].ResizableControl.Size, horizontalDirection, verticalDirection); 149 | } 150 | _initializedParameters = true; 151 | 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /UISystem/Transitions/Structs/ResizableControlSettings.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Transitions.Enums; 3 | 4 | namespace UISystem.Transitions.Structs; 5 | public readonly struct ResizableControlSettings 6 | { 7 | 8 | public readonly Vector2 OriginalPosition = Vector2.Zero; 9 | public readonly Vector2 OriginalSize = Vector2.Zero; 10 | public readonly Vector2 CenterPosition = Vector2.Zero; 11 | public readonly HorizontalDirection HorizontalDirection = HorizontalDirection.FromLeft; 12 | public readonly VerticalDirection VerticalDirection = VerticalDirection.FromTop; 13 | public readonly bool IsInitialized = false; // using it to not tween position when settings are default 14 | 15 | public ResizableControlSettings(Vector2 originalPosition, Vector2 originalSize, 16 | HorizontalDirection horizontalDirection, 17 | VerticalDirection verticalDirection) 18 | { 19 | OriginalPosition = originalPosition; 20 | OriginalSize = originalSize; 21 | CenterPosition = originalPosition + originalSize * 0.5f; 22 | HorizontalDirection = horizontalDirection; 23 | VerticalDirection = verticalDirection; 24 | IsInitialized = true; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /UISystem/UIInstaller.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://cv5bjtd0iw8pd"] 2 | 3 | [ext_resource type="Script" path="res://UISystem/UiInstaller.cs" id="1_rgp7s"] 4 | [ext_resource type="PackedScene" uid="uid://cq5278lo5txm8" path="res://UISystem/MenuSystem/Prefabs/3D/GUIPanel3D.tscn" id="3_ufqt6"] 5 | [ext_resource type="Script" path="res://UISystem/ScreenFade/ScreenFadeManager.cs" id="4_mlvp7"] 6 | 7 | [sub_resource type="CanvasTexture" id="CanvasTexture_w1hrq"] 8 | 9 | [sub_resource type="CanvasTexture" id="CanvasTexture_vnlb0"] 10 | 11 | [node name="UIInstaller" type="Control" node_paths=PackedStringArray("menuBackground", "menusParent", "popupsParent", "screenFadeManager", "guiPanel3D")] 12 | process_mode = 3 13 | light_mask = 2 14 | visibility_layer = 2 15 | layout_mode = 3 16 | anchors_preset = 15 17 | anchor_right = 1.0 18 | anchor_bottom = 1.0 19 | grow_horizontal = 2 20 | grow_vertical = 2 21 | mouse_filter = 2 22 | script = ExtResource("1_rgp7s") 23 | menuBackground = NodePath("CanvasLayer/MenuBackground") 24 | menusParent = NodePath("CanvasLayer/MenusParent") 25 | popupsParent = NodePath("CanvasLayer/PopupsParent") 26 | screenFadeManager = NodePath("CanvasLayer/ScreenFadeManager") 27 | guiPanel3D = NodePath("GUIPanel3D") 28 | 29 | [node name="CanvasLayer" type="CanvasLayer" parent="."] 30 | 31 | [node name="MenuBackground" type="TextureRect" parent="CanvasLayer"] 32 | modulate = Color(0, 0.52549, 1, 0.521569) 33 | light_mask = 2 34 | visibility_layer = 2 35 | anchors_preset = 15 36 | anchor_right = 1.0 37 | anchor_bottom = 1.0 38 | grow_horizontal = 2 39 | grow_vertical = 2 40 | texture = SubResource("CanvasTexture_w1hrq") 41 | 42 | [node name="MenusParent" type="Control" parent="CanvasLayer"] 43 | light_mask = 2 44 | visibility_layer = 2 45 | layout_mode = 3 46 | anchors_preset = 15 47 | anchor_right = 1.0 48 | anchor_bottom = 1.0 49 | grow_horizontal = 2 50 | grow_vertical = 2 51 | mouse_filter = 2 52 | 53 | [node name="PopupsParent" type="Control" parent="CanvasLayer"] 54 | light_mask = 2 55 | visibility_layer = 2 56 | z_index = 90 57 | layout_mode = 3 58 | anchors_preset = 15 59 | anchor_right = 1.0 60 | anchor_bottom = 1.0 61 | grow_horizontal = 2 62 | grow_vertical = 2 63 | mouse_filter = 2 64 | 65 | [node name="ScreenFadeManager" type="TextureRect" parent="CanvasLayer"] 66 | modulate = Color(0, 0, 0, 0) 67 | light_mask = 2 68 | visibility_layer = 2 69 | z_index = 100 70 | anchors_preset = 15 71 | anchor_right = 1.0 72 | anchor_bottom = 1.0 73 | grow_horizontal = 2 74 | grow_vertical = 2 75 | mouse_filter = 2 76 | texture = SubResource("CanvasTexture_vnlb0") 77 | script = ExtResource("4_mlvp7") 78 | 79 | [node name="GUIPanel3D" parent="." instance=ExtResource("3_ufqt6")] 80 | -------------------------------------------------------------------------------- /UISystem/UiInstaller.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using UISystem.Core.MenuSystem; 3 | using UISystem.Core.PhysicalInput; 4 | using UISystem.Core.PopupSystem; 5 | using UISystem.MenuSystem; 6 | using UISystem.MenuSystem.Constants; 7 | using UISystem.MenuSystem.Controllers; 8 | using UISystem.MenuSystem.Models; 9 | using UISystem.MenuSystem.Views; 10 | using UISystem.PhysicalInput; 11 | using UISystem.PopupSystem; 12 | using UISystem.PopupSystem.Constants; 13 | using UISystem.PopupSystem.Popups.Controllers; 14 | using UISystem.PopupSystem.Popups.Views; 15 | using UISystem.ScreenFade; 16 | using UISystem.Views; 17 | 18 | namespace UISystem; 19 | public partial class UiInstaller : Node 20 | { 21 | 22 | public static UiInstaller Instance { get; private set; } 23 | 24 | [Export] private TextureRect menuBackground; 25 | [Export] private Node menusParent; 26 | [Export] private Node popupsParent; 27 | [Export] private ScreenFadeManager screenFadeManager; 28 | [Export] private GuiPanel3D guiPanel3D; 29 | 30 | IInputProcessor _inputProcessor; 31 | 32 | public override void _EnterTree() 33 | { 34 | Instance ??= this; 35 | } 36 | 37 | public override void _Input(InputEvent inputEvent) 38 | { 39 | _inputProcessor?.ProcessInput(inputEvent); 40 | } 41 | 42 | public void Init(GameSettings settings) 43 | { 44 | SceneTree tree = GetTree(); 45 | 46 | _inputProcessor = new InputProcessor(); 47 | 48 | var popupsManager = new PopupsManager(); 49 | var yesPopupViewCreator = new ViewCreator(GetPopupPath(PopupType.Yes), popupsParent); 50 | var yesNoPopupViewCreator = new ViewCreator(GetPopupPath(PopupType.YesNo), popupsParent); 51 | var yesNoCancelPopupViewCreator = new ViewCreator(GetPopupPath(PopupType.YesNoCancel), popupsParent); 52 | var popups = new IPopupController[] 53 | { 54 | new YesPopupController(yesPopupViewCreator, popupsManager), 55 | new YesNoPopupController(yesNoPopupViewCreator, popupsManager), 56 | new YesNoCancelPopupController(yesNoCancelPopupViewCreator, popupsManager) 57 | }; 58 | popupsManager.Init(popups); 59 | 60 | var backgroundController = new MenuBackgroundController(GetTree(), menuBackground); 61 | 62 | var menusManager = new MenusManager(); 63 | var mainMenuViewCreator = new ViewCreator(GetMenuPath(MenuType.Main), menusParent); 64 | var inGameMenuViewCreator = new ViewCreator(GetMenuPath(MenuType.InGame), menusParent); 65 | var pauseViewCreator = new ViewCreator(GetMenuPath(MenuType.Pause), menusParent); 66 | var optionsViewCreator = new ViewCreator(GetMenuPath(MenuType.Options), menusParent); 67 | var audioSettingsViewCreator = new ViewCreator(GetMenuPath(MenuType.AudioSettings), menusParent); 68 | var videoSettingsViewCreator = new ViewCreator(GetMenuPath(MenuType.VideoSettings), menusParent); 69 | var rebindKeysViewCreator = new ViewCreator(GetMenuPath(MenuType.RebindKeys), menusParent); 70 | var interfaceMenuViewCreator = new ViewCreator(GetMenuPath(MenuType.InterfaceSettings), menusParent); 71 | var menus = new IMenuController[] 72 | { 73 | new MainMenuController(mainMenuViewCreator, null, menusManager, tree, popupsManager, screenFadeManager, backgroundController), 74 | new InGameMenuController(inGameMenuViewCreator, new InGameMenuModel(), menusManager), 75 | new PauseMenuController(pauseViewCreator, null, menusManager, popupsManager, screenFadeManager, backgroundController), 76 | new OptionsMenuController(optionsViewCreator, null, menusManager), 77 | new AudioSettingsMenuController(audioSettingsViewCreator, new AudioSettingsMenuModel(settings), menusManager, popupsManager), 78 | new VideoSettingsMenuController(videoSettingsViewCreator, new VideoSettingsMenuModel(settings), menusManager, popupsManager), 79 | new RebindKeysMenuController(rebindKeysViewCreator, new RebindKeysMenuModel(settings), menusManager, popupsManager), 80 | new InterfaceSettingsMenuController(interfaceMenuViewCreator, new InterfaceSettingsMenuModel(settings), menusManager, popupsManager), 81 | }; 82 | menusManager.Init(menus); 83 | menusManager.ShowMenu(MenuType.Main, StackingType.Clear); 84 | } 85 | 86 | private static string GetMenuPath(MenuType menuType) 87 | { 88 | return MenuViewsPaths.Paths[menuType]; 89 | } 90 | 91 | private static string GetPopupPath(PopupType type) 92 | { 93 | return PopupViewsPaths.Paths[type]; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="UISystem" 14 | run/main_scene="res://UISystem/DefaultScene.tscn" 15 | config/features=PackedStringArray("4.3", "C#", "GL Compatibility") 16 | 17 | [autoload] 18 | 19 | UiInstaller="*res://UISystem/UIInstaller.tscn" 20 | 21 | [display] 22 | 23 | window/size/viewport_width=1920 24 | window/size/viewport_height=1080 25 | window/size/always_on_top=true 26 | window/stretch/mode="viewport" 27 | 28 | [dotnet] 29 | 30 | project/assembly_name="UISystem" 31 | 32 | [editor] 33 | 34 | naming/scene_name_casing=1 35 | 36 | [file_customization] 37 | 38 | folder_colors={ 39 | "res://UISystem/Common/Prefabs/": "yellow", 40 | "res://UISystem/MenuSystem/Prefabs/": "yellow", 41 | "res://UISystem/PopupSystem/Prefabs/": "yellow" 42 | } 43 | 44 | [input] 45 | 46 | ui_accept={ 47 | "deadzone": 0.5, 48 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194309,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 49 | , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 50 | , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) 51 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null) 52 | ] 53 | } 54 | ReturnToPreviousMenu={ 55 | "deadzone": 0.5, 56 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":4194305,"key_label":4194305,"unicode":0,"location":0,"echo":false,"script":null) 57 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":false,"script":null) 58 | ] 59 | } 60 | PauseButton={ 61 | "deadzone": 0.5, 62 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) 63 | ] 64 | } 65 | MoveLeft={ 66 | "deadzone": 0.5, 67 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) 68 | , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null) 69 | ] 70 | } 71 | MoveRight={ 72 | "deadzone": 0.5, 73 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) 74 | , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null) 75 | ] 76 | } 77 | Jump={ 78 | "deadzone": 0.5, 79 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) 80 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":false,"script":null) 81 | ] 82 | } 83 | 84 | [layer_names] 85 | 86 | 2d_render/layer_1="Default" 87 | 3d_render/layer_1="Default" 88 | 2d_render/layer_2="UI" 89 | 3d_render/layer_2="UI" 90 | 3d_physics/layer_1="Default" 91 | 3d_physics/layer_2="UI" 92 | 93 | [rendering] 94 | 95 | renderer/rendering_method="gl_compatibility" 96 | renderer/rendering_method.mobile="gl_compatibility" 97 | --------------------------------------------------------------------------------