├── .gitignore ├── CreateNewProject.bat ├── CreateNewProject.sh ├── Media ├── 00_EmptyWindow.png ├── 01_winconsole.png ├── 02_linuxconsole.png ├── 04_WinNewWindow.png ├── slate-format-text.png ├── starship-colors.png ├── starship-icons.png └── starship-widgets.png ├── README.md ├── Source ├── EntryPoints │ ├── IOS │ │ └── IOSUnrealSlateAppTemplateMain.cpp │ ├── Linux │ │ └── UnrealSlateAppTemplateMainLinux.cpp │ ├── Mac │ │ └── UnrealSlateAppTemplateMainMac.cpp │ └── Windows │ │ └── UnrealSlateAppTemplateMainWindows.cpp ├── UnrealSlateAppTemplate.Build.cs ├── UnrealSlateAppTemplate.Target.cs ├── UnrealSlateAppTemplateApp.cpp ├── UnrealSlateAppTemplateApp.h └── UnrealSlateAppTemplateModule │ ├── Private │ ├── UnrealSlateAppTemplateModule.cpp │ ├── UnrealSlateAppTemplateModuleCommands.cpp │ └── UnrealSlateAppTemplateModuleStyle.cpp │ ├── Public │ ├── UnrealSlateAppTemplateModule.h │ ├── UnrealSlateAppTemplateModuleCommands.h │ └── UnrealSlateAppTemplateModuleStyle.h │ └── UnrealSlateAppTemplateModule.Build.cs ├── Tools └── TemplateNamer │ └── TemplateNamer.py └── UnrealSlateAppTemplate.uproject /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio 2015 user specific files 2 | .vs/ 3 | 4 | .vscode/ 5 | .ignore 6 | *.code-workspace 7 | 8 | # Jet Brains products specific files and caches 9 | .idea/ 10 | _ReSharper.Caches/ 11 | 12 | venv 13 | 14 | # Compiled Object files 15 | *.slo 16 | *.lo 17 | *.o 18 | *.obj 19 | 20 | # Precompiled Headers 21 | *.gch 22 | *.pch 23 | 24 | # Compiled Dynamic libraries 25 | *.so 26 | *.dylib 27 | *.dll 28 | 29 | # Fortran module files 30 | *.mod 31 | 32 | # Compiled Static libraries 33 | *.lai 34 | *.la 35 | *.a 36 | *.lib 37 | 38 | # Executables 39 | *.exe 40 | *.out 41 | *.app 42 | *.ipa 43 | 44 | # These project files can be generated by the engine 45 | *.xcodeproj 46 | *.xcworkspace 47 | *.sln 48 | *.suo 49 | *.opensdf 50 | *.sdf 51 | *.VC.db 52 | *.VC.opendb 53 | 54 | # Precompiled Assets 55 | SourceArt/**/*.png 56 | SourceArt/**/*.tga 57 | 58 | # Binary Files 59 | Binaries/* 60 | Plugins/*/Binaries/* 61 | 62 | # Builds 63 | Build/* 64 | 65 | # Whitelist PakBlacklist-.txt files 66 | !Build/*/ 67 | Build/*/** 68 | !Build/*/PakBlacklist*.txt 69 | 70 | # Don't ignore icon files in Build 71 | !Build/**/*.ico 72 | 73 | # Built data for maps 74 | *_BuiltData.uasset 75 | 76 | # Configuration files generated by the Editor 77 | Saved/* 78 | 79 | # Compiled source files for the engine to use 80 | Intermediate/* 81 | Plugins/*/Intermediate/* 82 | 83 | # Cache files for the editor to use 84 | DerivedDataCache/* 85 | -------------------------------------------------------------------------------- /CreateNewProject.bat: -------------------------------------------------------------------------------- 1 | @Echo off 2 | 3 | echo ----- 4 | 5 | pushd %~dp0% 6 | 7 | :: Check for Python Installation 8 | python -c "import sys; assert sys.version_info >= (3,6)" 2>NUL 9 | if errorlevel 1 ( 10 | echo Error^: Python3 is not installed. Install Python3 to run the script. 11 | echo ----- 12 | goto:eof 13 | ) 14 | 15 | cd Tools/TemplateNamer/ 16 | 17 | python TemplateNamer.py -i 18 | 19 | popd 20 | 21 | echo ----- -------------------------------------------------------------------------------- /CreateNewProject.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "-----" 4 | BASEDIR=$(dirname "$0") 5 | 6 | if ! python3 -c 'import sys; assert sys.version_info >= (3,6)' > /dev/null; then 7 | echo Python3 is not installed. Install Python3 to run the script. 8 | echo "-----" 9 | exit 1 10 | fi 11 | 12 | cd $BASEDIR/Tools/TemplateNamer/ 13 | python3 TemplateNamer.py -i 14 | 15 | echo "-----" 16 | -------------------------------------------------------------------------------- /Media/00_EmptyWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lpestl/UnrealSlateAppTemplate/32e7fe654f1007bcaacfdf2ed460abb89bb64220/Media/00_EmptyWindow.png -------------------------------------------------------------------------------- /Media/01_winconsole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lpestl/UnrealSlateAppTemplate/32e7fe654f1007bcaacfdf2ed460abb89bb64220/Media/01_winconsole.png -------------------------------------------------------------------------------- /Media/02_linuxconsole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lpestl/UnrealSlateAppTemplate/32e7fe654f1007bcaacfdf2ed460abb89bb64220/Media/02_linuxconsole.png -------------------------------------------------------------------------------- /Media/04_WinNewWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lpestl/UnrealSlateAppTemplate/32e7fe654f1007bcaacfdf2ed460abb89bb64220/Media/04_WinNewWindow.png -------------------------------------------------------------------------------- /Media/slate-format-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lpestl/UnrealSlateAppTemplate/32e7fe654f1007bcaacfdf2ed460abb89bb64220/Media/slate-format-text.png -------------------------------------------------------------------------------- /Media/starship-colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lpestl/UnrealSlateAppTemplate/32e7fe654f1007bcaacfdf2ed460abb89bb64220/Media/starship-colors.png -------------------------------------------------------------------------------- /Media/starship-icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lpestl/UnrealSlateAppTemplate/32e7fe654f1007bcaacfdf2ed460abb89bb64220/Media/starship-icons.png -------------------------------------------------------------------------------- /Media/starship-widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lpestl/UnrealSlateAppTemplate/32e7fe654f1007bcaacfdf2ed460abb89bb64220/Media/starship-widgets.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnrealSlateAppTemplate # 2 | 3 | Project template for creating cross-platform desktop applications based on [Unrial Engine](https://www.unrealengine.com/). For the GUI, the [Slate UI Framework](https://docs.unrealengine.com/en-US/ProgrammingAndScripting/Slate/index.html) (part of UnrealEngine) is used. 4 | 5 | ## Description ## 6 | 7 | This repository is a basic standalone application template based on the [Slate UI Framework](https://docs.unrealengine.com/en-US/ProgrammingAndScripting/Slate/index.html). This is how [Gerke Max Preussner says about the framework](https://gmpreussner.com/portfolio/slate-ui): 8 | 9 | > Slate is written entirely in C++ and runs on all Unreal Engine 4 supported platforms. It is render interface agnostic, which allows it to be used in standalone desktop and mobile applications that do not depend on the game engine. Its architecture rests on two powerful concepts that distinguish it from many classical frameworks: declarative syntax and composition. 10 | 11 | This repository contains the basic foundation for your future cross-platform application. 12 | 13 | As far as I know, there is currently no easy way to generate such an almost empty project. The GitHub repository with the UE4 contains only a few examples of stand-alone applications, on the basis of which I made this repository for quick and convenient generation of your own application. 14 | 15 | ![Empty window](Media/00_EmptyWindow.png) 16 | 17 | ## Requirements ## 18 | 19 | 1) In order for the "TemplateRenamer" Tool in the form of a script to run correctly, you need to install [Python 3](https://www.python.org/downloads/) (tested with 3.8, 3.9, 3.12): 20 | * Windows - https://www.python.org/downloads/windows/ 21 | * Linux - https://www.python.org/downloads/source/ 22 | * MacOS - https://www.python.org/downloads/mac-osx/ 23 | 2) In order for the project to be generated, compiled and run after renaming, you need to have an up-to-date version of [Unrial Engine](https://www.unrealengine.com/) (tested on 5.2, 5.3) compiled from [sources from GitHub](https://github.com/EpicGames/UnrealEngine) (**Release** branch is recommended). For this, there is a detailed instruction from EpicGames: 24 | * [How do I access Unreal Engine C++ source code via GitHub?](https://www.unrealengine.com/en-US/ue-on-github) 25 | * [Downloading Unreal Engine Source Code](https://docs.unrealengine.com/en-US/ProgrammingAndScripting/ProgrammingWithCPP/DownloadingSourceCode/index.html) 26 | * [Building Unreal Engine from Source](https://docs.unrealengine.com/en-US/ProductionPipelines/DevelopmentSetup/BuildingUnrealEngine/index.html) 27 | 28 | ## Quick start ## 29 | 30 | In order to get a new project with a new name, you need to do the following: 31 | 32 | 1) [Install and configure all requirements](#_requirements) 33 | 2) Go to the root of the repository and run the script `CreatNewProject` (`CreatNewProject.bat` for Windows and `CreatNewProject.sh` for Linux and MacOS). This step will execute the `Tools/TemplateNamer/TemplateRenamer.py` script interactively. 34 | 3) In the command line window, you will first need to enter the new project name, and then specify the path where to place the new project. The console will look something like this: 35 | 36 | | Windows Cmd | Linux bash | 37 | |:------------|:-----------| 38 | | ![Win console](Media/01_winconsole.png) | ![Linux console](Media/02_linuxconsole.png) | 39 | 40 | 4) Go to the folder with the newly created project, right-click on the `*.uproject` file and select "*Switch Unreal Engine version*" or "*Generate project files*" (there are alternative ways for the command line, [more details here](https://docs.unrealengine.com/en-US/ProductionPipelines/BuildTools/UnrealBuildTool/ProjectFilesForIDEs/index.html)) 41 | 5) Now open your IDE for which the project was generated, select the project to start, and after compilation, you will see an empty window. 42 | 43 | ![New window](Media/04_WinNewWindow.png) 44 | 45 | Note: It is important to understand that at the first compilation, building the project can take a long time, since IDE tries to index the entire source code of the engine, as well as build the modules that are included in the dependencies. In the future, if you do not change the engine code, then the dependent modules will not be rebuilt, which means that the assembly of your project will be faster. 46 | 47 | ## Slate UI Gallery ## 48 | 49 | All screenshots are taken from base app **SlateViewer** 50 | 51 | * ![Slate Starship widgets](Media/starship-widgets.png) 52 | * ![Starship icons](Media/starship-icons.png) 53 | * ![Slate text format](Media/slate-format-text.png) 54 | * ![Base starship theme colors](Media/starship-colors.png) 55 | -------------------------------------------------------------------------------- /Source/EntryPoints/IOS/IOSUnrealSlateAppTemplateMain.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "UnrealSlateAppTemplateApp.h" 4 | #include "IOS/IOSAppDelegate.h" 5 | #include "IOS/IOSCommandLineHelper.h" 6 | #include "IOS/SlateOpenGLESView.h" 7 | #include "Widgets/Testing/STestSuite.h" 8 | 9 | #import 10 | 11 | 12 | #define IOS_MAX_PATH 1024 13 | #define CMD_LINE_MAX 16384 14 | 15 | FString GSavedCommandLine; 16 | 17 | void FAppEntry::Suspend() 18 | { 19 | } 20 | 21 | void FAppEntry::Resume() 22 | { 23 | } 24 | 25 | void FAppEntry::SuspendTick() 26 | { 27 | } 28 | 29 | bool FAppEntry::IsStartupMoviePlaying() 30 | { 31 | return false; 32 | } 33 | 34 | 35 | void FAppEntry::PreInit(IOSAppDelegate* AppDelegate, UIApplication* Application) 36 | { 37 | // make a controller object 38 | AppDelegate.SlateController = [[SlateOpenGLESViewController alloc] init]; 39 | 40 | // property owns it now 41 | [AppDelegate.SlateController release]; 42 | 43 | // point to the GL view we want to use 44 | AppDelegate.RootView = [AppDelegate.SlateController view]; 45 | 46 | [AppDelegate.Window setRootViewController:AppDelegate.SlateController]; 47 | } 48 | 49 | 50 | void FAppEntry::PlatformInit() 51 | { 52 | } 53 | 54 | 55 | void FAppEntry::Init() 56 | { 57 | // start up the main loop 58 | GEngineLoop.PreInit(FCommandLine::Get()); 59 | 60 | // move it to this thread 61 | SlateOpenGLESView* View = (SlateOpenGLESView*)[IOSAppDelegate GetDelegate].RootView; 62 | [EAGLContext setCurrentContext:View.Context]; 63 | 64 | // crank up a normal Slate application using the platform's standalone renderer 65 | FSlateApplication::InitializeAsStandaloneApplication(GetStandardStandaloneRenderer()); 66 | 67 | // Bring up the test suite. 68 | { 69 | RestoreSlateTestSuite(); 70 | } 71 | 72 | #if WITH_SHARED_POINTER_TESTS 73 | SharedPointerTesting::TestSharedPointer< ESPMode::Fast >(); 74 | SharedPointerTesting::TestSharedPointer< ESPMode::ThreadSafe >(); 75 | #endif 76 | 77 | // loop while the server does the rest 78 | double LastTime = FPlatformTime::Seconds(); 79 | } 80 | 81 | 82 | void FAppEntry::Tick() 83 | { 84 | FSlateApplication::Get().PumpMessages(); 85 | FSlateApplication::Get().Tick(); 86 | 87 | // Sleep 88 | FPlatformProcess::Sleep( 0 ); 89 | } 90 | 91 | 92 | void FAppEntry::Shutdown() 93 | { 94 | FSlateApplication::Shutdown(); 95 | } 96 | 97 | 98 | int main(int argc, char *argv[]) 99 | { 100 | for (int32 Option = 1; Option < argc; Option++) 101 | { 102 | GSavedCommandLine += TEXT(" "); 103 | GSavedCommandLine += ANSI_TO_TCHAR(argv[Option]); 104 | } 105 | 106 | FIOSCommandLineHelper::InitCommandArgs(FString()); 107 | 108 | @autoreleasepool { 109 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([IOSAppDelegate class])); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Source/EntryPoints/Linux/UnrealSlateAppTemplateMainLinux.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "UnrealSlateAppTemplateApp.h" 4 | #include "UnixCommonStartup.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | return CommonUnixMain(argc, argv, &RunUnrealSlateAppTemplate); 9 | } 10 | -------------------------------------------------------------------------------- /Source/EntryPoints/Mac/UnrealSlateAppTemplateMainMac.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "UnrealSlateAppTemplateApp.h" 4 | #include "HAL/ExceptionHandling.h" 5 | #include "Mac/CocoaThread.h" 6 | 7 | static FString GSavedCommandLine; 8 | 9 | @interface UE4AppDelegate : NSObject 10 | { 11 | } 12 | 13 | @end 14 | 15 | @implementation UE4AppDelegate 16 | 17 | //handler for the quit apple event used by the Dock menu 18 | - (void)handleQuitEvent:(NSAppleEventDescriptor*)Event withReplyEvent:(NSAppleEventDescriptor*)ReplyEvent 19 | { 20 | [NSApp terminate:self]; 21 | } 22 | 23 | - (void) runGameThread:(id)Arg 24 | { 25 | FPlatformMisc::SetGracefulTerminationHandler(); 26 | FPlatformMisc::SetCrashHandler(nullptr); 27 | 28 | RunUnrealSlateAppTemplate(*GSavedCommandLine); 29 | 30 | [NSApp terminate: self]; 31 | } 32 | 33 | - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)Sender; 34 | { 35 | if(!IsEngineExitRequested() || ([NSThread gameThread] && [NSThread gameThread] != [NSThread mainThread])) 36 | { 37 | RequestEngineExit(TEXT("applicationShouldTerminate")); 38 | return NSTerminateLater; 39 | } 40 | else 41 | { 42 | return NSTerminateNow; 43 | } 44 | } 45 | 46 | - (void)applicationDidFinishLaunching:(NSNotification *)Notification 47 | { 48 | //install the custom quit event handler 49 | NSAppleEventManager* appleEventManager = [NSAppleEventManager sharedAppleEventManager]; 50 | [appleEventManager setEventHandler:self andSelector:@selector(handleQuitEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEQuitApplication]; 51 | 52 | RunGameThread(self, @selector(runGameThread:)); 53 | } 54 | 55 | @end 56 | 57 | int main(int argc, char *argv[]) 58 | { 59 | for (int32 Option = 1; Option < argc; Option++) 60 | { 61 | GSavedCommandLine += TEXT(" "); 62 | FString Argument(ANSI_TO_TCHAR(argv[Option])); 63 | if (Argument.Contains(TEXT(" "))) 64 | { 65 | if (Argument.Contains(TEXT("="))) 66 | { 67 | FString ArgName; 68 | FString ArgValue; 69 | Argument.Split( TEXT("="), &ArgName, &ArgValue ); 70 | Argument = FString::Printf( TEXT("%s=\"%s\""), *ArgName, *ArgValue ); 71 | } 72 | else 73 | { 74 | Argument = FString::Printf(TEXT("\"%s\""), *Argument); 75 | } 76 | } 77 | GSavedCommandLine += Argument; 78 | } 79 | 80 | SCOPED_AUTORELEASE_POOL; 81 | [NSApplication sharedApplication]; 82 | [NSApp setDelegate:[UE4AppDelegate new]]; 83 | [NSApp run]; 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /Source/EntryPoints/Windows/UnrealSlateAppTemplateMainWindows.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | 4 | #include "UnrealSlateAppTemplateApp.h" 5 | #include "Windows/WindowsHWrapper.h" 6 | 7 | 8 | /** 9 | * WinMain, called when the application is started 10 | */ 11 | int WINAPI WinMain( _In_ HINSTANCE hInInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR, _In_ int nCmdShow ) 12 | { 13 | // do the UnrealSlateAppTemplate thing 14 | RunUnrealSlateAppTemplate(GetCommandLineW()); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplate.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using System.IO; 4 | using UnrealBuildTool; 5 | 6 | public class UnrealSlateAppTemplate : ModuleRules 7 | { 8 | public UnrealSlateAppTemplate(ReadOnlyTargetRules Target) : base(Target) 9 | { 10 | PublicIncludePaths.Add(Path.Combine(EngineDirectory, "Source", "Runtime/Launch/Public")); 11 | 12 | PrivateDependencyModuleNames.AddRange( 13 | new string[] { 14 | "AppFramework", 15 | "Core", 16 | "ApplicationCore", 17 | "Projects", 18 | "Slate", 19 | "SlateCore", 20 | "StandaloneRenderer", 21 | } 22 | ); 23 | 24 | PrivateIncludePaths.Add(Path.Combine(EngineDirectory, "Source", "Runtime/Launch/Private")); // For LaunchEngineLoop.cpp include 25 | 26 | if (Target.Platform == UnrealTargetPlatform.IOS || Target.Platform == UnrealTargetPlatform.TVOS) 27 | { 28 | PrivateDependencyModuleNames.AddRange( 29 | new string [] { 30 | "NetworkFile", 31 | "StreamingFile" 32 | } 33 | ); 34 | } 35 | 36 | if (Target.IsInPlatformGroup(UnrealPlatformGroup.Linux)) 37 | { 38 | PrivateDependencyModuleNames.AddRange( 39 | new string[] { 40 | "UnixCommonStartup" 41 | } 42 | ); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplate.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | [SupportedPlatforms(UnrealPlatformClass.Desktop)] 7 | [SupportedPlatforms("IOS")] 8 | public class UnrealSlateAppTemplateTarget : TargetRules 9 | { 10 | public UnrealSlateAppTemplateTarget(TargetInfo Target) : base(Target) 11 | { 12 | Type = TargetType.Program; 13 | LinkType = TargetLinkType.Monolithic; 14 | DefaultBuildSettings = BuildSettingsVersion.Latest; 15 | IncludeOrderVersion = EngineIncludeOrderVersion.Latest; 16 | 17 | LaunchModuleName = "UnrealSlateAppTemplate"; 18 | if (bBuildEditor) 19 | { 20 | ExtraModuleNames.Add("EditorStyle"); 21 | } 22 | 23 | // UnrealSlateAppTemplate doesn't ever compile with the engine linked in 24 | bCompileAgainstEngine = false; 25 | 26 | // We need CoreUObject compiled in as the source code access module requires it 27 | bCompileAgainstCoreUObject = true; 28 | 29 | // UnrealSlateAppTemplate.exe has no exports, so no need to verify that a .lib and .exp file was emitted by 30 | // the linker. 31 | bHasExports = false; 32 | 33 | // Make sure to get all code in SlateEditorStyle compiled in 34 | bBuildDeveloperTools = true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplateApp.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "UnrealSlateAppTemplateApp.h" 4 | #include "UnrealSlateAppTemplateModule/Public/UnrealSlateAppTemplateModule.h" 5 | 6 | #include "Runtime/Launch/Public/RequiredProgramMainCPPInclude.h" 7 | #include "Framework/Application/SlateApplication.h" 8 | #include "Framework/Docking/TabManager.h" 9 | #include "Framework/Docking/WorkspaceItem.h" 10 | #include "Styling/StarshipCoreStyle.h" 11 | 12 | IMPLEMENT_APPLICATION(UnrealSlateAppTemplate, "UnrealSlateAppTemplate"); 13 | 14 | #define LOCTEXT_NAMESPACE "UnrealSlateAppTemplate" 15 | 16 | namespace WorkspaceMenu 17 | { 18 | TSharedRef DeveloperMenu = FWorkspaceItem::NewGroup(LOCTEXT("DeveloperMenu", "Developer")); 19 | } 20 | 21 | 22 | int RunUnrealSlateAppTemplate( const TCHAR* CommandLine ) 23 | { 24 | FTaskTagScope TaskTagScope(ETaskTag::EGameThread); 25 | 26 | // start up the main loop 27 | GEngineLoop.PreInit(CommandLine); 28 | 29 | // Make sure all UObject classes are registered and default properties have been initialized 30 | ProcessNewlyLoadedUObjects(); 31 | 32 | // Tell the module manager it may now process newly-loaded UObjects when new C++ modules are loaded 33 | FModuleManager::Get().StartProcessingNewlyLoadedObjects(); 34 | 35 | // crank up a normal Slate application using the platform's standalone renderer 36 | FSlateApplication::InitializeAsStandaloneApplication(GetStandardStandaloneRenderer()); 37 | 38 | FSlateApplication::InitHighDPI(true); 39 | 40 | // set the application name 41 | FGlobalTabmanager::Get()->SetApplicationTitle(LOCTEXT("AppTitle", "UnrealSlateAppTemplate")); 42 | FAppStyle::SetAppStyleSetName(FStarshipCoreStyle::GetCoreStyle().GetStyleSetName()); 43 | 44 | // launch the main window of the UnrealSlateAppTemplate module 45 | FUnrealSlateAppTemplateModule& UnrealSlateAppTemplateModule = FModuleManager::LoadModuleChecked(FName("UnrealSlateAppTemplateModule")); 46 | UnrealSlateAppTemplateModule.AppStarted(); 47 | 48 | // loop while the server does the rest 49 | while (!IsEngineExitRequested()) 50 | { 51 | BeginExitIfRequested(); 52 | 53 | FTaskGraphInterface::Get().ProcessThreadUntilIdle(ENamedThreads::GameThread); 54 | FStats::AdvanceFrame(false); 55 | FTSTicker::GetCoreTicker().Tick(FApp::GetDeltaTime()); 56 | FSlateApplication::Get().PumpMessages(); 57 | FSlateApplication::Get().Tick(); 58 | FPlatformProcess::Sleep(0.01); 59 | 60 | GFrameCounter++; 61 | } 62 | 63 | FCoreDelegates::OnExit.Broadcast(); 64 | FSlateApplication::Shutdown(); 65 | FModuleManager::Get().UnloadModulesAtShutdown(); 66 | 67 | GEngineLoop.AppPreExit(); 68 | GEngineLoop.AppExit(); 69 | 70 | return 0; 71 | } 72 | 73 | #undef LOCTEXT_NAMESPACE 74 | -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplateApp.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "StandaloneRenderer.h" 7 | 8 | /** 9 | * Run the UnrealSlateAppTemplate . 10 | */ 11 | int RunUnrealSlateAppTemplate(const TCHAR* Commandline); 12 | -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplateModule/Private/UnrealSlateAppTemplateModule.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "UnrealSlateAppTemplateModule/Public/UnrealSlateAppTemplateModule.h" 4 | #include "UnrealSlateAppTemplateModule/Public/UnrealSlateAppTemplateModuleStyle.h" 5 | #include "UnrealSlateAppTemplateModule/Public/UnrealSlateAppTemplateModuleCommands.h" 6 | 7 | #include "Widgets/Docking/SDockTab.h" 8 | #include "Widgets/Layout/SBox.h" 9 | #include "Widgets/Text/STextBlock.h" 10 | 11 | static const FName UnrealSlateAppTemplateModuleTabName("UnrealSlateAppTemplateModule"); 12 | 13 | #define LOCTEXT_NAMESPACE "FUnrealSlateAppTemplateModule" 14 | 15 | void FUnrealSlateAppTemplateModule::StartupModule() 16 | { 17 | // This code will execute after your module is loaded into memory; 18 | 19 | FUnrealSlateAppTemplateModuleStyle::Initialize(); 20 | FUnrealSlateAppTemplateModuleStyle::ReloadTextures(); 21 | 22 | FUnrealSlateAppTemplateModuleCommands::Register(); 23 | 24 | AppCommands = MakeShareable(new FUICommandList); 25 | 26 | AppCommands->MapAction( 27 | FUnrealSlateAppTemplateModuleCommands::Get().OpenMainWindow, 28 | FExecuteAction::CreateRaw(this, &FUnrealSlateAppTemplateModule::AppStarted), 29 | FCanExecuteAction()); 30 | 31 | FGlobalTabmanager::Get()->RegisterNomadTabSpawner(UnrealSlateAppTemplateModuleTabName, FOnSpawnTab::CreateRaw(this, &FUnrealSlateAppTemplateModule::OnSpawnMainTab)) 32 | .SetDisplayName(LOCTEXT("FUnrealSlateAppTemplateModuleTabTitle", "UnrealSlateAppTemplateModule")) 33 | .SetMenuType(ETabSpawnerMenuType::Hidden); 34 | } 35 | 36 | void FUnrealSlateAppTemplateModule::ShutdownModule() 37 | { 38 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 39 | // we call this function before unloading the module. 40 | 41 | FUnrealSlateAppTemplateModuleStyle::Shutdown(); 42 | 43 | FUnrealSlateAppTemplateModuleCommands::Unregister(); 44 | 45 | FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(UnrealSlateAppTemplateModuleTabName); 46 | } 47 | 48 | TSharedRef FUnrealSlateAppTemplateModule::OnSpawnMainTab(const FSpawnTabArgs& SpawnTabArgs) 49 | { 50 | FText WidgetText = FText::Format( 51 | LOCTEXT("WindowWidgetText", "Add code to {0} in {1} to override this window's contents"), 52 | FText::FromString(TEXT("FUnrealSlateAppTemplateModule::OnSpawnMainTab")), 53 | FText::FromString(TEXT("UnrealSlateAppTemplateModule.cpp")) 54 | ); 55 | 56 | return SNew(SDockTab) 57 | .TabRole(ETabRole::NomadTab) 58 | [ 59 | // Put your tab content here! 60 | SNew(SBox) 61 | .HAlign(HAlign_Center) 62 | .VAlign(VAlign_Center) 63 | [ 64 | SNew(STextBlock) 65 | .Text(WidgetText) 66 | ] 67 | ]; 68 | } 69 | 70 | void FUnrealSlateAppTemplateModule::AppStarted() 71 | { 72 | FGlobalTabmanager::Get()->TryInvokeTab(UnrealSlateAppTemplateModuleTabName); 73 | } 74 | 75 | #undef LOCTEXT_NAMESPACE 76 | 77 | IMPLEMENT_MODULE(FUnrealSlateAppTemplateModule, UnrealSlateAppTemplateModule) -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplateModule/Private/UnrealSlateAppTemplateModuleCommands.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "UnrealSlateAppTemplateModule/Public/UnrealSlateAppTemplateModuleCommands.h" 4 | 5 | #define LOCTEXT_NAMESPACE "FUnrealSlateAppTemplateModuleModule" 6 | 7 | void FUnrealSlateAppTemplateModuleCommands::RegisterCommands() 8 | { 9 | UI_COMMAND(OpenMainWindow, "UnrealSlateAppTemplateModule", "Bring up UnrealSlateAppTemplateModule window", EUserInterfaceActionType::Button, FInputChord()); 10 | } 11 | 12 | #undef LOCTEXT_NAMESPACE 13 | -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplateModule/Private/UnrealSlateAppTemplateModuleStyle.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "UnrealSlateAppTemplateModule/Public/UnrealSlateAppTemplateModuleStyle.h" 4 | #include "Styling/SlateStyleRegistry.h" 5 | #include "Framework/Application/SlateApplication.h" 6 | 7 | TSharedPtr< FSlateStyleSet > FUnrealSlateAppTemplateModuleStyle::StyleInstance = NULL; 8 | 9 | void FUnrealSlateAppTemplateModuleStyle::Initialize() 10 | { 11 | if (!StyleInstance.IsValid()) 12 | { 13 | StyleInstance = Create(); 14 | FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance); 15 | } 16 | } 17 | 18 | void FUnrealSlateAppTemplateModuleStyle::Shutdown() 19 | { 20 | FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance); 21 | ensure(StyleInstance.IsUnique()); 22 | StyleInstance.Reset(); 23 | } 24 | 25 | FName FUnrealSlateAppTemplateModuleStyle::GetStyleSetName() 26 | { 27 | static FName StyleSetName(TEXT("UnrealSlateAppTemplateModuleStyle")); 28 | return StyleSetName; 29 | } 30 | 31 | #define IMAGE_BRUSH( RelativePath, ... ) FSlateImageBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) 32 | #define BOX_BRUSH( RelativePath, ... ) FSlateBoxBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) 33 | #define BORDER_BRUSH( RelativePath, ... ) FSlateBorderBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) 34 | #define TTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".ttf") ), __VA_ARGS__ ) 35 | #define OTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".otf") ), __VA_ARGS__ ) 36 | 37 | const FVector2D Icon16x16(16.0f, 16.0f); 38 | const FVector2D Icon20x20(20.0f, 20.0f); 39 | const FVector2D Icon40x40(40.0f, 40.0f); 40 | 41 | TSharedRef< FSlateStyleSet > FUnrealSlateAppTemplateModuleStyle::Create() 42 | { 43 | TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("UnrealSlateAppTemplateModuleStyle")); 44 | 45 | // TODO: Configure styles to interact with the resources folder 46 | //Style->SetContentRoot(IPluginManager::Get().FindPlugin("UnrealSlateAppTemplateModule")->GetBaseDir() / TEXT("Resources")); 47 | //Style->Set("UnrealSlateAppTemplateModule.OpenMainWindow", new IMAGE_BRUSH(TEXT("ButtonIcon_40x"), Icon40x40)); 48 | 49 | return Style; 50 | } 51 | 52 | #undef IMAGE_BRUSH 53 | #undef BOX_BRUSH 54 | #undef BORDER_BRUSH 55 | #undef TTF_FONT 56 | #undef OTF_FONT 57 | 58 | void FUnrealSlateAppTemplateModuleStyle::ReloadTextures() 59 | { 60 | if (FSlateApplication::IsInitialized()) 61 | { 62 | FSlateApplication::Get().GetRenderer()->ReloadTextureResources(); 63 | } 64 | } 65 | 66 | const ISlateStyle& FUnrealSlateAppTemplateModuleStyle::Get() 67 | { 68 | return *StyleInstance; 69 | } 70 | -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplateModule/Public/UnrealSlateAppTemplateModule.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Modules/ModuleManager.h" 7 | 8 | class FToolBarBuilder; 9 | class FMenuBuilder; 10 | 11 | class FUnrealSlateAppTemplateModule : public IModuleInterface 12 | { 13 | public: 14 | 15 | /** IModuleInterface implementation */ 16 | virtual void StartupModule() override; 17 | virtual void ShutdownModule() override; 18 | 19 | /** This function will be bound to Command (by default it will bring up application window) */ 20 | void AppStarted(); 21 | 22 | private: 23 | 24 | TSharedRef OnSpawnMainTab(const class FSpawnTabArgs& SpawnTabArgs); 25 | 26 | private: 27 | TSharedPtr AppCommands; 28 | }; 29 | -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplateModule/Public/UnrealSlateAppTemplateModuleCommands.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Framework/Commands/Commands.h" 7 | #include "UnrealSlateAppTemplateModuleStyle.h" 8 | 9 | class FUnrealSlateAppTemplateModuleCommands : public TCommands 10 | { 11 | public: 12 | 13 | FUnrealSlateAppTemplateModuleCommands() 14 | : TCommands(TEXT("UnrealSlateAppTemplateModule"), NSLOCTEXT("Contexts", "UnrealSlateAppTemplateModule", "UnrealSlateAppTemplateModule application"), NAME_None, FUnrealSlateAppTemplateModuleStyle::GetStyleSetName()) 15 | { 16 | } 17 | 18 | // TCommands<> interface 19 | virtual void RegisterCommands() override; 20 | 21 | public: 22 | TSharedPtr< FUICommandInfo > OpenMainWindow; 23 | }; -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplateModule/Public/UnrealSlateAppTemplateModuleStyle.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Styling/SlateStyle.h" 7 | 8 | /** */ 9 | class FUnrealSlateAppTemplateModuleStyle 10 | { 11 | public: 12 | 13 | static void Initialize(); 14 | 15 | static void Shutdown(); 16 | 17 | /** reloads textures used by slate renderer */ 18 | static void ReloadTextures(); 19 | 20 | /** @return The Slate style set for the Shooter game */ 21 | static const ISlateStyle& Get(); 22 | 23 | static FName GetStyleSetName(); 24 | 25 | private: 26 | 27 | static TSharedRef< class FSlateStyleSet > Create(); 28 | 29 | private: 30 | 31 | static TSharedPtr< class FSlateStyleSet > StyleInstance; 32 | }; -------------------------------------------------------------------------------- /Source/UnrealSlateAppTemplateModule/UnrealSlateAppTemplateModule.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class UnrealSlateAppTemplateModule : ModuleRules 6 | { 7 | public UnrealSlateAppTemplateModule(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicIncludePaths.AddRange( 12 | new string[] { 13 | // ... add public include paths required here ... 14 | } 15 | ); 16 | 17 | 18 | PrivateIncludePaths.AddRange( 19 | new string[] { 20 | // ... add other private include paths required here ... 21 | } 22 | ); 23 | 24 | 25 | PublicDependencyModuleNames.AddRange( 26 | new string[] 27 | { 28 | "Core", 29 | // ... add other public dependencies that you statically link with here ... 30 | } 31 | ); 32 | 33 | 34 | PrivateDependencyModuleNames.AddRange( 35 | new string[] 36 | { 37 | "InputCore", 38 | "CoreUObject", 39 | "Slate", 40 | "SlateCore", 41 | // ... add private dependencies that you statically link with here ... 42 | } 43 | ); 44 | 45 | 46 | DynamicallyLoadedModuleNames.AddRange( 47 | new string[] 48 | { 49 | // ... add any modules that your module loads dynamically here ... 50 | } 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Tools/TemplateNamer/TemplateNamer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # TemplateNamer - script for generating a new Slate UI stand alone project based on a template 4 | 5 | import sys 6 | import getopt 7 | import os 8 | 9 | 10 | key_replacing_name = 'UnrealSlateAppTemplate' 11 | 12 | 13 | 14 | def is_valid_path(path): 15 | if not os.path.exists(path): 16 | return False, f'The specified path "{path}" does not exist.' 17 | return True, None 18 | 19 | 20 | def parse_args(argv): 21 | project_name = '' 22 | project_path = '' 23 | 24 | help_msg = 'Usage: \tTemplateNamer.py ' \ 25 | '[-n | --name=""] ' \ 26 | '[-p | --path=""] ' \ 27 | '[-h | --help]\n' 28 | 29 | try: 30 | opts, args = getopt.getopt(argv, "hn:p:i", ["name=", "path=", "interactive"]) 31 | except getopt.GetoptError: 32 | print('Bad option(s)\n') 33 | print(help_msg) 34 | sys.exit(3) 35 | 36 | if ('-i', '') in opts or ('--interactive', '') in opts: 37 | input_str = input('<< Please enter a NAME for the new project:\n>> ') 38 | # print(f'{input_str}\n') 39 | project_name = input_str 40 | 41 | input_str = input('<< Please enter the PATH for the new project:\n>> ') 42 | # print(f'{input_str}\n') 43 | is_valid, error = is_valid_path(input_str) 44 | if not is_valid: 45 | print(f'[ERROR] {error}\n') 46 | sys.exit(3) 47 | project_path = input_str 48 | return project_name, project_path 49 | 50 | for opt, arg in opts: 51 | if opt == '-h': 52 | print(help_msg) 53 | sys.exit() 54 | 55 | if opt == '-n' or opt == '--name': 56 | if arg.startswith('"') and arg.endswith('"'): 57 | arg = arg[1:-1] 58 | project_name = arg 59 | 60 | if opt == '-p' or opt == '--path': 61 | if arg.startswith('"') and arg.endswith('"'): 62 | arg = arg[1:-1] 63 | is_valid, error = is_valid_path(arg) 64 | if not is_valid: 65 | print(f'[ERROR] {error}\n') 66 | sys.exit(3) 67 | project_path = arg 68 | 69 | return project_name, project_path 70 | 71 | 72 | def get_dst_name_by_src_path(path, target_name): 73 | src_base_name = os.path.basename(path) 74 | if key_replacing_name in src_base_name: 75 | src_base_name = src_base_name.replace(key_replacing_name, target_name) 76 | return src_base_name 77 | 78 | 79 | def read_src_and_write_dst_file(path, target_path, target_name): 80 | dst_file_name = get_dst_name_by_src_path(path, target_name) 81 | dst_path = os.path.join(target_path, dst_file_name) 82 | 83 | try: 84 | with open(path, 'r') as src_file: 85 | with open(dst_path, 'w') as dst_file: 86 | src_content = src_file.read() 87 | dst_content = src_content.replace(key_replacing_name, target_name) 88 | dst_file.write(dst_content) 89 | except: 90 | print("F! Creation of the file %s failed" % dst_path) 91 | return False 92 | else: 93 | print("F+ Successfully created the file %s " % dst_path) 94 | return True 95 | 96 | 97 | def iterate_by_dir_content(dir_path, target_path, target_name): 98 | dst_dir_name = get_dst_name_by_src_path(dir_path, target_name) 99 | dst_path = os.path.join(target_path, dst_dir_name) 100 | if not os.path.exists(dst_path): 101 | try: 102 | os.mkdir(dst_path) 103 | except OSError: 104 | print("D! Creation of the directory %s failed" % dst_path) 105 | return False 106 | else: 107 | print("D+ Successfully created the directory %s " % dst_path) 108 | 109 | for item in os.listdir(dir_path): 110 | item_path = os.path.join(dir_path, item) 111 | if os.path.isdir(item_path): 112 | if not iterate_by_dir_content(item_path, dst_path, target_name): 113 | return False 114 | else: 115 | if not read_src_and_write_dst_file(item_path, dst_path, target_name): 116 | return False 117 | return True 118 | 119 | 120 | def create_empty_slate_project(name, path): 121 | target_root = os.path.join(path, name) 122 | try: 123 | os.mkdir(target_root) 124 | except OSError: 125 | print("D! Creation of the directory %s failed" % target_root) 126 | return False 127 | else: 128 | print("D+ Successfully created the directory %s " % target_root) 129 | 130 | # detect the current working directory and print it 131 | tool_path = os.getcwd() 132 | template_path = os.path.join(tool_path, "../../") 133 | 134 | is_success = iterate_by_dir_content(os.path.join(template_path, "Source"), target_root, name) 135 | is_success &= read_src_and_write_dst_file(os.path.join(template_path, f'{key_replacing_name}.uproject'), target_root, name) 136 | 137 | return is_success 138 | 139 | 140 | def main(argv): 141 | name, path = parse_args(argv) 142 | print(f'--- Creating "{name}" to "{path}"...') 143 | if create_empty_slate_project(name, path): 144 | print(f'--- Done! ---') 145 | else: 146 | print(f'--- Failed. ---') 147 | 148 | 149 | if __name__ == "__main__": 150 | main(sys.argv[1:]) 151 | -------------------------------------------------------------------------------- /UnrealSlateAppTemplate.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Category": "", 4 | "Description": "", 5 | "Modules": [ 6 | { 7 | "Name": "EmptyProject", 8 | "Type": "Runtime", 9 | "LoadingPhase": "Default" 10 | } 11 | ] 12 | } --------------------------------------------------------------------------------