├── Config ├── DefaultEditor.ini ├── DefaultGame.ini ├── DefaultEngine.ini └── DefaultInput.ini ├── Screenshots ├── Directions1.PNG ├── Directions2.png ├── Directions3.PNG ├── Directions4.PNG ├── Directions5.PNG ├── Directions6.PNG └── Directions7.PNG ├── Content ├── Sounds │ ├── Menu_OK.uasset │ ├── Menu_Hovered.uasset │ ├── Menu_OK_Cue.uasset │ └── Menu_Hovered_Cue.uasset ├── UI │ ├── MainMenu_Mixed.uasset │ ├── MainMenu_Vertical.uasset │ └── MainMenu_Horizontal.uasset └── Base │ └── Textures │ ├── Grey_Circle.uasset │ ├── Red_Circle.uasset │ ├── Green_Button.uasset │ ├── Yellow_Button.uasset │ └── Dark_Checkered_Button.uasset ├── Plugins ├── Resources │ └── Icon128.png └── MenuPadPlus │ ├── MenuPadPlus.uplugin │ └── Source │ └── MenuPadPlus │ ├── Private │ ├── GameFramework │ │ └── MyPlayerController.cpp │ ├── MenuPadPlusPrivatePCH.h │ ├── Widget │ │ ├── MenuPadPlusInterface.cpp │ │ ├── Components │ │ │ ├── MenuPadPlusPanelWidget.cpp │ │ │ ├── MenuPadPlusVerticalBox.cpp │ │ │ ├── MenuPadPlusHorizontalBox.cpp │ │ │ └── MenuPadPlusButton.cpp │ │ └── UserWidget_MenuPadPlus.cpp │ ├── MenuPadPlus.cpp │ └── Utilities │ │ └── MenuPadPlusStatics.cpp │ ├── Classes │ ├── GameFramework │ │ └── MyPlayerController.h │ ├── Widget │ │ ├── MenuPadPlusInterface.h │ │ ├── Components │ │ │ ├── MenuPadPlusHorizontalBox.h │ │ │ ├── MenuPadPlusVerticalBox.h │ │ │ ├── MenuPadPlusPanelWidget.h │ │ │ └── MenuPadPlusButton.h │ │ └── UserWidget_MenuPadPlus.h │ └── Utilities │ │ └── MenuPadPlusStatics.h │ ├── MenuPadPlus.Build.cs │ └── Public │ └── IMenuPadPlus_Implementation.h ├── MenuPadPlusExample.uproject ├── ChangeLog.txt ├── LICENSE ├── Source ├── MenuPadPlusExample │ ├── MenuPadPlusExample.h │ ├── MenuPadPlusExample.cpp │ ├── MyGameViewportClient.cpp │ ├── MenuPadPlusExampleGameModeBase.cpp │ ├── MenuPadPlusExampleGameModeBase.h │ ├── MyGameViewportClient.h │ ├── MyHUD.h │ ├── MenuPadPlusExample.Build.cs │ └── MyHUD.cpp ├── MenuPadPlusExample.Target.cs └── MenuPadPlusExampleEditor.Target.cs ├── .gitignore └── README.md /Config/DefaultEditor.ini: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Screenshots/Directions1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Screenshots/Directions1.PNG -------------------------------------------------------------------------------- /Screenshots/Directions2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Screenshots/Directions2.png -------------------------------------------------------------------------------- /Screenshots/Directions3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Screenshots/Directions3.PNG -------------------------------------------------------------------------------- /Screenshots/Directions4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Screenshots/Directions4.PNG -------------------------------------------------------------------------------- /Screenshots/Directions5.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Screenshots/Directions5.PNG -------------------------------------------------------------------------------- /Screenshots/Directions6.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Screenshots/Directions6.PNG -------------------------------------------------------------------------------- /Screenshots/Directions7.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Screenshots/Directions7.PNG -------------------------------------------------------------------------------- /Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | [/Script/EngineSettings.GeneralProjectSettings] 2 | ProjectID=19ADCEAB4A89FB941005A49122796436 3 | -------------------------------------------------------------------------------- /Content/Sounds/Menu_OK.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/Sounds/Menu_OK.uasset -------------------------------------------------------------------------------- /Plugins/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Plugins/Resources/Icon128.png -------------------------------------------------------------------------------- /Content/UI/MainMenu_Mixed.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/UI/MainMenu_Mixed.uasset -------------------------------------------------------------------------------- /Content/Sounds/Menu_Hovered.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/Sounds/Menu_Hovered.uasset -------------------------------------------------------------------------------- /Content/Sounds/Menu_OK_Cue.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/Sounds/Menu_OK_Cue.uasset -------------------------------------------------------------------------------- /Content/UI/MainMenu_Vertical.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/UI/MainMenu_Vertical.uasset -------------------------------------------------------------------------------- /Content/UI/MainMenu_Horizontal.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/UI/MainMenu_Horizontal.uasset -------------------------------------------------------------------------------- /Content/Base/Textures/Grey_Circle.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/Base/Textures/Grey_Circle.uasset -------------------------------------------------------------------------------- /Content/Base/Textures/Red_Circle.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/Base/Textures/Red_Circle.uasset -------------------------------------------------------------------------------- /Content/Sounds/Menu_Hovered_Cue.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/Sounds/Menu_Hovered_Cue.uasset -------------------------------------------------------------------------------- /Content/Base/Textures/Green_Button.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/Base/Textures/Green_Button.uasset -------------------------------------------------------------------------------- /Content/Base/Textures/Yellow_Button.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/Base/Textures/Yellow_Button.uasset -------------------------------------------------------------------------------- /Content/Base/Textures/Dark_Checkered_Button.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1robertslattery/MenuPadPlus/HEAD/Content/Base/Textures/Dark_Checkered_Button.uasset -------------------------------------------------------------------------------- /MenuPadPlusExample.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "4.21", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "MenuPadPlusExample", 9 | "Type": "Runtime", 10 | "LoadingPhase": "Default" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /ChangeLog.txt: -------------------------------------------------------------------------------- 1 | 2018-08-17: v1.0.0: 2 | + Initial Commit 3 | 4 | 2018-08-24: v1.1.0: 5 | + Improved ability to swap images and sounds 6 | + Created MyGameViewportClient class to disable outline of focused button 7 | + Fixed memory leaks in UserWidget_MenuPadPlus class 8 | + Improved OnPressed/OnHovered button delegates in MenuPadPlusButton class 9 | 10 | 2018-11-17: v1.2.0: 11 | + Updated to UE v4.21 12 | + Improved syntax to better support C++11/14 13 | 14 | 2019-03-31: v1.2.1: 15 | + Lines 98-132 in UserWidget_MenuPadPlus.h replaced with TArray structure for simplicity -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/MenuPadPlus.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion" : 3, 3 | "Version" : 1, 4 | "VersionName" : "1.0.0", 5 | "FriendlyName" : "MenuPadPlus", 6 | "Description" : "This plugin allows your UMG Blueprints to be navigated with a gamepad.", 7 | "Category" : "MenuPadPlus", 8 | "CreatedBy" : "Robert Slattery", 9 | "CreatedByURL" : "http://robert-slattery.com", 10 | "DocsURL" : "", 11 | "MarketplaceURL" : "", 12 | "SupportURL" : "", 13 | "EnabledByDefault" : true, 14 | "CanContainContent" : false, 15 | "IsBetaVersion" : false, 16 | "Installed" : false, 17 | "Modules" : 18 | [ 19 | { 20 | "Name" : "MenuPadPlus", 21 | "Type" : "Runtime", 22 | "LoadingPhase" : "PreDefault" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Robert Slattery 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 | -------------------------------------------------------------------------------- /Source/MenuPadPlusExample/MenuPadPlusExample.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | 28 | -------------------------------------------------------------------------------- /Source/MenuPadPlusExample/MenuPadPlusExample.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "MenuPadPlusExample.h" 25 | #include "Modules/ModuleManager.h" 26 | 27 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, MenuPadPlusExample, "MenuPadPlusExample" ); 28 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/GameFramework/MyPlayerController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "../../Classes/GameFramework/MyPlayerController.h" 25 | 26 | AMyPlayerController::AMyPlayerController() 27 | { 28 | bShowMouseCursor = true; 29 | } 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Source/MenuPadPlusExample/MyGameViewportClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "MyGameViewportClient.h" 25 | 26 | TOptional UMyGameViewportClient::QueryShowFocus(const EFocusCause InFocusCause) const 27 | { 28 | // Disables outline of focused button 29 | return false; 30 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | 4 | # Visual Studio 2015 user specific files 5 | .vs/ 6 | 7 | # Compiled Object files 8 | *.slo 9 | *.lo 10 | *.o 11 | *.obj 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Compiled Dynamic libraries 18 | *.so 19 | *.dylib 20 | *.dll 21 | 22 | # Fortran module files 23 | *.mod 24 | 25 | # Compiled Static libraries 26 | *.lai 27 | *.la 28 | *.a 29 | *.lib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.ipa 36 | 37 | # These project files can be generated by the engine 38 | *.xcodeproj 39 | *.xcworkspace 40 | *.sln 41 | *.suo 42 | *.opensdf 43 | *.sdf 44 | *.VC.db 45 | *.VC.opendb 46 | 47 | # Precompiled Assets 48 | SourceArt/**/*.png 49 | SourceArt/**/*.tga 50 | 51 | # Binary Files 52 | Binaries/* 53 | Plugins/*/Binaries/* 54 | 55 | # Builds 56 | Build/* 57 | 58 | # Debug 59 | Debug/ 60 | 61 | # Whitelist PakBlacklist-.txt files 62 | !Build/*/ 63 | Build/*/** 64 | !Build/*/PakBlacklist*.txt 65 | 66 | # Don't ignore icon files in Build 67 | !Build/**/*.ico 68 | 69 | # Built data for maps 70 | *_BuiltData.uasset 71 | 72 | # Configuration files generated by the Editor 73 | Saved/* 74 | 75 | # Compiled source files for the engine to use 76 | Intermediate/* 77 | Plugins/*/Intermediate/* 78 | 79 | # Cache files for the editor to use 80 | LocalDerivedDataCache/* 81 | -------------------------------------------------------------------------------- /Source/MenuPadPlusExample.Target.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | using UnrealBuildTool; 25 | using System.Collections.Generic; 26 | 27 | public class MenuPadPlusExampleTarget : TargetRules 28 | { 29 | public MenuPadPlusExampleTarget(TargetInfo Target) : base(Target) 30 | { 31 | Type = TargetType.Game; 32 | 33 | ExtraModuleNames.AddRange( new string[] { "MenuPadPlusExample" } ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Source/MenuPadPlusExampleEditor.Target.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | using UnrealBuildTool; 25 | using System.Collections.Generic; 26 | 27 | public class MenuPadPlusExampleEditorTarget : TargetRules 28 | { 29 | public MenuPadPlusExampleEditorTarget(TargetInfo Target) : base(Target) 30 | { 31 | Type = TargetType.Editor; 32 | 33 | ExtraModuleNames.AddRange( new string[] { "MenuPadPlusExample" } ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Source/MenuPadPlusExample/MenuPadPlusExampleGameModeBase.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "MenuPadPlusExampleGameModeBase.h" 25 | #include "MyHUD.h" 26 | #include "../../Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/GameFramework/MyPlayerController.h" 27 | 28 | AMenuPadPlusExampleGameModeBase::AMenuPadPlusExampleGameModeBase() 29 | { 30 | PlayerControllerClass = AMyPlayerController::StaticClass(); 31 | HUDClass = AMyHUD::StaticClass(); 32 | } 33 | -------------------------------------------------------------------------------- /Source/MenuPadPlusExample/MenuPadPlusExampleGameModeBase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "GameFramework/GameModeBase.h" 28 | #include "MenuPadPlusExampleGameModeBase.generated.h" 29 | 30 | /** 31 | * 32 | */ 33 | UCLASS() 34 | class MENUPADPLUSEXAMPLE_API AMenuPadPlusExampleGameModeBase : public AGameModeBase 35 | { 36 | GENERATED_BODY() 37 | 38 | public: 39 | 40 | AMenuPadPlusExampleGameModeBase(); 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/MenuPadPlusPrivatePCH.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "CoreUObject.h" 25 | #include "ModuleManager.h" 26 | #include "Engine.h" 27 | #include "UnrealEd.h" 28 | #include "Slate.h" 29 | 30 | // You should place include statements to your module's private header files here. You only need to 31 | // add includes for headers that are used in most of your module's source files though. 32 | #include "../Public/IMenuPadPlus_Implementation.h" 33 | -------------------------------------------------------------------------------- /Source/MenuPadPlusExample/MyGameViewportClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "Engine/GameViewportClient.h" 27 | #include "MyGameViewportClient.generated.h" 28 | 29 | UCLASS(Within=Engine, transient, config=Engine) 30 | class MENUPADPLUSEXAMPLE_API UMyGameViewportClient : public UGameViewportClient 31 | { 32 | GENERATED_BODY() 33 | 34 | public: 35 | 36 | virtual TOptional QueryShowFocus(const EFocusCause InFocusCause) const override; 37 | 38 | }; -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/GameFramework/MyPlayerController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "Runtime/Engine/Classes/GameFramework/PlayerController.h" 28 | #include "MyPlayerController.generated.h" 29 | 30 | /** 31 | * 32 | */ 33 | UCLASS() 34 | class MENUPADPLUS_API AMyPlayerController : public APlayerController 35 | { 36 | GENERATED_BODY() 37 | 38 | public: 39 | 40 | AMyPlayerController(); 41 | 42 | 43 | }; 44 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/Widget/MenuPadPlusInterface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "../../Classes/Widget/MenuPadPlusInterface.h" 25 | #include "../../Classes/Widget/Components/MenuPadPlusButton.h" 26 | #include "Runtime/Engine/Classes/GameFramework/PlayerController.h" 27 | #include "../../Classes/GameFramework/MyPlayerController.h" 28 | 29 | // Startup Interface 30 | void IMenuPadPlusInterface::Startup() 31 | { 32 | UnBindData(); 33 | BindData(); 34 | if (!bInitialized) bInitialized = true; 35 | } 36 | 37 | // Shutdown Interface 38 | void IMenuPadPlusInterface::Shutdown() 39 | { 40 | UnBindData(); 41 | ResetAllWidgetFocus(); 42 | if (bInitialized) bInitialized = false; 43 | if (bIsActive) bIsActive = false; 44 | } -------------------------------------------------------------------------------- /Source/MenuPadPlusExample/MyHUD.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "GameFramework/HUD.h" 28 | #include "MyHUD.generated.h" 29 | 30 | /** 31 | * 32 | */ 33 | UCLASS() 34 | class MENUPADPLUSEXAMPLE_API AMyHUD : public AHUD 35 | { 36 | GENERATED_BODY() 37 | 38 | public: 39 | 40 | AMyHUD(); 41 | 42 | protected: 43 | 44 | //~ Begin Actor Interface 45 | virtual void BeginPlay() override; 46 | //~ End Actor Interface 47 | 48 | public: 49 | 50 | //~ Begin MenuPadPlus 51 | // Widget Blueprint Class 52 | UPROPERTY() 53 | TSubclassOf MenuWidgetBlueprint; 54 | 55 | // Create Widget Method 56 | void InitMenuPadPlus(); 57 | //~ End MenuPadPlus 58 | 59 | private: 60 | 61 | const static int32 PLAYER_CONTROLLER_INDEX; 62 | 63 | }; 64 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/MenuPadPlus.Build.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | using System.IO; 25 | 26 | namespace UnrealBuildTool.Rules 27 | { 28 | public class MenuPadPlus : ModuleRules 29 | { 30 | public MenuPadPlus(ReadOnlyTargetRules Target) : base(Target) 31 | { 32 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 33 | bEnableShadowVariableWarnings = false; 34 | 35 | PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Public")); 36 | PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Classes")); 37 | 38 | PrivateIncludePaths.AddRange(new string[] { "MenuPadPlus/Private" }); 39 | 40 | PublicDependencyModuleNames.AddRange(new string[]{ "Core", "CoreUObject", "Engine", "InputCore", "UnrealEd", "UMG", "MenuPadPlus" }); 41 | 42 | PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 43 | } 44 | } 45 | } 46 | /// -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/MenuPadPlus.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "CoreMinimal.h" 25 | #include "Engine.h" 26 | #include "Modules/ModuleManager.h" 27 | #include "MenuPadPlusPrivatePCH.h" 28 | #include "../Public/IMenuPadPlus_Implementation.h" 29 | #include "UnrealEd.h" 30 | 31 | DEFINE_LOG_CATEGORY(MenuPadPlusLog); 32 | 33 | #define LOCTEXT_NAMESPACE "MenuPadPlus" 34 | 35 | class FMenuPadPlus : public IMenuPadPlus_Implementation 36 | { 37 | /** IModuleInterface implementation */ 38 | virtual void StartupModule() override; 39 | virtual void ShutdownModule() override; 40 | // End IModuleInterface implementation 41 | 42 | }; 43 | 44 | void FMenuPadPlus::StartupModule() 45 | { 46 | // This code will execute after your module is loaded into memory (but after global variables are initialized, of course.) 47 | UE_LOG(MenuPadPlusLog, Warning, TEXT("MenuPadPlus: Log Started")); 48 | 49 | } 50 | 51 | void FMenuPadPlus::ShutdownModule() 52 | { 53 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 54 | // we call this function before unloading the module. 55 | UE_LOG(MenuPadPlusLog, Warning, TEXT("MenuPadPlus: Log Ended")); 56 | 57 | } 58 | 59 | IMPLEMENT_MODULE(FMenuPadPlus, MenuPadPlus) 60 | 61 | #undef LOCTEXT_NAMESPACE 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /Source/MenuPadPlusExample/MenuPadPlusExample.Build.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | using UnrealBuildTool; 25 | 26 | public class MenuPadPlusExample : ModuleRules 27 | { 28 | public MenuPadPlusExample(ReadOnlyTargetRules Target) : base(Target) 29 | { 30 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 31 | 32 | PublicIncludePaths.AddRange(new string[] { "Game/../../Plugins/MenuPadPlus/Source/MenuPadPlus/Public", 33 | "Game/../../Plugins/MenuPadPlus/Source/MenuPadPlus/Classes"}); 34 | 35 | PrivateIncludePaths.AddRange(new string[] { "Game/../../Plugins/MenuPadPlus/Source/MenuPadPlus/Private" }); 36 | 37 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG", "MenuPadPlus" }); 38 | 39 | // Uncomment if you are using Slate UI 40 | PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 41 | 42 | // Uncomment if you are using Slate UI 43 | // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 44 | 45 | // Uncomment if you are using online features 46 | // PrivateDependencyModuleNames.Add("OnlineSubsystem"); 47 | 48 | // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Public/IMenuPadPlus_Implementation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "Modules/ModuleInterface.h" 28 | #include "Modules/ModuleManager.h" 29 | 30 | DECLARE_LOG_CATEGORY_EXTERN(MenuPadPlusLog, Log, All); 31 | 32 | /** 33 | * The public interface to this module. In most cases, this interface is only public to sibling modules 34 | * within this plugin. 35 | */ 36 | class IMenuPadPlus_Implementation : public IModuleInterface 37 | { 38 | 39 | public: 40 | 41 | /** 42 | * Singleton-like access to this module's interface. This is just for convenience! 43 | * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. 44 | * 45 | * @return Returns singleton instance, loading the module on demand if needed 46 | */ 47 | static inline IMenuPadPlus_Implementation& Get() 48 | { 49 | return FModuleManager::LoadModuleChecked( "MenuPadPlus" ); 50 | } 51 | 52 | /** 53 | * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. 54 | * 55 | * @return True if the module is loaded and ready to use 56 | */ 57 | static inline bool IsAvailable() 58 | { 59 | return FModuleManager::Get().IsModuleLoaded( "MenuPadPlus" ); 60 | } 61 | }; 62 | 63 | -------------------------------------------------------------------------------- /Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | [URL] 2 | 3 | [/Script/HardwareTargeting.HardwareTargetingSettings] 4 | TargetedHardwareClass=Desktop 5 | AppliedTargetedHardwareClass=Desktop 6 | DefaultGraphicsPerformance=Maximum 7 | AppliedDefaultGraphicsPerformance=Maximum 8 | 9 | [/Script/EngineSettings.GameMapsSettings] 10 | GlobalDefaultGameMode=/Script/MenuPadPlusExample.MenuPadPlusExampleGameModeBase 11 | 12 | [/Script/Engine.Engine] 13 | GameViewportClientClassName=/Script/MenuPadPlusExample.MyGameViewportClient 14 | bUseFixedFrameRate=True 15 | 16 | [/Script/IOSRuntimeSettings.IOSRuntimeSettings] 17 | bSupportsPortraitOrientation=False 18 | bSupportsUpsideDownOrientation=False 19 | bSupportsLandscapeLeftOrientation=True 20 | PreferredLandscapeOrientation=LandscapeLeft 21 | 22 | [/Script/Engine.PhysicsSettings] 23 | DefaultGravityZ=-980.000000 24 | DefaultTerminalVelocity=4000.000000 25 | DefaultFluidFriction=0.300000 26 | SimulateScratchMemorySize=262144 27 | RagdollAggregateThreshold=4 28 | TriangleMeshTriangleMinAreaThreshold=5.000000 29 | bEnableAsyncScene=False 30 | bEnableShapeSharing=False 31 | bEnablePCM=True 32 | bEnableStabilization=False 33 | bWarnMissingLocks=True 34 | bEnable2DPhysics=False 35 | PhysicErrorCorrection=(PingExtrapolation=0.100000,PingLimit=100.000000,ErrorPerLinearDifference=1.000000,ErrorPerAngularDifference=1.000000,MaxRestoredStateError=1.000000,MaxLinearHardSnapDistance=400.000000,PositionLerp=0.000000,AngleLerp=0.400000,LinearVelocityCoefficient=100.000000,AngularVelocityCoefficient=10.000000,ErrorAccumulationSeconds=0.500000,ErrorAccumulationDistanceSq=15.000000,ErrorAccumulationSimilarity=100.000000) 36 | LockedAxis=Invalid 37 | DefaultDegreesOfFreedom=Full3D 38 | BounceThresholdVelocity=200.000000 39 | FrictionCombineMode=Average 40 | RestitutionCombineMode=Average 41 | MaxAngularVelocity=3600.000000 42 | MaxDepenetrationVelocity=0.000000 43 | ContactOffsetMultiplier=0.020000 44 | MinContactOffset=2.000000 45 | MaxContactOffset=8.000000 46 | bSimulateSkeletalMeshOnDedicatedServer=True 47 | DefaultShapeComplexity=CTF_UseSimpleAndComplex 48 | bDefaultHasComplexCollision=True 49 | bSuppressFaceRemapTable=False 50 | bSupportUVFromHitResults=False 51 | bDisableActiveActors=False 52 | bDisableKinematicStaticPairs=False 53 | bDisableKinematicKinematicPairs=False 54 | bDisableCCD=False 55 | bEnableEnhancedDeterminism=False 56 | MaxPhysicsDeltaTime=0.033333 57 | bSubstepping=False 58 | bSubsteppingAsync=False 59 | MaxSubstepDeltaTime=0.016667 60 | MaxSubsteps=6 61 | SyncSceneSmoothingFactor=0.000000 62 | AsyncSceneSmoothingFactor=0.990000 63 | InitialAverageFrameRate=0.016667 64 | PhysXTreeRebuildRate=10 65 | DefaultBroadphaseSettings=(bUseMBPOnClient=False,bUseMBPOnServer=False,MBPBounds=(Min=(X=0.000000,Y=0.000000,Z=0.000000),Max=(X=0.000000,Y=0.000000,Z=0.000000),IsValid=0),MBPNumSubdivs=2) 66 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Widget/MenuPadPlusInterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "UObject/ObjectMacros.h" 28 | #include "UObject/Object.h" 29 | #include "MenuPadPlusInterface.generated.h" 30 | 31 | class UMenuPadPlusButton; 32 | class AMyPlayerController; 33 | 34 | UINTERFACE(Blueprintable) 35 | class MENUPADPLUS_API UMenuPadPlusInterface : public UInterface { GENERATED_BODY() }; 36 | 37 | class MENUPADPLUS_API IMenuPadPlusInterface 38 | { 39 | GENERATED_BODY() 40 | 41 | public: 42 | 43 | // Interface Status Variables 44 | bool bInitialized; 45 | bool bIsActive; 46 | 47 | // Allows reference to interface derived from UObject 48 | TScriptInterface Parent; 49 | 50 | //~ Begin IMenuPadPlusInterface 51 | virtual void Startup(); 52 | virtual void Shutdown(); 53 | virtual void BindData() = 0; 54 | virtual void UnBindData() = 0; 55 | virtual UMenuPadPlusButton* GetFocusedWidget() { return nullptr; } 56 | virtual UMenuPadPlusButton* GetFirstWidget() const { return nullptr; } 57 | virtual AMyPlayerController* GetOwningPlayerController() const = 0; 58 | virtual void ResetAllWidgetFocus() = 0; 59 | virtual bool DoesContainButtons() = 0; 60 | //~ End IMenuPadPlusInterface 61 | 62 | protected: 63 | 64 | // Constructor (Allowed only for child classes) 65 | explicit IMenuPadPlusInterface() {} 66 | 67 | // Copy Constructor 68 | IMenuPadPlusInterface(const IMenuPadPlusInterface&) = delete; 69 | 70 | // Move Constructor 71 | IMenuPadPlusInterface(IMenuPadPlusInterface&&) = delete; 72 | 73 | // Copy-Assignment Operator 74 | IMenuPadPlusInterface& operator=(const IMenuPadPlusInterface&) = delete; 75 | 76 | // Move-Assignment Operator 77 | IMenuPadPlusInterface& operator=(IMenuPadPlusInterface&&) = delete; 78 | }; -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Utilities/MenuPadPlusStatics.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "UObject/ObjectMacros.h" 28 | #include "UObject/Object.h" 29 | #include "UObjectGlobals.h" 30 | #include "Kismet/BlueprintFunctionLibrary.h" 31 | #include "MenuPadPlusStatics.generated.h" 32 | 33 | class UUserWidget_MenuPadPlus; 34 | class UMenuPadPlusButton; 35 | class UMenuPadPlusInterface; 36 | 37 | /** 38 | * Static utilities for focusable buttons via MenuPadPlus 39 | */ 40 | UCLASS(Blueprintable, BlueprintType) 41 | class MENUPADPLUS_API UMenuPadPlusStatics : public UBlueprintFunctionLibrary 42 | { 43 | GENERATED_BODY() 44 | 45 | public: 46 | 47 | // Get Active Interface 48 | UFUNCTION(Category = "MenuPadPlus | Utilities", BlueprintCallable) 49 | static TScriptInterface GetActiveContainer(); 50 | 51 | // Used for changing focus on a button inside a navigable container. NOTE: Currently, only implements Text changes 52 | UFUNCTION(Category = "MenuPadPlus | Utilities", BlueprintCallable) 53 | static void SetWidgetFocus(TScriptInterface Container, UMenuPadPlusButton* NavigableWidget); 54 | 55 | // Disable All Widget Focus 56 | UFUNCTION(Category = "MenuPadPlus | Utilities", BlueprintCallable) 57 | static void ResetAllWidgetFocus(); 58 | 59 | // Get the Hovered Button Inside a Menu 60 | UFUNCTION(Category = "MenuPadPlus | Utilities", BlueprintCallable) 61 | static UMenuPadPlusButton* GetFocusedWidget(TScriptInterface Container); 62 | 63 | // Sets Focus on a Button in Menu, using a Player Controller 64 | UFUNCTION(Category = "MenuPadPlus | Utilities", BlueprintCallable) 65 | static void SetButtonFocus(class UMenuPadPlusButton* NavigableWidget, class AMyPlayerController* PlayerController); 66 | 67 | }; -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Widget/Components/MenuPadPlusHorizontalBox.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "UObject/ObjectMacros.h" 28 | #include "UObject/Object.h" 29 | #include "Widgets/SWidget.h" 30 | #include "Widgets/SBoxPanel.h" 31 | #include "MenuPadPlusPanelWidget.h" 32 | #include "MenuPadPlusHorizontalBox.generated.h" 33 | 34 | class UHorizontalBoxSlot; 35 | 36 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMenuPadPlusHorizontalBoxChangedChild, int32, ChildIndex); 37 | 38 | /** 39 | * Allows widgets to be laid out in a flow horizontally. 40 | * 41 | * * Many Children 42 | * * Flow Horizontal 43 | */ 44 | UCLASS(AutoExpandCategories = ("MenuPadPlus | Widgets"), meta = (DisplayName = "HorizontalBox")) 45 | class MENUPADPLUS_API UMenuPadPlusHorizontalBox : public UMenuPadPlusPanelWidget 46 | { 47 | GENERATED_BODY() 48 | 49 | public: 50 | 51 | // Constructor 52 | UMenuPadPlusHorizontalBox(const FObjectInitializer& ObjectInitializer); 53 | 54 | /** */ 55 | UFUNCTION(BlueprintCallable, Category = "Widget") 56 | UHorizontalBoxSlot* AddChildToHorizontalBox(UWidget* Content); 57 | 58 | #if WITH_EDITOR 59 | //~ Begin UWidget Interface 60 | virtual const FText GetPaletteCategory() override; 61 | //~ End UWidget Interface 62 | #endif 63 | 64 | virtual void ReleaseSlateResources(bool bReleaseChildren) override; 65 | 66 | protected: 67 | 68 | //~ Begin UPanelWidget 69 | virtual UClass* GetSlotClass() const override; 70 | virtual void OnSlotAdded(UPanelSlot* Slot) override; 71 | virtual void OnSlotRemoved(UPanelSlot* Slot) override; 72 | //~ End UPanelWidget 73 | 74 | TSharedPtr MyHorizontalBox; 75 | 76 | //~ Begin UWidget interface 77 | virtual TSharedRef RebuildWidget() override; 78 | //~ End of UWidget interface 79 | 80 | public: 81 | 82 | UPROPERTY(BlueprintAssignable, Category = "MenuPadPlus | Widgets") 83 | FMenuPadPlusHorizontalBoxChangedChild OnHorizontalBoxChangedChild; 84 | 85 | }; -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Widget/Components/MenuPadPlusVerticalBox.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "UObject/ObjectMacros.h" 28 | #include "UObject/Object.h" 29 | #include "Widgets/SWidget.h" 30 | #include "Widgets/SBoxPanel.h" 31 | #include "MenuPadPlusPanelWidget.h" 32 | #include "MenuPadPlusVerticalBox.generated.h" 33 | 34 | class UVerticalBoxSlot; 35 | 36 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMenuPadPlusVerticalBoxChangedChild, int32, ChildIndex); 37 | 38 | /** 39 | * A navigable vertical box widget is a layout panel allowing child widgets to be automatically laid out 40 | * vertically and user can navigate through their navigable child widgets 41 | * 42 | * * Many Children 43 | * * Flows Vertical 44 | */ 45 | UCLASS(AutoExpandCategories = ("MenuPadPlus | Widgets"), meta = (DisplayName = "VerticalBox")) 46 | class MENUPADPLUS_API UMenuPadPlusVerticalBox : public UMenuPadPlusPanelWidget 47 | { 48 | GENERATED_BODY() 49 | 50 | public: 51 | 52 | // Constructor 53 | UMenuPadPlusVerticalBox(const FObjectInitializer& ObjectInitializer); 54 | 55 | /** */ 56 | UFUNCTION(BlueprintCallable, Category = "Panel") 57 | UVerticalBoxSlot* AddChildToVerticalBox(UWidget* Content); 58 | 59 | #if WITH_EDITOR 60 | //~ Begin UWidget Interface 61 | virtual const FText GetPaletteCategory() override; 62 | //~ End UWidget Interface 63 | #endif 64 | 65 | virtual void ReleaseSlateResources(bool bReleaseChildren) override; 66 | 67 | protected: 68 | 69 | //~ Begin UPanelWidget 70 | virtual UClass* GetSlotClass() const override; 71 | virtual void OnSlotAdded(UPanelSlot* Slot) override; 72 | virtual void OnSlotRemoved(UPanelSlot* Slot) override; 73 | //~ End UPanelWidget 74 | 75 | TSharedPtr MyVerticalBox; 76 | 77 | //~ Begin UWidget interface 78 | virtual TSharedRef RebuildWidget() override; 79 | //~ End UWidget interface 80 | 81 | public: 82 | 83 | UPROPERTY(BlueprintAssignable, Category = "MenuPadPlus | Widgets") 84 | FMenuPadPlusVerticalBoxChangedChild OnVerticalBoxChangedChild; 85 | 86 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MenuPadPlus 2 | An Unreal Engine 4 UI Plugin 3 | 4 | MenuPadPlus is an Unreal Engine 4 plugin that allows ready-to-use gamepads in UMG Blueprints. It is written in C++. 5 | It is released under the terms of the MIT License for educational, research and/or 6 | commercial purposes. 7 | 8 | ## PROJECT DETAILS 9 | 10 | MenuPadPlus is designed to allow gamepads to work within minutes for your UMG Blueprints in Unreal Engine 4. 11 | I developed it in one of my games and later adapted it as this open source plugin. It's designed for any type of navigable menu 12 | and allows for changes in the UMG Blueprints graph. 13 | 14 | **Features** 15 | 16 | - Ready-to-use out of the box 17 | - Supports up to 12 Navigable Menus 18 | - Supports Alternate Button Images 19 | - Custom UserWidget that you re-parent in your own Widget Blueprint which handles everything 20 | - Custom Button that has optional text, if you need it 21 | - An API that advanced C++ users can use to build upon 22 | 23 | ## GETTING STARTED 24 | 25 | Video Tutorial [here](https://youtu.be/rJ23w__VuhQ) 26 | 27 | The MenuPadPlus repository includes the UE4 project MenuPadPlusExample. If you do not wish to use this project example, 28 | move the Plugins folder of this repository to the root directory of your game and rebuild in Visual Studio. Build out your Plugins 29 | folders in Visual Studio with "Add Filter" then drag in each file. 30 | 31 | ##### **1. Create a Widget Blueprint** 32 | ![Alt text](/Screenshots/Directions1.PNG?raw=true) 33 | ##### 2. Re-parent your Widget Blueprint with UserWidget_MenuPadPlus 34 | ![Alt text](/Screenshots/Directions2.png?raw=true) 35 | ##### 3. Go to the Designer, and open the MenuPadPlus option in the Palette panel to reveal options. 36 | ![Alt text](/Screenshots/Directions3.PNG?raw=true) 37 | ##### 4. Drag in a Vertical/Horizontal Box and then add Buttons to it. 38 | ![Alt text](/Screenshots/Directions4.PNG?raw=true) 39 | ##### 5. Design your menu to your liking 40 | ![Alt text](/Screenshots/Directions5.PNG?raw=true) 41 | ##### 6. Create a HUD Blueprint and create your widget from BeginPlay. (Make sure your GameMode has your HUD Blueprint set by default) 42 | ![Alt text](/Screenshots/Directions6.PNG?raw=true) 43 | ##### 7. Press Play and Enjoy MenuPadPlus! 44 | ![Alt text](/Screenshots/Directions7.PNG?raw=true) 45 | 46 | If you are using your own Player Controller class, make changes to the source where necessary and move the 47 | class to your Plugin directory like in this example or else your project will not compile. 48 | 49 | **Include these Dependency Modules in your Project's Build.cs file:** 50 | ``` 51 | PublicDependencyModuleNames.AddRange(new string[] { 52 | "Core", 53 | "CoreUObject", 54 | "Engine", 55 | "InputCore", 56 | "UMG", 57 | "MenuPadPlus" }); 58 | 59 | PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 60 | ``` 61 | 62 | When using C++, you should follow the MyHUD class example to create a widget. If you make changes to the source code of MenuPadPlus, 63 | you must rebuild both your project and the plugin in Visual Studio outside of Unreal Engine. 64 | 65 | ## NOTES 66 | 67 | Tested to work in v4.20 and v4.21 for Windows. This software requires one gamepad/controller. MenuPadPlus is shipped as-is without warranty. 68 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/Widget/Components/MenuPadPlusPanelWidget.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "../../../Classes/Widget/Components/MenuPadPlusPanelWidget.h" 25 | #include "../../../Classes/Widget/Components/MenuPadPlusButton.h" 26 | #include "../../../Classes/Utilities/MenuPadPlusStatics.h" 27 | #include "Runtime/UMG/Public/Components/Button.h" 28 | #include "Runtime/Engine/Classes/Kismet/GameplayStatics.h" 29 | #include "Runtime/Engine/Classes/GameFramework/PlayerController.h" 30 | #include "Runtime/Engine/Classes/GameFramework/Actor.h" 31 | #include "Runtime/Engine/Classes/Engine/Texture.h" 32 | #include "Runtime/Engine/Classes/Engine/Texture2D.h" 33 | #include "Runtime/Engine/Classes/Engine/World.h" 34 | #include "../../../Classes/GameFramework/MyPlayerController.h" 35 | 36 | #define LOCTEXT_NAMESPACE "MenuPadPlus" 37 | 38 | const int32 UMenuPadPlusPanelWidget::PLAYER_CONTROLLER_INDEX = 0; 39 | 40 | void UMenuPadPlusPanelWidget::BindData() 41 | { 42 | // Set data related to this class 43 | } 44 | 45 | void UMenuPadPlusPanelWidget::UnBindData() 46 | { 47 | // Delete data related to this class 48 | } 49 | 50 | // Good for tracking status 51 | UMenuPadPlusButton* UMenuPadPlusPanelWidget::GetFocusedWidget() 52 | { 53 | for (auto& Widget : Buttons) 54 | { 55 | if (Widget->bHasForcedHover) 56 | return Widget; 57 | } 58 | 59 | return nullptr; 60 | } 61 | 62 | UMenuPadPlusButton* UMenuPadPlusPanelWidget::GetFirstWidget() const 63 | { 64 | return Buttons[0]; 65 | } 66 | 67 | AMyPlayerController* UMenuPadPlusPanelWidget::GetOwningPlayerController() const 68 | { 69 | return Cast(UGameplayStatics::GetPlayerController(GetWorld(), PLAYER_CONTROLLER_INDEX)); 70 | } 71 | 72 | bool UMenuPadPlusPanelWidget::DoesContainButtons() 73 | { 74 | return Buttons.Num() > 0; 75 | } 76 | 77 | void UMenuPadPlusPanelWidget::ResetAllWidgetFocus() 78 | { 79 | for (auto const& Widget : Buttons) 80 | Widget->ForceNormalText(); 81 | 82 | if (GetOwningPlayerController() != nullptr) UMenuPadPlusStatics::SetButtonFocus(GetFirstWidget(), GetOwningPlayerController()); 83 | } 84 | 85 | #undef LOCTEXT_NAMESPACE -------------------------------------------------------------------------------- /Source/MenuPadPlusExample/MyHUD.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "MyHUD.h" 25 | #include "Runtime/UMG/Public/UMG.h" 26 | #include "Runtime/UMG/Public/UMGStyle.h" 27 | #include "Runtime/UMG/Public/Slate/SObjectWidget.h" 28 | #include "Runtime/UMG/Public/IUMGModule.h" 29 | #include "Runtime/UMG/Public/Blueprint/UserWidget.h" 30 | #include "Runtime/Engine/Classes/Kismet/GameplayStatics.h" 31 | #include "Runtime/Engine/Classes/GameFramework/PlayerController.h" 32 | #include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h" 33 | #include "Engine/World.h" 34 | 35 | // MenuPadPlus Plugin Includes 36 | #include "../../Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Widget/UserWidget_MenuPadPlus.h" 37 | #include "../../Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Widget/Components/MenuPadPlusButton.h" 38 | #include "../../Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Utilities/MenuPadPlusStatics.h" 39 | #include "../../Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/GameFramework/MyPlayerController.h" 40 | 41 | const int32 AMyHUD::PLAYER_CONTROLLER_INDEX = 0; 42 | 43 | AMyHUD::AMyHUD() 44 | { 45 | //~ Begin MenuPadPlus 46 | PrimaryActorTick.bCanEverTick = true; 47 | static ConstructorHelpers::FClassFinder WidgetAsset(TEXT("/Game/UI/MainMenu_Mixed")); 48 | if (WidgetAsset.Succeeded()) MenuWidgetBlueprint = WidgetAsset.Class; 49 | //~ End MenuPadPlus 50 | } 51 | 52 | void AMyHUD::BeginPlay() 53 | { 54 | Super::BeginPlay(); 55 | 56 | //~ Begin MenuPadPlus 57 | InitMenuPadPlus(); 58 | //~ End MenuPadPlus 59 | } 60 | 61 | // Create widget and add to viewport 62 | void AMyHUD::InitMenuPadPlus() 63 | { 64 | class UUserWidget_MenuPadPlus* MenuPtr = nullptr; 65 | auto const WorldPtr = GetWorld(); 66 | 67 | if (ensure(WorldPtr)) 68 | { 69 | auto PC = Cast(UGameplayStatics::GetPlayerController(WorldPtr, PLAYER_CONTROLLER_INDEX)); 70 | 71 | if (PC != nullptr) 72 | { 73 | if (MenuWidgetBlueprint != NULL) 74 | { 75 | MenuPtr = CreateWidget(WorldPtr, MenuWidgetBlueprint); 76 | 77 | if (MenuPtr != nullptr) 78 | { 79 | MenuPtr->AddToViewport(); 80 | 81 | // Sets Focus on a Button in Menu, using a Player Controller 82 | UMenuPadPlusStatics::SetButtonFocus(MenuPtr->GetFirstWidget(), PC); 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/Utilities/MenuPadPlusStatics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "../../Classes/Utilities/MenuPadPlusStatics.h" 25 | #include "Runtime/Engine/Classes/GameFramework/PlayerController.h" 26 | #include "../../Classes/Widget/UserWidget_MenuPadPlus.h" 27 | #include "../../Classes/Widget/Components/MenuPadPlusButton.h" 28 | #include "../../Classes/Widget/Components/MenuPadPlusVerticalBox.h" 29 | #include "../../Classes/Widget/Components/MenuPadPlusPanelWidget.h" 30 | #include "../../Classes/Widget/MenuPadPlusInterface.h" 31 | #include "Runtime/Engine/Classes/Kismet/GameplayStatics.h" 32 | #include "../../Classes/GameFramework/MyPlayerController.h" 33 | #include "Runtime/Engine/Classes/GameFramework/Actor.h" 34 | #include "Runtime/CoreUObject/Public/UObject/UObjectIterator.h" 35 | #include "Runtime/Engine/Classes/Engine/World.h" 36 | 37 | TScriptInterface UMenuPadPlusStatics::GetActiveContainer() 38 | { 39 | TScriptInterface retVal = NULL; 40 | 41 | for (TObjectIterator Itr; Itr; ++Itr) 42 | { 43 | UObject* Object = *Itr; 44 | 45 | if (IMenuPadPlusInterface* Interface = Cast(Object)) 46 | { 47 | if (Interface->bIsActive) 48 | { 49 | retVal.SetInterface(Interface); 50 | retVal.SetObject(Object); 51 | return retVal; 52 | } 53 | } 54 | } 55 | 56 | return retVal; 57 | } 58 | 59 | void UMenuPadPlusStatics::SetWidgetFocus(TScriptInterface Container, UMenuPadPlusButton* Widget) 60 | { 61 | if (!Container) 62 | return; 63 | 64 | // UnFocus 65 | if (Container->GetFocusedWidget()) 66 | Container->GetFocusedWidget()->ForceNormalText(); 67 | 68 | // Then Focus 69 | if (Widget) 70 | Widget->ForceHoveredText(); 71 | } 72 | 73 | void UMenuPadPlusStatics::ResetAllWidgetFocus() 74 | { 75 | for (TObjectIterator Itr; Itr; ++Itr) 76 | { 77 | UObject* Object = *Itr; 78 | 79 | if (IMenuPadPlusInterface* Interface = Cast(Object)) 80 | Interface->ResetAllWidgetFocus(); 81 | } 82 | } 83 | 84 | UMenuPadPlusButton* UMenuPadPlusStatics::GetFocusedWidget(TScriptInterface Container) 85 | { 86 | if (Container) 87 | return Container->GetFocusedWidget(); 88 | 89 | return nullptr; 90 | } 91 | 92 | void UMenuPadPlusStatics::SetButtonFocus(class UMenuPadPlusButton* NavigableWidget, class AMyPlayerController* PlayerController) 93 | { 94 | if (NavigableWidget != nullptr) 95 | { 96 | FInputModeUIOnly uiMode; 97 | uiMode.SetWidgetToFocus(NavigableWidget->GetCachedWidget()); 98 | uiMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock); 99 | if (PlayerController != nullptr) PlayerController->SetInputMode(uiMode); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/Widget/Components/MenuPadPlusVerticalBox.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "../../../Classes/Widget/Components/MenuPadPlusVerticalBox.h" 25 | #include "../../../Classes/Widget/UserWidget_MenuPadPlus.h" 26 | #include "../../../Classes/Widget/Components/MenuPadPlusButton.h" 27 | #include "../../../Classes/Utilities/MenuPadPlusStatics.h" 28 | #include "Runtime/UMG/Public/Components/VerticalBox.h" 29 | #include "Runtime/UMG/Public/Components/VerticalBoxSlot.h" 30 | #include "Runtime/Engine/Classes/Engine/Texture.h" 31 | #include "Runtime/Engine/Classes/Engine/Texture2D.h" 32 | #include "Runtime/Engine/Classes/Kismet/GameplayStatics.h" 33 | 34 | #define LOCTEXT_NAMESPACE "MenuPadPlus" 35 | 36 | UMenuPadPlusVerticalBox::UMenuPadPlusVerticalBox(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) 37 | { 38 | bIsVariable = false; 39 | 40 | SVerticalBox::FArguments Defaults; 41 | Visibility = UWidget::ConvertRuntimeToSerializedVisibility(Defaults._Visibility.Get()); 42 | } 43 | 44 | void UMenuPadPlusVerticalBox::ReleaseSlateResources(bool bReleaseChildren) 45 | { 46 | Super::ReleaseSlateResources(bReleaseChildren); 47 | 48 | Buttons.Empty(); 49 | AlternateImages.Empty(); 50 | AlternateHoveredSound = nullptr; 51 | AlternatePressedSound = nullptr; 52 | MyVerticalBox.Reset(); 53 | } 54 | 55 | UClass* UMenuPadPlusVerticalBox::GetSlotClass() const 56 | { 57 | return UVerticalBoxSlot::StaticClass(); 58 | } 59 | 60 | #pragma region UPanelWidget Interface 61 | // Add Child 62 | void UMenuPadPlusVerticalBox::OnSlotAdded(UPanelSlot* InSlot) 63 | { 64 | Super::OnSlotAdded(InSlot); 65 | 66 | // Add the child to the live canvas if it already exists 67 | if (MyVerticalBox.IsValid()) 68 | { 69 | CastChecked(InSlot)->BuildSlot(MyVerticalBox.ToSharedRef()); 70 | } 71 | } 72 | 73 | // Remove Child 74 | void UMenuPadPlusVerticalBox::OnSlotRemoved(UPanelSlot* InSlot) 75 | { 76 | Super::OnSlotRemoved(InSlot); 77 | 78 | // Remove the widget from the live slot if it exists. 79 | if (MyVerticalBox.IsValid()) 80 | { 81 | TSharedPtr Widget = InSlot->Content->GetCachedWidget(); 82 | if (Widget.IsValid()) 83 | { 84 | MyVerticalBox->RemoveSlot(Widget.ToSharedRef()); 85 | } 86 | } 87 | } 88 | #pragma endregion 89 | 90 | UVerticalBoxSlot* UMenuPadPlusVerticalBox::AddChildToVerticalBox(UWidget* Content) 91 | { 92 | return Cast(Super::AddChild(Content)); 93 | } 94 | 95 | TSharedRef UMenuPadPlusVerticalBox::RebuildWidget() 96 | { 97 | MyVerticalBox = SNew(SVerticalBox); 98 | 99 | for (UPanelSlot* PanelSlot : Slots) 100 | { 101 | if (UVerticalBoxSlot* TypedSlot = Cast(PanelSlot)) 102 | { 103 | TypedSlot->Parent = this; 104 | TypedSlot->BuildSlot(MyVerticalBox.ToSharedRef()); 105 | } 106 | } 107 | 108 | return MyVerticalBox.ToSharedRef(); 109 | } 110 | 111 | #if WITH_EDITOR 112 | const FText UMenuPadPlusVerticalBox::GetPaletteCategory() 113 | { 114 | return LOCTEXT("MenuPadPlus", "Menu Pad Plus"); 115 | } 116 | #endif 117 | 118 | #undef LOCTECT_NAMESPACE 119 | 120 | 121 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/Widget/Components/MenuPadPlusHorizontalBox.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "../../../Classes/Widget/Components/MenuPadPlusHorizontalBox.h" 25 | #include "../../../Classes/Widget/UserWidget_MenuPadPlus.h" 26 | #include "../../../Classes/Widget/Components/MenuPadPlusButton.h" 27 | #include "../../../Classes/Utilities/MenuPadPlusStatics.h" 28 | #include "Runtime/UMG/Public/Components/HorizontalBox.h" 29 | #include "Runtime/UMG/Public/Components/HorizontalBoxSlot.h" 30 | #include "Runtime/Engine/Classes/Engine/Texture.h" 31 | #include "Runtime/Engine/Classes/Engine/Texture2D.h" 32 | #include "Runtime/Engine/Classes/Kismet/GameplayStatics.h" 33 | 34 | #define LOCTEXT_NAMESPACE "MenuPadPlus" 35 | 36 | UMenuPadPlusHorizontalBox::UMenuPadPlusHorizontalBox(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) 37 | { 38 | bIsVariable = false; 39 | 40 | SHorizontalBox::FArguments Defaults; 41 | Visibility = UWidget::ConvertRuntimeToSerializedVisibility(Defaults._Visibility.Get()); 42 | } 43 | 44 | void UMenuPadPlusHorizontalBox::ReleaseSlateResources(bool bReleaseChildren) 45 | { 46 | Super::ReleaseSlateResources(bReleaseChildren); 47 | 48 | Buttons.Empty(); 49 | AlternateImages.Empty(); 50 | AlternateHoveredSound = nullptr; 51 | AlternatePressedSound = nullptr; 52 | MyHorizontalBox.Reset(); 53 | } 54 | 55 | UClass* UMenuPadPlusHorizontalBox::GetSlotClass() const 56 | { 57 | return UHorizontalBoxSlot::StaticClass(); 58 | } 59 | 60 | #pragma region UPanelWidget Interface 61 | // Add Child 62 | void UMenuPadPlusHorizontalBox::OnSlotAdded(UPanelSlot* InSlot) 63 | { 64 | Super::OnSlotAdded(InSlot); 65 | 66 | // Add the child to the live canvas if it already exists 67 | if (MyHorizontalBox.IsValid()) 68 | { 69 | CastChecked(InSlot)->BuildSlot(MyHorizontalBox.ToSharedRef()); 70 | } 71 | } 72 | 73 | // Remove Child 74 | void UMenuPadPlusHorizontalBox::OnSlotRemoved(UPanelSlot* InSlot) 75 | { 76 | Super::OnSlotRemoved(InSlot); 77 | 78 | // Remove the widget from the live slot if it exists. 79 | if (MyHorizontalBox.IsValid()) 80 | { 81 | TSharedPtr Widget = InSlot->Content->GetCachedWidget(); 82 | if (Widget.IsValid()) 83 | { 84 | MyHorizontalBox->RemoveSlot(Widget.ToSharedRef()); 85 | } 86 | } 87 | } 88 | #pragma endregion 89 | 90 | UHorizontalBoxSlot* UMenuPadPlusHorizontalBox::AddChildToHorizontalBox(UWidget* Content) 91 | { 92 | return Cast(Super::AddChild(Content)); 93 | } 94 | 95 | TSharedRef UMenuPadPlusHorizontalBox::RebuildWidget() 96 | { 97 | MyHorizontalBox = SNew(SHorizontalBox); 98 | 99 | for (UPanelSlot* PanelSlot : Slots) 100 | { 101 | if (UHorizontalBoxSlot* TypedSlot = Cast(PanelSlot)) 102 | { 103 | TypedSlot->Parent = this; 104 | TypedSlot->BuildSlot(MyHorizontalBox.ToSharedRef()); 105 | } 106 | } 107 | 108 | return MyHorizontalBox.ToSharedRef(); 109 | } 110 | 111 | #if WITH_EDITOR 112 | const FText UMenuPadPlusHorizontalBox::GetPaletteCategory() 113 | { 114 | return LOCTEXT("MenuPadPlus", "Menu Pad Plus"); 115 | } 116 | #endif 117 | 118 | #undef LOCTECT_NAMESPACE -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Widget/Components/MenuPadPlusPanelWidget.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "UObject/ObjectMacros.h" 28 | #include "UObject/Object.h" 29 | #include "UObjectGlobals.h" 30 | #include "Components/PanelSlot.h" 31 | #include "Components/Widget.h" 32 | #include "Blueprint/UserWidget.h" 33 | #include "Runtime/UMG/Public/Components/PanelWidget.h" 34 | #include "../MenuPadPlusInterface.h" 35 | #include "MenuPadPlusPanelWidget.generated.h" 36 | 37 | class UMenuPadPlusButton; 38 | 39 | UCLASS(AutoExpandCategories = ("MenuPadPlus | Widgets")) 40 | class MENUPADPLUS_API UMenuPadPlusPanelWidget : public UPanelWidget, public IMenuPadPlusInterface 41 | { 42 | GENERATED_BODY() 43 | 44 | public: 45 | 46 | // All Button Children 47 | UPROPERTY(BlueprintReadOnly, Category = "MenuPadPlus | Widgets") 48 | TArray Buttons; 49 | 50 | // Do we want to replace our Normal/Hovered/Pressed button images with different ones? 51 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MenuPadPlus | Images", meta = (DisplayName = "Use Alternate Images")) 52 | bool bUseAlternateImages; 53 | 54 | // All Alternate Normal/Hovered/Pressed Images 55 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MenuPadPlus | Images") 56 | TArray AlternateImages; 57 | 58 | // Alternate Button Size X 59 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MenuPadPlus | Images") 60 | float AlternateSizeX; 61 | 62 | // Alternate Button Size Y 63 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MenuPadPlus | Images") 64 | float AlternateSizeY; 65 | 66 | // Alternate Hovered Sound Cue 67 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MenuPadPlus | Sounds") 68 | class USoundCue* AlternateHoveredSound; 69 | 70 | // Alternate Pressed Sound Cue 71 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MenuPadPlus | Sounds") 72 | class USoundCue* AlternatePressedSound; 73 | 74 | FORCEINLINE TArray GetButtons() const { return Buttons; } 75 | FORCEINLINE int32 GetAlternateImagesSize() const { return AlternateImages.Num(); } 76 | FORCEINLINE class UTexture2D* GetAlternateImages_Normal() const { return AlternateImages[0]; } 77 | FORCEINLINE class UTexture2D* GetAlternateImages_Hovered() const { return AlternateImages[1]; } 78 | FORCEINLINE class UTexture2D* GetAlternateImages_Pressed() const { return AlternateImages[2]; } 79 | FORCEINLINE constexpr float GetAlternateSizeX() const { return AlternateSizeX; } 80 | FORCEINLINE constexpr float GetAlternateSizeY() const { return AlternateSizeY; } 81 | FORCEINLINE class USoundCue* GetAlternateHoveredSound() const { return AlternateHoveredSound; } 82 | FORCEINLINE class USoundCue* GetAlternatePressedSound() const { return AlternatePressedSound; } 83 | 84 | //~ Begin IMenuPadPlusInterface 85 | virtual void BindData() override; 86 | virtual void UnBindData() override; 87 | virtual UMenuPadPlusButton* GetFocusedWidget() override; 88 | virtual UMenuPadPlusButton* GetFirstWidget() const override; 89 | virtual AMyPlayerController* GetOwningPlayerController() const override; 90 | virtual bool DoesContainButtons() override; 91 | virtual void ResetAllWidgetFocus() override; 92 | //~ End IMenuPadPlusInterface 93 | 94 | private: 95 | 96 | const static int32 PLAYER_CONTROLLER_INDEX; 97 | 98 | }; -------------------------------------------------------------------------------- /Config/DefaultInput.ini: -------------------------------------------------------------------------------- 1 | 2 | [/Script/Engine.InputSettings] 3 | -AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) 4 | -AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) 5 | -AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) 6 | -AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) 7 | -AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) 8 | -AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) 9 | +AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 10 | +AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 11 | +AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 12 | +AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 13 | +AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) 14 | +AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) 15 | +AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_Z",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 16 | +AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_Z",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 17 | +AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 18 | +AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 19 | +AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 20 | +AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 21 | +AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 22 | +AxisConfig=(AxisKeyName="MotionController_Left_TriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 23 | +AxisConfig=(AxisKeyName="MotionController_Left_Grip1Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 24 | +AxisConfig=(AxisKeyName="MotionController_Left_Grip2Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 25 | +AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 26 | +AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 27 | +AxisConfig=(AxisKeyName="MotionController_Right_TriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 28 | +AxisConfig=(AxisKeyName="MotionController_Right_Grip1Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 29 | +AxisConfig=(AxisKeyName="MotionController_Right_Grip2Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 30 | +AxisConfig=(AxisKeyName="Gamepad_Special_Left_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 31 | +AxisConfig=(AxisKeyName="Gamepad_Special_Left_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 32 | bAltEnterTogglesFullscreen=True 33 | bF11TogglesFullscreen=True 34 | bUseMouseForTouch=False 35 | bEnableMouseSmoothing=True 36 | bEnableFOVScaling=True 37 | bCaptureMouseOnLaunch=True 38 | bDefaultViewportMouseLock=False 39 | bAlwaysShowTouchInterface=False 40 | bShowConsoleOnFourFingerTap=True 41 | bEnableGestureRecognizer=False 42 | bUseAutocorrect=False 43 | DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown 44 | DefaultViewportMouseLockMode=LockOnCapture 45 | FOVScale=0.011110 46 | DoubleClickTime=0.200000 47 | +ActionMappings=(ActionName="Confirm",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_FaceButton_Bottom) 48 | +ActionMappings=(ActionName="Cancel",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_FaceButton_Right) 49 | DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks 50 | ConsoleKey=None 51 | -ConsoleKeys=Tilde 52 | +ConsoleKeys=Tilde 53 | 54 | 55 | -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Widget/Components/MenuPadPlusButton.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "Runtime/UMG/Public/Components/Button.h" 28 | #include "Misc/Attribute.h" 29 | #include "Layout/Margin.h" 30 | #include "Components/Widget.h" 31 | #include "Framework/Text/TextLayout.h" 32 | #include "MenuPadPlusButton.generated.h" 33 | 34 | class STextBlock; 35 | class IMenuPadPlusInterface; 36 | 37 | /** 38 | * The button is a click-able primitive widget to enable basic interaction, you 39 | * can place any other widget inside a button to make a more complex and 40 | * interesting click-able element in your UI. 41 | * 42 | * * Single Child 43 | * * Clickable 44 | * * Text (Optional) 45 | */ 46 | UCLASS(Blueprintable, BlueprintType, meta=(DisplayName="Button")) 47 | class MENUPADPLUS_API UMenuPadPlusButton : public UButton 48 | { 49 | GENERATED_BODY() 50 | 51 | public: 52 | 53 | UMenuPadPlusButton(const FObjectInitializer& ObjectInitializer); 54 | 55 | // Bindings for Text Color 56 | PROPERTY_BINDING_IMPLEMENTATION(FText, Text); 57 | PROPERTY_BINDING_IMPLEMENTATION(FSlateColor, TextColorAndOpacity); 58 | PROPERTY_BINDING_IMPLEMENTATION(FSlateColor, TextColorAndOpacityHover); 59 | PROPERTY_BINDING_IMPLEMENTATION(FSlateColor, TextColorAndOpacityPressed); 60 | PROPERTY_BINDING_IMPLEMENTATION(FLinearColor, TextShadowColorAndOpacity); 61 | 62 | // The Text 63 | UPROPERTY(Category = "Text", EditAnywhere, meta = (MultiLine = "true")) 64 | FText Text; 65 | 66 | // A delegate to allow logic to drive the text of the widget 67 | UPROPERTY() 68 | FGetText TextDelegate; 69 | 70 | // Text justification 71 | UPROPERTY(Category = "Text", EditAnywhere, BlueprintReadOnly) 72 | TEnumAsByte TextJustification; 73 | 74 | // Margin 75 | UPROPERTY(Category = "Text", EditAnywhere, BlueprintReadOnly) 76 | FMargin TextMargin; 77 | 78 | // Normal Color and Opacity 79 | UPROPERTY(Category = "Text", EditAnywhere, BlueprintReadOnly) 80 | FSlateColor TextColorAndOpacity; 81 | 82 | // A delegate for Normal Color and Opacity 83 | UPROPERTY() 84 | FGetSlateColor TextColorAndOpacityDelegate; 85 | 86 | // Hover Color and Opacity 87 | UPROPERTY(Category = "Text", EditAnywhere, BlueprintReadOnly) 88 | FSlateColor TextColorAndOpacityHover; 89 | 90 | // A delegate for Hover Color and Opacity 91 | UPROPERTY() 92 | FGetSlateColor TextColorAndOpacityHoverDelegate; 93 | 94 | // Pressed Color and Opacity 95 | UPROPERTY(Category = "Text", EditAnywhere, BlueprintReadOnly) 96 | FSlateColor TextColorAndOpacityPressed; 97 | 98 | // A delegate for Pressed Color and Opacity 99 | UPROPERTY() 100 | FGetSlateColor TextColorAndOpacityPressedDelegate; 101 | 102 | // The Font 103 | UPROPERTY(Category = "Text", EditAnywhere, BlueprintReadOnly) 104 | FSlateFontInfo TextFont; 105 | 106 | // The direction the shadow is cast 107 | UPROPERTY(Category = "Text", EditAnywhere, BlueprintReadOnly) 108 | FVector2D TextShadowOffset; 109 | 110 | // Shadow Color 111 | UPROPERTY(Category = "Text", EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "Shadow Color")) 112 | FLinearColor TextShadowColorAndOpacity; 113 | 114 | // A delegate for the Shadow Color and Opacity 115 | UPROPERTY() 116 | FGetLinearColor TextShadowColorAndOpacityDelegate; 117 | 118 | UPROPERTY(Category = "MenuPadPlus | Widgets | Navigation", BlueprintReadOnly) 119 | TScriptInterface OwnerContainer; 120 | 121 | UFUNCTION(BlueprintCallable, Category = "Button") 122 | virtual void ForceNormalText(); 123 | 124 | UFUNCTION(BlueprintCallable, Category = "Button") 125 | virtual void ForceHoveredText(); 126 | 127 | UFUNCTION(BlueprintCallable, Category = "Button") 128 | virtual void ForcePressedText(); 129 | 130 | bool bHasForcedNormal; 131 | bool bHasForcedHover; 132 | bool bHasForcedPressed; 133 | bool bCanPlayHoveredSound; 134 | 135 | // Customize OnHovered Delegate 136 | UFUNCTION(Category=Default) 137 | virtual void OnHoveredLogic(); 138 | 139 | // Customize OnPressed Delegate 140 | UFUNCTION(Category = Default) 141 | virtual void OnPressedLogic(); 142 | 143 | // Customize OnReleased Delegate 144 | UFUNCTION(Category = Default) 145 | virtual void OnReleasedLogic(); 146 | 147 | // Pointer to the underlying slate button owned by this UWidget 148 | TSharedPtr OptionalTextBlock; 149 | 150 | const static int32 PLAYER_CONTROLLER_INDEX; 151 | 152 | #if WITH_EDITOR 153 | virtual const FText GetPaletteCategory() override; 154 | #endif 155 | 156 | protected: 157 | 158 | //~ Begin UWidget Interface 159 | virtual TSharedRef RebuildWidget() override; 160 | virtual void SynchronizeProperties() override; 161 | //~ End UWidget Interface 162 | 163 | //~ Begin UVisual Interface 164 | virtual void ReleaseSlateResources(bool bReleaseChildren) override; 165 | //~ End UVisual Interface 166 | 167 | }; -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/Widget/Components/MenuPadPlusButton.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 Robert Slattery 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 | */ 23 | 24 | #include "../../../Classes/Widget/Components/MenuPadPlusButton.h" 25 | #include "Runtime/SlateCore/Public/Widgets/SNullWidget.h" 26 | #include "Runtime/SlateCore/Public/Widgets/DeclarativeSyntaxSupport.h" 27 | #include "Runtime/Slate/Public/Widgets/Input/SButton.h" 28 | #include "Runtime/Slate/Public/Widgets/Text/STextBlock.h" 29 | #include "Runtime/UMG/Public/Components/ButtonSlot.h" 30 | #include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h" 31 | #include "Runtime/Engine/Classes/Kismet/GameplayStatics.h" 32 | #include "Runtime/Engine/Classes/Engine/Texture.h" 33 | #include "Runtime/Engine/Classes/Engine/Texture2D.h" 34 | #include "Engine/Font.h" 35 | #include "Runtime/Engine/Classes/GameFramework/PlayerController.h" 36 | #include "../../../Classes/GameFramework/MyPlayerController.h" 37 | 38 | #define LOCTEXT_NAMESPACE "MenuPadPlus" 39 | 40 | const int32 UMenuPadPlusButton::PLAYER_CONTROLLER_INDEX = 0; 41 | 42 | UMenuPadPlusButton::UMenuPadPlusButton(const FObjectInitializer& ObjectInitializer) : UButton(ObjectInitializer) 43 | { 44 | bIsVariable = true; 45 | TextShadowOffset = FVector2D(1.0f, 1.0f); 46 | TextColorAndOpacity = FLinearColor::White; 47 | TextShadowColorAndOpacity = FLinearColor::Transparent; 48 | 49 | if (!IsRunningDedicatedServer()) 50 | { 51 | static ConstructorHelpers::FObjectFinder RobotoFontObj(TEXT("/Engine/EngineFonts/Roboto")); 52 | TextFont = FSlateFontInfo(RobotoFontObj.Object, 24, FName("Bold")); 53 | } 54 | 55 | OnHovered.AddDynamic(this, &UMenuPadPlusButton::OnHoveredLogic); 56 | OnPressed.AddDynamic(this, &UMenuPadPlusButton::OnPressedLogic); 57 | OnReleased.AddDynamic(this, &UMenuPadPlusButton::OnReleasedLogic); 58 | 59 | bHasForcedNormal = false; 60 | bHasForcedHover = false; 61 | bHasForcedPressed = false; 62 | bCanPlayHoveredSound = false; 63 | } 64 | 65 | TSharedRef UMenuPadPlusButton::RebuildWidget() 66 | { 67 | OptionalTextBlock = SNew(STextBlock); 68 | OptionalTextBlock->SetText(Text); 69 | OptionalTextBlock->SetColorAndOpacity(TextColorAndOpacity); 70 | OptionalTextBlock->SetFont(TextFont); 71 | OptionalTextBlock->SetJustification(TextJustification); 72 | OptionalTextBlock->SetMargin(TextMargin); 73 | 74 | MyButton = SNew(SButton) 75 | .OnClicked(BIND_UOBJECT_DELEGATE(FOnClicked, SlateHandleClicked)) 76 | .OnPressed(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandlePressed)) 77 | .OnReleased(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandleReleased)) 78 | .OnHovered_UObject(this, &ThisClass::SlateHandleHovered) 79 | .OnUnhovered_UObject(this, &ThisClass::SlateHandleUnhovered) 80 | .ButtonStyle(&WidgetStyle) 81 | .ClickMethod(ClickMethod) 82 | .TouchMethod(TouchMethod) 83 | .IsFocusable(IsFocusable) 84 | .Content() 85 | [ 86 | OptionalTextBlock.ToSharedRef() 87 | ] 88 | ; 89 | 90 | if (GetChildrenCount() > 0) 91 | Cast(GetContentSlot())->BuildSlot(MyButton.ToSharedRef()); 92 | 93 | return MyButton.ToSharedRef(); 94 | } 95 | 96 | void UMenuPadPlusButton::SynchronizeProperties() 97 | { 98 | Super::SynchronizeProperties(); 99 | 100 | TAttribute RenderText = (TextDelegate.IsBound()) ? PROPERTY_BINDING(FText, Text) : Text; 101 | 102 | OptionalTextBlock->SetText(RenderText); 103 | OptionalTextBlock->SetColorAndOpacity(TextColorAndOpacity); 104 | OptionalTextBlock->SetFont(TextFont); 105 | OptionalTextBlock->SetJustification(TextJustification); 106 | OptionalTextBlock->SetMargin(TextMargin); 107 | } 108 | 109 | void UMenuPadPlusButton::ReleaseSlateResources(bool bReleaseChildren) 110 | { 111 | Super::ReleaseSlateResources(bReleaseChildren); 112 | OptionalTextBlock.Reset(); 113 | } 114 | 115 | void UMenuPadPlusButton::ForceNormalText() 116 | { 117 | OptionalTextBlock->SetColorAndOpacity(TextColorAndOpacity); 118 | if (!bHasForcedNormal) bHasForcedNormal = true; 119 | if (bHasForcedHover) bHasForcedHover = false; 120 | if (bHasForcedPressed) bHasForcedPressed = false; 121 | } 122 | 123 | void UMenuPadPlusButton::ForceHoveredText() 124 | { 125 | OptionalTextBlock->SetColorAndOpacity(TextColorAndOpacityHover); 126 | if(!bHasForcedHover) bHasForcedHover = true; 127 | if (bHasForcedNormal) bHasForcedNormal = false; 128 | if (bHasForcedPressed) bHasForcedPressed = false; 129 | } 130 | 131 | void UMenuPadPlusButton::ForcePressedText() 132 | { 133 | OptionalTextBlock->SetColorAndOpacity(TextColorAndOpacityPressed); 134 | if (!bHasForcedPressed) bHasForcedPressed = true; 135 | } 136 | 137 | void UMenuPadPlusButton::OnHoveredLogic() 138 | { 139 | auto const World = GetWorld(); 140 | 141 | if (ensure(World)) 142 | { 143 | auto PC = Cast(UGameplayStatics::GetPlayerController(World, PLAYER_CONTROLLER_INDEX)); 144 | if (PC != nullptr) SetUserFocus(PC); 145 | } 146 | } 147 | 148 | void UMenuPadPlusButton::OnPressedLogic() 149 | { 150 | ForcePressedText(); 151 | } 152 | 153 | void UMenuPadPlusButton::OnReleasedLogic() 154 | { 155 | if (bHasForcedPressed) bHasForcedPressed = false; 156 | if (!bHasForcedHover) bHasForcedHover = true; 157 | } 158 | 159 | #if WITH_EDITOR 160 | const FText UMenuPadPlusButton::GetPaletteCategory() 161 | { 162 | return LOCTEXT("MenuPadPlus", "Menu Pad Plus"); 163 | } 164 | #endif 165 | 166 | #undef LOCTEXT_NAMESPACE -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Classes/Widget/UserWidget_MenuPadPlus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018-2019 Robert Slattery 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 | */ 23 | 24 | #pragma once 25 | 26 | #include "CoreMinimal.h" 27 | #include "Runtime/UMG/Public/Blueprint/UserWidget.h" 28 | #include "Runtime/UMG/Public/UMG.h" 29 | #include "Runtime/UMG/Public/Blueprint/WidgetTree.h" 30 | #include "Runtime/UMG/Public/Components/TextWidgetTypes.h" 31 | #include "Runtime/UMG/Public/Components/TextBlock.h" 32 | #include "UserWidget_MenuPadPlus.generated.h" 33 | 34 | #define SUCCESS 0 35 | #define FAILURE -1 36 | 37 | class IMenuPadPlusInterface; 38 | 39 | USTRUCT(BlueprintType) 40 | struct FMenuPadPlusButtonProperties 41 | { 42 | GENERATED_USTRUCT_BODY() 43 | 44 | // Which key should we use to handle going back in menus? 45 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MenuPadPlus") 46 | FKey GoBackButton; 47 | 48 | // All Box Children 49 | TArray> BoxArray; 50 | 51 | // All Normal Texture Children 52 | TArray> NormalTextureArray; 53 | 54 | // All Hovered Texture Children 55 | TArray> HoveredTextureArray; 56 | 57 | // All Pressed Texture Children 58 | TArray> PressedTextureArray; 59 | 60 | FORCEINLINE void ClearAll() 61 | { 62 | BoxArray.Empty(); 63 | NormalTextureArray.Empty(); 64 | HoveredTextureArray.Empty(); 65 | PressedTextureArray.Empty(); 66 | } 67 | 68 | explicit FMenuPadPlusButtonProperties() {} 69 | 70 | FMenuPadPlusButtonProperties( 71 | const FKey& _GoBackButton 72 | , TArray> _BoxArray 73 | , TArray> _NormalTextureArray 74 | , TArray> _HoveredTextureArray 75 | , TArray> _PressedTextureArray) : 76 | GoBackButton(_GoBackButton) 77 | , BoxArray(_BoxArray) 78 | , NormalTextureArray(_NormalTextureArray) 79 | , HoveredTextureArray(_HoveredTextureArray) 80 | , PressedTextureArray(_PressedTextureArray) 81 | {} 82 | 83 | friend bool operator==(const FMenuPadPlusButtonProperties& A, const FMenuPadPlusButtonProperties& B) 84 | { 85 | return (A.GoBackButton == B.GoBackButton 86 | && A.BoxArray == B.BoxArray 87 | && A.NormalTextureArray == B.NormalTextureArray 88 | && A.HoveredTextureArray == B.HoveredTextureArray 89 | && A.PressedTextureArray == B.PressedTextureArray); 90 | } 91 | }; 92 | 93 | USTRUCT(BlueprintType) 94 | struct FMenuPadPlusBoxData 95 | { 96 | GENERATED_USTRUCT_BODY() 97 | 98 | UPROPERTY() 99 | TArray RootMenuArray; 100 | 101 | FMenuPadPlusBoxData() { RootMenuArray.Empty(); } 102 | 103 | friend bool operator==(const FMenuPadPlusBoxData& A, const FMenuPadPlusBoxData& B) 104 | { 105 | return (A.RootMenuArray == B.RootMenuArray); 106 | } 107 | }; 108 | 109 | UCLASS(Abstract, BlueprintType, Blueprintable, Category = "MenuPadPlus") 110 | class MENUPADPLUS_API UUserWidget_MenuPadPlus : public UUserWidget 111 | { 112 | GENERATED_BODY() 113 | 114 | public: 115 | 116 | //~ Begin UUserWidget Interface 117 | virtual void NativeConstruct() override; 118 | virtual void NativeDestruct() override; 119 | virtual void NativeTick(const FGeometry& MyGeometry, float DeltaTime) override; 120 | virtual FReply NativeOnKeyUp(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override; 121 | //~ End UUserWidget Interface 122 | 123 | public: 124 | 125 | //~ Begin MenuPadPlus 126 | 127 | // Find all possible Vertical/Horizontal Boxes (Supports up to 12) 128 | int32 InitMenus(); 129 | 130 | // Adds Menus to array and sets their Button children 131 | template 132 | Idx SetMenuChildren(Type* RootMenu, const Idx& Index); 133 | 134 | template 135 | Type* FillArrayWith(Type* RootMenu); 136 | 137 | // Method to run the system 138 | void RunMenuPadPlus(float DeltaSeconds); 139 | 140 | // The actual handling of Normal/Hover/Pressed States 141 | void OnJoystickAxisChanged( 142 | TArray ButtonsArray 143 | , class AMyPlayerController* InPC); 144 | 145 | void OnJoystickAxisChangedAlternate( 146 | TArray ButtonsArray 147 | , class UObject* NormalTexture 148 | , class UObject* HoveredTexture 149 | , class UObject* PressedTexture 150 | , float ImageSizeX 151 | , float ImageSizeY 152 | , class USoundCue* HoveredSound 153 | , class USoundCue* PressedSound 154 | , class AMyPlayerController* InPC); 155 | 156 | // Which menus will allow joystick changes? 157 | void RunMenuAt(const int32 Index); 158 | 159 | UMenuPadPlusButton* GetFocusedWidget(TArray Buttons); 160 | UMenuPadPlusButton* GetFirstWidget(); 161 | UMenuPadPlusButton* GetPreviousWidget(); 162 | void ResetAllWidgetFocus(TArray CurrentButton); 163 | 164 | // Interface Owner 165 | UPROPERTY(Category = "MenuPadPlus", BlueprintReadOnly) 166 | TScriptInterface OwnerContainer; 167 | 168 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MenuPadPlus") 169 | FMenuPadPlusButtonProperties ButtonProperties; 170 | 171 | UPROPERTY(BlueprintReadOnly, Category = "MenuPadPlus") 172 | FMenuPadPlusBoxData BoxData; 173 | 174 | template 175 | FORCEINLINE constexpr int32 GetNumMenus(const TArray& RootMenus) const { return RootMenus.Num(); } 176 | 177 | // TODO: Timers for different platforms 178 | FORCEINLINE float GetTimer() const noexcept { return Timer; } 179 | FORCEINLINE float GetTimeNeededToLoad() const noexcept { return TimeNeededToLoad; } 180 | FORCEINLINE float RunTimer(float DeltaSeconds) { return Timer += (1 * DeltaSeconds); } 181 | 182 | private: 183 | 184 | float Timer; 185 | float TimeNeededToLoad; 186 | bool bHasFinishedSetup; 187 | 188 | // Numericals for Menus 189 | const static int32 ROOT_MENU_ONE; 190 | const static int32 ROOT_MENU_TWO; 191 | const static int32 ROOT_MENU_THREE; 192 | const static int32 ROOT_MENU_FOUR; 193 | const static int32 ROOT_MENU_FIVE; 194 | const static int32 ROOT_MENU_SIX; 195 | const static int32 ROOT_MENU_SEVEN; 196 | const static int32 ROOT_MENU_EIGHT; 197 | const static int32 ROOT_MENU_NINE; 198 | const static int32 ROOT_MENU_TEN; 199 | const static int32 ROOT_MENU_ELEVEN; 200 | const static int32 ROOT_MENU_TWELVE; 201 | 202 | const static int32 PLAYER_CONTROLLER_INDEX; 203 | //~ End MenuPadPlus 204 | }; -------------------------------------------------------------------------------- /Plugins/MenuPadPlus/Source/MenuPadPlus/Private/Widget/UserWidget_MenuPadPlus.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018-2019 Robert Slattery 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 | */ 23 | 24 | #include "../../Classes/Widget/UserWidget_MenuPadPlus.h" 25 | #include "../../Classes/Widget/Components/MenuPadPlusButton.h" 26 | #include "../../Classes/Widget/Components/MenuPadPlusVerticalBox.h" 27 | #include "../../Classes/Widget/Components/MenuPadPlusHorizontalBox.h" 28 | #include "../../Classes/Widget/Components/MenuPadPlusPanelWidget.h" 29 | #include "../../Classes/Utilities/MenuPadPlusStatics.h" 30 | #include "Runtime/UMG/Public/Components/PanelWidget.h" 31 | #include "Runtime/UMG/Public/Components/VerticalBox.h" 32 | #include "Runtime/UMG/Public/Components/HorizontalBox.h" 33 | #include "Runtime/UMG/Public/Components/Button.h" 34 | #include "Runtime/UMG/Public/Components/VerticalBox.h" 35 | #include "Runtime/UMG/Public/Components/HorizontalBox.h" 36 | #include "Runtime/Engine/Classes/GameFramework/PlayerController.h" 37 | #include "Runtime/Engine/Classes/GameFramework/Actor.h" 38 | #include "Runtime/Engine/Classes/Kismet/GameplayStatics.h" 39 | #include "Runtime/Engine/Classes/Engine/Texture.h" 40 | #include "Runtime/Engine/Classes/Engine/Texture2D.h" 41 | #include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h" 42 | #include "Runtime/Engine/Classes/Sound/SoundCue.h" 43 | #include "../../Classes/GameFramework/MyPlayerController.h" 44 | #include "Runtime/Engine/Public/EngineUtils.h" 45 | #include "Runtime/Engine/Classes/Engine/World.h" 46 | #include "Engine.h" 47 | 48 | #define LOCTEXT_NAMESPACE "MenuPadPlus" 49 | 50 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_ONE = 0; 51 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_TWO = 1; 52 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_THREE = 2; 53 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_FOUR = 3; 54 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_FIVE = 4; 55 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_SIX = 5; 56 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_SEVEN = 6; 57 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_EIGHT = 7; 58 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_NINE = 8; 59 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_TEN = 9; 60 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_ELEVEN = 10; 61 | const int32 UUserWidget_MenuPadPlus::ROOT_MENU_TWELVE = 11; 62 | const int32 UUserWidget_MenuPadPlus::PLAYER_CONTROLLER_INDEX = 0; 63 | 64 | #pragma region UUserWidget Interface 65 | void UUserWidget_MenuPadPlus::NativeConstruct() 66 | { 67 | Super::NativeConstruct(); 68 | 69 | //~ Begin MenuPadPlus 70 | bHasFinishedSetup = false; 71 | Timer = 0.f; 72 | TimeNeededToLoad = 0.08f; 73 | ButtonProperties.NormalTextureArray.Empty(); 74 | ButtonProperties.HoveredTextureArray.Empty(); 75 | ButtonProperties.PressedTextureArray.Empty(); 76 | BoxData.RootMenuArray.Empty(); 77 | InitMenus(); 78 | //~ End MenuPadPlus 79 | } 80 | 81 | void UUserWidget_MenuPadPlus::NativeDestruct() 82 | { 83 | Super::NativeDestruct(); 84 | 85 | //~ Begin MenuPadPlus 86 | ButtonProperties.ClearAll(); 87 | BoxData.RootMenuArray.Empty(); 88 | OwnerContainer = nullptr; 89 | //~ End MenuPadPlus 90 | } 91 | 92 | void UUserWidget_MenuPadPlus::NativeTick(const FGeometry& MyGeometry, float DeltaTime) 93 | { 94 | Super::NativeTick(MyGeometry, DeltaTime); 95 | 96 | //~ Begin MenuPadPlus 97 | RunMenuPadPlus(DeltaTime); 98 | //~ End MenuPadPlus 99 | } 100 | 101 | // Use to "Go Back" in Menus. 102 | FReply UUserWidget_MenuPadPlus::NativeOnKeyUp(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) 103 | { 104 | //~ Begin MenuPadPlus 105 | auto const WorldPtr = GetWorld(); 106 | auto ArrayLength = GetNumMenus(ButtonProperties.BoxArray); 107 | auto const MenuCount = 1; 108 | 109 | if (ensure(WorldPtr)) 110 | { 111 | auto PC = Cast(UGameplayStatics::GetPlayerController(WorldPtr, PLAYER_CONTROLLER_INDEX)); 112 | 113 | if (PC != nullptr) 114 | { 115 | if (ArrayLength > MenuCount) 116 | { 117 | for (int32 i = 0; i < ArrayLength; ++i) 118 | { 119 | if (ButtonProperties.BoxArray[i]->IsVisible() && ButtonProperties.BoxArray.IsValidIndex(i - 1)) 120 | { 121 | // Example: "B" Button (XBox controller) 122 | if (InKeyEvent.GetKey() == ButtonProperties.GoBackButton) 123 | { 124 | // Hide Current Menu 125 | ButtonProperties.BoxArray[i]->SetVisibility(ESlateVisibility::Hidden); 126 | 127 | // Show Previous Menu 128 | ButtonProperties.BoxArray[i - 1]->SetVisibility(ESlateVisibility::Visible); 129 | 130 | // Force Normal State of Buttons 131 | int32 BoxChildrenNum = ButtonProperties.BoxArray[i - 1]->Buttons.Num(); 132 | 133 | for (int32 j = 0; j < BoxChildrenNum; ++j) 134 | ButtonProperties.BoxArray[i - 1]->Buttons[j]->ForceNormalText(); 135 | 136 | // Set new focus on previous menu button 137 | UMenuPadPlusStatics::SetButtonFocus(ButtonProperties.BoxArray[i - 1]->GetFirstWidget(), PC); 138 | 139 | // TODO: Add Pressed Sound 140 | 141 | return FReply::Handled(); 142 | } 143 | } 144 | } 145 | } 146 | } 147 | } 148 | //~ End MenuPadPlus 149 | 150 | return FReply::Unhandled(); 151 | } 152 | #pragma endregion 153 | 154 | #pragma region MenuPadPlus 155 | int32 UUserWidget_MenuPadPlus::InitMenus() 156 | { 157 | // Allows 12 by default 158 | auto Size = 12; 159 | BoxData.RootMenuArray.Reserve(Size); 160 | 161 | for (int32 i = 0; i < 12; ++i) 162 | { 163 | class UMenuPadPlusPanelWidget* Temp = nullptr; 164 | BoxData.RootMenuArray.Add(Temp); 165 | } 166 | 167 | { 168 | SetMenuChildren(BoxData.RootMenuArray[0], ROOT_MENU_ONE); 169 | SetMenuChildren(BoxData.RootMenuArray[1], ROOT_MENU_TWO); 170 | SetMenuChildren(BoxData.RootMenuArray[2], ROOT_MENU_THREE); 171 | SetMenuChildren(BoxData.RootMenuArray[3], ROOT_MENU_FOUR); 172 | SetMenuChildren(BoxData.RootMenuArray[4], ROOT_MENU_FIVE); 173 | SetMenuChildren(BoxData.RootMenuArray[5], ROOT_MENU_SIX); 174 | SetMenuChildren(BoxData.RootMenuArray[6], ROOT_MENU_SEVEN); 175 | SetMenuChildren(BoxData.RootMenuArray[7], ROOT_MENU_EIGHT); 176 | SetMenuChildren(BoxData.RootMenuArray[8], ROOT_MENU_NINE); 177 | SetMenuChildren(BoxData.RootMenuArray[9], ROOT_MENU_TEN); 178 | SetMenuChildren(BoxData.RootMenuArray[10], ROOT_MENU_ELEVEN); 179 | SetMenuChildren(BoxData.RootMenuArray[11], ROOT_MENU_TWELVE); 180 | } 181 | 182 | return SUCCESS; 183 | } 184 | 185 | template 186 | Type* UUserWidget_MenuPadPlus::FillArrayWith(Type* RootMenu) 187 | { 188 | if (RootMenu != nullptr) 189 | { 190 | ButtonProperties.BoxArray.Add(RootMenu); 191 | return RootMenu; 192 | } 193 | 194 | return nullptr; 195 | } 196 | 197 | template 198 | Idx UUserWidget_MenuPadPlus::SetMenuChildren(Type* RootMenu, const Idx& Index) 199 | { 200 | if (UPanelWidget* RootPanel = Cast(GetRootWidget())) 201 | { 202 | if ((RootMenu = Cast(RootPanel->GetChildAt(Index))) != 0) 203 | { 204 | FillArrayWith(RootMenu); 205 | auto BoxChildrenNum = RootMenu->GetChildrenCount(); 206 | 207 | for (int32 i = 0; i < BoxChildrenNum; ++i) 208 | { 209 | if (UMenuPadPlusButton* Button = Cast(RootMenu->GetChildAt(i))) 210 | { 211 | RootMenu->Buttons.Add(Button); 212 | Button->OwnerContainer = RootMenu; 213 | 214 | auto ButtonChildrenNum = RootMenu->Buttons.Num(); 215 | 216 | for (int32 j = 0; j < ButtonChildrenNum; ++j) 217 | { 218 | if (UTexture2D* NormalImage = Cast(RootMenu->Buttons[j]->WidgetStyle.Normal.GetResourceObject())) 219 | ButtonProperties.NormalTextureArray.Add(NormalImage); 220 | 221 | if (UTexture2D* HoveredImage = Cast(RootMenu->Buttons[j]->WidgetStyle.Hovered.GetResourceObject())) 222 | ButtonProperties.HoveredTextureArray.Add(HoveredImage); 223 | 224 | if (UTexture2D* PressedImage = Cast(RootMenu->Buttons[j]->WidgetStyle.Pressed.GetResourceObject())) 225 | ButtonProperties.PressedTextureArray.Add(PressedImage); 226 | } 227 | } 228 | } 229 | } 230 | } 231 | 232 | return SUCCESS; 233 | } 234 | 235 | // Runs the system 236 | void UUserWidget_MenuPadPlus::RunMenuPadPlus(float DeltaSeconds) 237 | { 238 | if (!bHasFinishedSetup) 239 | { 240 | if (GetTimer() < GetTimeNeededToLoad()) RunTimer(DeltaSeconds); 241 | else bHasFinishedSetup = true; 242 | } 243 | else 244 | { 245 | RunMenuAt(ROOT_MENU_ONE); 246 | RunMenuAt(ROOT_MENU_TWO); 247 | RunMenuAt(ROOT_MENU_THREE); 248 | RunMenuAt(ROOT_MENU_FOUR); 249 | RunMenuAt(ROOT_MENU_FIVE); 250 | RunMenuAt(ROOT_MENU_SIX); 251 | RunMenuAt(ROOT_MENU_SEVEN); 252 | RunMenuAt(ROOT_MENU_EIGHT); 253 | RunMenuAt(ROOT_MENU_NINE); 254 | RunMenuAt(ROOT_MENU_TEN); 255 | RunMenuAt(ROOT_MENU_ELEVEN); 256 | RunMenuAt(ROOT_MENU_TWELVE); 257 | } 258 | } 259 | 260 | void UUserWidget_MenuPadPlus::OnJoystickAxisChanged( 261 | TArray ButtonsArray 262 | , class AMyPlayerController* InPC) 263 | { 264 | auto const MenuCount = 0; 265 | 266 | if (ButtonsArray.Num() > MenuCount && InPC) 267 | { 268 | int32 ArrayLength = ButtonsArray.Num(); 269 | 270 | for (int32 i = 0; i < ArrayLength; ++i) 271 | { 272 | FVector2D NormalSize = ButtonsArray[i]->WidgetStyle.Normal.GetImageSize(); 273 | FVector2D HoveredSize = ButtonsArray[i]->WidgetStyle.Hovered.GetImageSize(); 274 | FVector2D PressedSize = ButtonsArray[i]->WidgetStyle.Pressed.GetImageSize(); 275 | 276 | auto HoveredSound = Cast(ButtonsArray[i]->WidgetStyle.HoveredSlateSound.GetResourceObject()); 277 | auto PressedSound = Cast(ButtonsArray[i]->WidgetStyle.PressedSlateSound.GetResourceObject()); 278 | 279 | if (ButtonsArray[i]->HasUserFocus(InPC)) 280 | { 281 | FButtonStyle ButtonStyle; 282 | 283 | ButtonStyle.Normal.SetResourceObject(ButtonProperties.HoveredTextureArray[i]); 284 | ButtonStyle.Hovered.SetResourceObject(ButtonProperties.HoveredTextureArray[i]); 285 | ButtonStyle.Pressed.SetResourceObject(ButtonProperties.PressedTextureArray[i]); 286 | 287 | ButtonStyle.Normal.ImageSize = NormalSize; 288 | ButtonStyle.Hovered.ImageSize = HoveredSize; 289 | ButtonStyle.Pressed.ImageSize = PressedSize; 290 | 291 | ButtonStyle.HoveredSlateSound.SetResourceObject(HoveredSound); 292 | ButtonStyle.PressedSlateSound.SetResourceObject(PressedSound); 293 | 294 | if (!ButtonsArray[i]->bCanPlayHoveredSound) 295 | { 296 | auto const WorldPtr = GetWorld(); 297 | if (ensure(WorldPtr)) UGameplayStatics::PlaySound2D(WorldPtr, HoveredSound); 298 | ButtonsArray[i]->bCanPlayHoveredSound = true; 299 | } 300 | 301 | ButtonsArray[i]->SetStyle(ButtonStyle); 302 | if (!ButtonsArray[i]->bHasForcedPressed) ButtonsArray[i]->ForceHoveredText(); 303 | } 304 | else 305 | { 306 | FButtonStyle ButtonStyle; 307 | 308 | ButtonStyle.Normal.SetResourceObject(ButtonProperties.NormalTextureArray[i]); 309 | ButtonStyle.Hovered.SetResourceObject(ButtonProperties.HoveredTextureArray[i]); 310 | ButtonStyle.Pressed.SetResourceObject(ButtonProperties.PressedTextureArray[i]); 311 | 312 | ButtonStyle.Normal.ImageSize = NormalSize; 313 | ButtonStyle.Hovered.ImageSize = HoveredSize; 314 | ButtonStyle.Pressed.ImageSize = PressedSize; 315 | 316 | ButtonStyle.PressedSlateSound.SetResourceObject(PressedSound); 317 | ButtonStyle.HoveredSlateSound.SetResourceObject(HoveredSound); 318 | 319 | if (ButtonsArray[i]->bCanPlayHoveredSound) ButtonsArray[i]->bCanPlayHoveredSound = false; 320 | 321 | ButtonsArray[i]->SetStyle(ButtonStyle); 322 | ButtonsArray[i]->ForceNormalText(); 323 | } 324 | } 325 | } 326 | } 327 | 328 | // When we want to use different images 329 | void UUserWidget_MenuPadPlus::OnJoystickAxisChangedAlternate( 330 | TArray ButtonsArray 331 | , class UObject* NormalTexture 332 | , class UObject* HoveredTexture 333 | , class UObject* PressedTexture 334 | , float ImageSizeX 335 | , float ImageSizeY 336 | , class USoundCue* HoveredSound 337 | , class USoundCue* PressedSound 338 | , class AMyPlayerController* InPC) 339 | { 340 | auto const MenuCount = 0; 341 | 342 | if (ButtonsArray.Num() > MenuCount && InPC) 343 | { 344 | int32 ArrayLength = ButtonsArray.Num(); 345 | 346 | for (int32 i = 0; i < ArrayLength; ++i) 347 | { 348 | if (ButtonsArray[i]->HasUserFocus(InPC)) 349 | { 350 | FButtonStyle ButtonStyle; 351 | ButtonStyle.Normal.SetResourceObject(HoveredTexture); 352 | ButtonStyle.Hovered.SetResourceObject(HoveredTexture); 353 | ButtonStyle.Pressed.SetResourceObject(PressedTexture); 354 | 355 | ButtonStyle.Normal.ImageSize = FVector2D(ImageSizeX, ImageSizeY); 356 | ButtonStyle.Hovered.ImageSize = FVector2D(ImageSizeX, ImageSizeY); 357 | ButtonStyle.Pressed.ImageSize = FVector2D(ImageSizeX, ImageSizeY); 358 | 359 | if (PressedSound != NULL) ButtonStyle.PressedSlateSound.SetResourceObject(PressedSound); 360 | 361 | if (HoveredSound != NULL) 362 | { 363 | if (!ButtonsArray[i]->bCanPlayHoveredSound) 364 | { 365 | auto const WorldPtr = GetWorld(); 366 | if (ensure(WorldPtr)) UGameplayStatics::PlaySound2D(WorldPtr, HoveredSound); 367 | ButtonsArray[i]->bCanPlayHoveredSound = true; 368 | } 369 | } 370 | 371 | ButtonsArray[i]->SetStyle(ButtonStyle); 372 | if (!ButtonsArray[i]->bHasForcedPressed) ButtonsArray[i]->ForceHoveredText(); 373 | } 374 | else 375 | { 376 | FButtonStyle ButtonStyle; 377 | ButtonStyle.Normal.SetResourceObject(NormalTexture); 378 | ButtonStyle.Hovered.SetResourceObject(NormalTexture); 379 | 380 | ButtonStyle.Normal.ImageSize = FVector2D(ImageSizeX, ImageSizeY); 381 | ButtonStyle.Hovered.ImageSize = FVector2D(ImageSizeX, ImageSizeY); 382 | 383 | if (ButtonsArray[i]->bCanPlayHoveredSound) ButtonsArray[i]->bCanPlayHoveredSound = false; 384 | 385 | ButtonsArray[i]->SetStyle(ButtonStyle); 386 | ButtonsArray[i]->ForceNormalText(); 387 | } 388 | } 389 | } 390 | } 391 | 392 | void UUserWidget_MenuPadPlus::RunMenuAt(const int32 Index) 393 | { 394 | auto const MenuCount = 0; 395 | auto const AlternateImageCount = 2; 396 | 397 | if (GetNumMenus(ButtonProperties.BoxArray) > MenuCount) 398 | { 399 | if (ButtonProperties.BoxArray.IsValidIndex(Index)) 400 | { 401 | if (ButtonProperties.BoxArray[Index]->bUseAlternateImages == true) 402 | { 403 | if (ButtonProperties.BoxArray[Index]->IsVisible()) 404 | { 405 | if (ButtonProperties.BoxArray[Index]->DoesContainButtons()) 406 | { 407 | if (ButtonProperties.BoxArray[Index]->GetAlternateImagesSize() > AlternateImageCount) 408 | { 409 | OnJoystickAxisChangedAlternate( 410 | ButtonProperties.BoxArray[Index]->GetButtons() // Buttons 411 | , ButtonProperties.BoxArray[Index]->GetAlternateImages_Normal() // Normal Texture 412 | , ButtonProperties.BoxArray[Index]->GetAlternateImages_Hovered() // Hovered Texture 413 | , ButtonProperties.BoxArray[Index]->GetAlternateImages_Pressed() // Pressed Texture 414 | , ButtonProperties.BoxArray[Index]->GetAlternateSizeX() // Size X 415 | , ButtonProperties.BoxArray[Index]->GetAlternateSizeY() // Size Y 416 | , ButtonProperties.BoxArray[Index]->GetAlternateHoveredSound() // Hovered Sound 417 | , ButtonProperties.BoxArray[Index]->GetAlternatePressedSound() // Pressed Sound 418 | , ButtonProperties.BoxArray[Index]->GetOwningPlayerController()); // The Player Controller 419 | } 420 | } 421 | } 422 | } 423 | else 424 | { 425 | if (ButtonProperties.BoxArray[Index]->IsVisible()) 426 | { 427 | if (ButtonProperties.BoxArray[Index]->DoesContainButtons()) 428 | { 429 | OnJoystickAxisChanged( 430 | ButtonProperties.BoxArray[Index]->GetButtons() // Buttons 431 | , ButtonProperties.BoxArray[Index]->GetOwningPlayerController()); // The Player Controller 432 | } 433 | } 434 | } 435 | } 436 | } 437 | } 438 | 439 | UMenuPadPlusButton* UUserWidget_MenuPadPlus::GetFocusedWidget(TArray Buttons) 440 | { 441 | for (auto& Widget : Buttons) 442 | if (Widget->bHasForcedHover) 443 | return Widget; 444 | 445 | return nullptr; 446 | } 447 | 448 | UMenuPadPlusButton* UUserWidget_MenuPadPlus::GetFirstWidget() 449 | { 450 | auto const MenuCount = 0; 451 | 452 | if (UPanelWidget* RootPanel = Cast(GetRootWidget())) 453 | { 454 | if (GetNumMenus(ButtonProperties.BoxArray) > MenuCount) 455 | { 456 | if ((ButtonProperties.BoxArray[ROOT_MENU_ONE] = Cast(RootPanel->GetChildAt(MenuCount))) != 0) 457 | return ButtonProperties.BoxArray[ROOT_MENU_ONE]->GetFirstWidget(); 458 | else 459 | return nullptr; 460 | } 461 | } 462 | 463 | return nullptr; 464 | } 465 | 466 | UMenuPadPlusButton* UUserWidget_MenuPadPlus::GetPreviousWidget() 467 | { 468 | auto const MenuCount = 1; 469 | auto VerticalArrayLength = GetNumMenus(ButtonProperties.BoxArray); 470 | 471 | if (VerticalArrayLength > MenuCount) 472 | for (int32 i = 0; i < VerticalArrayLength; ++i) 473 | return ButtonProperties.BoxArray[i - 1]->GetFirstWidget(); 474 | 475 | return nullptr; 476 | } 477 | 478 | void UUserWidget_MenuPadPlus::ResetAllWidgetFocus(TArray CurrentButton) 479 | { 480 | for (auto const& Widget : CurrentButton) 481 | Widget->ForceNormalText(); 482 | 483 | auto const WorldPtr = GetWorld(); 484 | 485 | if (ensure(WorldPtr)) 486 | { 487 | auto PC = Cast(UGameplayStatics::GetPlayerController(WorldPtr, PLAYER_CONTROLLER_INDEX)); 488 | if (PC != nullptr) UMenuPadPlusStatics::SetButtonFocus(GetFirstWidget(), PC); 489 | } 490 | } 491 | #pragma endregion 492 | 493 | #undef LOCTEXT_NAMESPACE --------------------------------------------------------------------------------