diff --git a/Source/Private/RealExecutionMain.cpp b/Source/Private/RealExecutionMain.cpp index a2d095d..8a712f7 100644 --- a/Source/Private/RealExecutionMain.cpp +++ b/Source/Private/RealExecutionMain.cpp @@ -121,11 +121,12 @@ int RealExecutionMain(const TCHAR* pCmdLine) #include "SlateWidget/SConfigListPanel.h" - +#include "SlateWidget/SVersionUpdater/SVersionUpdaterWidget.h" namespace WindowManager { static TSharedPtr < SConfPanel > LauncherPanel; static TSharedPtr < SConfigListPanel > LauncherConfListPanel; + static TSharedPtr < SVersionUpdaterWidget > VersionUpdaterWidget; void OnConfigSelected(FLaunchConf Config) { if(LauncherPanel.IsValid()) @@ -154,20 +155,36 @@ namespace WindowManager .MinWidth(1200) .IsTopmostWindow(false) [ - SNew(SHorizontalBox) - +SHorizontalBox::Slot() - .FillWidth(0.3) + SNew(SVerticalBox) + + SVerticalBox::Slot() + .AutoHeight() [ - SNew(SBox) - [ - SAssignNew(LauncherConfListPanel,SConfigListPanel) - ] + SAssignNew(VersionUpdaterWidget,SVersionUpdaterWidget) + .ToolName(FText::FromString(TOOL_NAME)) + .DeveloperName(FText::FromString(TEXT("lipengzha"))) + .DeveloperWebsite(FText::FromString(TEXT("https://imzlp.com"))) + .UpdateWebsite(FText::FromString(TEXT("https://imzlp.com/posts/11750/"))) + .CurrentVersion(CURRENT_VERSION_ID) ] - +SHorizontalBox::Slot() - .FillWidth(0.7) + +SVerticalBox::Slot() + .FillHeight(1.0) [ - SAssignNew(LauncherPanel, SConfPanel) + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .FillWidth(0.3) + [ + SNew(SBox) + [ + SAssignNew(LauncherConfListPanel, SConfigListPanel) + ] + ] + + SHorizontalBox::Slot() + .FillWidth(0.7) + [ + SAssignNew(LauncherPanel, SConfPanel) + ] ] + //.OnOpenedFileEvent.BindStatic(&WindowManager::OnOpenFileChangeWindowTitle) ]; LauncherConfListPanel->OnConfigFileSelected.BindStatic(&WindowManager::OnConfigSelected); diff --git a/Source/Private/SlateWidget/SConfListPanel.cpp b/Source/Private/SlateWidget/SConfListPanel.cpp index df197d6..0da4b58 100644 --- a/Source/Private/SlateWidget/SConfListPanel.cpp +++ b/Source/Private/SlateWidget/SConfListPanel.cpp @@ -20,7 +20,6 @@ #include "Widgets/SCanvas.h" #include "Tools/SerializationTools.h" #include "Tools/EngineLaunchTools.h" - #define LOCTEXT_NAMESPACE "WidgetConfigListPanel" BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION @@ -157,14 +156,14 @@ void SConfigListPanel::Construct(const FArguments& InArgs) [ SNew(SOverlay) ] - +SHorizontalBox::Slot() - .AutoWidth() - .HAlign(HAlign_Center) - [ - SNew(SHyperlink) - .Text(LOCTEXT("LauncherVersion", LAUNCHER_VERSION)) - .OnNavigate(this, &SConfigListPanel::HyLinkClickEventOpenVersionWebsite) - ] + //+SHorizontalBox::Slot() + //.AutoWidth() + //.HAlign(HAlign_Center) + //[ + // SNew(SHyperlink) + // .Text(LOCTEXT("LauncherVersion", *UKismetStringLibrary::Conv_IntToString(CURRENT_VERSION_ID))) + // .OnNavigate(this, &SConfigListPanel::HyLinkClickEventOpenVersionWebsite) + //] ] +SVerticalBox::Slot() .AutoHeight() diff --git a/Source/Private/SlateWidget/SConfPanel.cpp b/Source/Private/SlateWidget/SConfPanel.cpp index 6c25ba0..3ec198e 100644 --- a/Source/Private/SlateWidget/SConfPanel.cpp +++ b/Source/Private/SlateWidget/SConfPanel.cpp @@ -91,14 +91,14 @@ void SConfPanel::Construct(const FArguments& InArgs) [ SNew(SOverlay) ] - +SHorizontalBox::Slot() - .AutoWidth() - .HAlign(HAlign_Center) - [ - SNew(SHyperlink) - .Text(LOCTEXT("Developer", "Developed by lipengzha")) - .OnNavigate(this, &SConfPanel::HyLinkClickEventOpenDeveloperWebsite) - ] + //+SHorizontalBox::Slot() + //.AutoWidth() + //.HAlign(HAlign_Center) + //[ + // SNew(SHyperlink) + // .Text(LOCTEXT("Developer", "Developed by lipengzha")) + // .OnNavigate(this, &SConfPanel::HyLinkClickEventOpenDeveloperWebsite) + //] ] ] +SVerticalBox::Slot() diff --git a/Source/Private/SlateWidget/SVersionUpdater/SVersionUpdaterWidget.cpp b/Source/Private/SlateWidget/SVersionUpdater/SVersionUpdaterWidget.cpp new file mode 100644 index 0000000..810bff5 --- /dev/null +++ b/Source/Private/SlateWidget/SVersionUpdater/SVersionUpdaterWidget.cpp @@ -0,0 +1,217 @@ +#include "SVersionUpdaterWidget.h" +// engine header +#include "Widgets/Input/SHyperlink.h" +#include "Widgets/Layout/SBorder.h" +#include "Widgets/Images/SImage.h" +#include "Widgets/Layout/SBox.h" +#include "Widgets/Layout/SScrollBox.h" +#include "Widgets/SBoxPanel.h" +#include "HttpModule.h" +#include "Misc/FileHelper.h" +#include "Json.h" +#include "VersionUpdaterStyle.h" +#include "Interfaces/IHttpRequest.h" +#include "Interfaces/IHttpResponse.h" + +#define LOCTEXT_NAMESPACE "VersionUpdaterWidget" + + +void SVersionUpdaterWidget::Construct(const FArguments& InArgs) +{ + static bool GBrushInited = false; + if(!GBrushInited) + { + FVersionUpdaterStyle::Initialize(); + FVersionUpdaterStyle::ReloadTextures(); + GBrushInited = true; + } + + SetToolUpdateInfo( + InArgs._ToolName.Get().ToString(), + InArgs._DeveloperName.Get().ToString(), + InArgs._DeveloperWebsite.Get().ToString(), + InArgs._UpdateWebsite.Get().ToString() + ); + CurrentVersion = InArgs._CurrentVersion.Get(); + + ChildSlot + [ + SNew(SBorder) + .Padding(2) + .ColorAndOpacity(FLinearColor{ 1.0,1.0,1.0,1.0 }) + //.BorderImage(FVersionUpdaterStyle::GetBrush("Updater.GroupBorder")) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .FillWidth(1.0f) + .VAlign(VAlign_Center) + .Padding(4.0f, 0.0f, 4.0f, 0.0f) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .AutoWidth() + .VAlign(VAlign_Center) + [ + SNew(SBox) + .WidthOverride(40) + .HeightOverride(40) + [ + SNew(SImage) + .Image(FVersionUpdaterStyle::GetBrush("Updater.QuickLaunch")) + ] + ] + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(10,0,10,0) + .VAlign(VAlign_Center) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .AutoHeight() + .Padding(2, 4, 2, 4) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .AutoWidth() + [ + SNew(SHyperlink) + .Text_Raw(this,&SVersionUpdaterWidget::GetToolName) + .OnNavigate(this, &SVersionUpdaterWidget::HyLinkClickEventOpenUpdateWebsite) + ] + + SHorizontalBox::Slot() + .FillWidth(1.0) + [ + SNew(SOverlay) + ] + ] + + SVerticalBox::Slot() + .AutoHeight() + .Padding(2, 4, 2, 4) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(0,0,4,0) + [ + SNew(STextBlock) + .Text_Raw(this,&SVersionUpdaterWidget::GetCurrentVersionText) + ] + + SHorizontalBox::Slot() + .AutoWidth() + [ + SAssignNew(UpdateInfoWidget,SHorizontalBox) + .Visibility(EVisibility::Collapsed) + + SHorizontalBox::Slot() + .AutoWidth() + [ + SNew(SBox) + .WidthOverride(18) + .HeightOverride(18) + [ + SNew(SImage) + .Image(FVersionUpdaterStyle::GetBrush("Updater.SpawnableIconOverlay")) + ] + ] + + SHorizontalBox::Slot() + .Padding(2,0,0,0) + .AutoWidth() + [ + SNew(SHyperlink) + .Text_Raw(this,&SVersionUpdaterWidget::GetLatstVersionText) + .OnNavigate(this, &SVersionUpdaterWidget::HyLinkClickEventOpenUpdateWebsite) + ] + ] + ] + ] + ] + + SHorizontalBox::Slot() + .FillWidth(1.0f) + .VAlign(VAlign_Center) + [ + SNew(SOverlay) + ] + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(10,0,10,0) + .VAlign(VAlign_Center) + [ + SNew(SHyperlink) + .Text_Raw(this,&SVersionUpdaterWidget::GetDeveloperDescrible) + .OnNavigate(this, &SVersionUpdaterWidget::HyLinkClickEventOpenDeveloperWebsite) + ] + ] + ]; + RequestVersion(REMOTE_VERSION_FILE); +} + +void SVersionUpdaterWidget::HyLinkClickEventOpenUpdateWebsite() +{ + FPlatformProcess::LaunchURL(*UpdateWebsite, NULL, NULL); +} + +void SVersionUpdaterWidget::HyLinkClickEventOpenDeveloperWebsite() +{ + FPlatformProcess::LaunchURL(*DeveloperWebsite, NULL, NULL); +} + +void SVersionUpdaterWidget::SetToolUpdateInfo(const FString& InToolName, const FString& InDeveloperName, + const FString& InDeveloperWebsite, const FString& InUpdateWebsite) +{ + ToolName = InToolName; + DeveloperName = InDeveloperName; + DeveloperWebsite = InDeveloperWebsite; + UpdateWebsite = InUpdateWebsite; +} + +DEFINE_LOG_CATEGORY_STATIC(LogVersionUpdater,All,All); + +void SVersionUpdaterWidget::OnRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bConnectedSuccessfully) +{ + FString Result = ResponsePtr->GetContentAsString();; + // UE_LOG(LogVersionUpdater, Log, TEXT("%s"),*Result); + TSharedRef> JsonReader = TJsonReaderFactory::Create(Result); + TSharedPtr JsonObject; + if (FJsonSerializer::Deserialize(JsonReader, JsonObject)) + { + TArray ToolNames; + if(JsonObject->TryGetStringArrayField(TEXT("Tools"),ToolNames)) + { + if(ToolNames.Contains(GetToolName().ToString())) + { + const TSharedPtr* ToolJsonObject; + if(JsonObject->TryGetObjectField(GetToolName().ToString(),ToolJsonObject)) + { + int32 Version = ToolJsonObject->Get()->GetIntegerField(TEXT("Version")); + FString Developer = ToolJsonObject->Get()->GetStringField(TEXT("Author")); + FString UpdateURL = ToolJsonObject->Get()->GetStringField(TEXT("URL")); + FString Website = ToolJsonObject->Get()->GetStringField(TEXT("Website")); + SetToolUpdateInfo(GetToolName().ToString(),Developer,Website,UpdateURL); + LatstVersion = Version; + if(CurrentVersion < LatstVersion) + { + UpdateInfoWidget->SetVisibility(EVisibility::Visible); + } + } + } + } + } +} + +void SVersionUpdaterWidget::RequestVersion(const FString& URL) +{ + if(HttpHeadRequest.IsValid()) + { + HttpHeadRequest->CancelRequest(); + HttpHeadRequest.Reset(); + } + HttpHeadRequest = FHttpModule::Get().CreateRequest(); + HttpHeadRequest->SetURL(URL); + HttpHeadRequest->SetVerb(TEXT("GET")); + HttpHeadRequest->OnProcessRequestComplete().BindRaw(this,&SVersionUpdaterWidget::OnRequestComplete); + if (HttpHeadRequest->ProcessRequest()) + { + UE_LOG(LogVersionUpdater, Log, TEXT("Request %s Version."),*GetToolName().ToString()); + } +} + +#undef LOCTEXT_NAMESPACE diff --git a/Source/Private/SlateWidget/SVersionUpdater/SVersionUpdaterWidget.h b/Source/Private/SlateWidget/SVersionUpdater/SVersionUpdaterWidget.h new file mode 100644 index 0000000..f468e83 --- /dev/null +++ b/Source/Private/SlateWidget/SVersionUpdater/SVersionUpdaterWidget.h @@ -0,0 +1,62 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Input/Reply.h" +#include "Interfaces/IHttpRequest.h" +#include "Widgets/SCompoundWidget.h" + +// #define CURRENT_VERSION_ID 68 +// #define REMOTE_VERSION_FILE TEXT("https://imzlp.com/opensource/version.json") + +class SVersionUpdaterWidget : public SCompoundWidget +{ + +public: + SLATE_BEGIN_ARGS(SVersionUpdaterWidget): + _CurrentVersion(), + _ToolName(), + _DeveloperName(), + _DeveloperWebsite(), + _UpdateWebsite() + {} + SLATE_ATTRIBUTE( int32, CurrentVersion ) + SLATE_ATTRIBUTE( FText, ToolName ) + SLATE_ATTRIBUTE( FText, DeveloperName ) + SLATE_ATTRIBUTE( FText, DeveloperWebsite ) + SLATE_ATTRIBUTE( FText, UpdateWebsite ) + SLATE_END_ARGS() + +public: + /** + * Construct the widget + * + * @param InArgs A declaration from which to construct the widget + */ + void Construct(const FArguments& InArgs); + void HyLinkClickEventOpenUpdateWebsite(); + void HyLinkClickEventOpenDeveloperWebsite(); + + FText GetCurrentVersionText() const {return FText::FromString(FString::Printf(TEXT("Current Version v%d."),GetCurrentVersion()));}; + FText GetToolName() const {return FText::FromString(ToolName);}; + FText GetDeveloperName() const {return FText::FromString(DeveloperName);}; + FText GetUpdateWebsite() const {return FText::FromString(UpdateWebsite);}; + FText GetDeveloperWebsite() const {return FText::FromString(DeveloperWebsite);}; + FText GetDeveloperDescrible() const {return FText::FromString(FString::Printf(TEXT("Developed by %s"),*GetDeveloperName().ToString()));}; + FText GetLatstVersionText() const {return FText::FromString(FString::Printf(TEXT("A new version v%d is avaliable"),LatstVersion));}; + virtual void SetToolUpdateInfo(const FString& ToolName,const FString& DeveloperName,const FString& DeveloperWebsite,const FString& UpdateWebsite); + int32 GetCurrentVersion()const { return CurrentVersion; } + + void OnRequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bConnectedSuccessfully); + void RequestVersion(const FString& URL); +private: + int32 CurrentVersion = 0; + FString ToolName; + FString UpdateWebsite; + FString DeveloperWebsite; + FString DeveloperName; + TSharedPtr UpdateInfoWidget; + int32 LatstVersion = 0; + FHttpRequestPtr HttpHeadRequest; +}; + diff --git a/Source/Private/SlateWidget/SVersionUpdater/VersionUpdaterStyle.cpp b/Source/Private/SlateWidget/SVersionUpdater/VersionUpdaterStyle.cpp new file mode 100644 index 0000000..9616130 --- /dev/null +++ b/Source/Private/SlateWidget/SVersionUpdater/VersionUpdaterStyle.cpp @@ -0,0 +1,79 @@ +// Copyright 2019 Lipeng Zha, Inc. All Rights Reserved. + +#include "VersionUpdaterStyle.h" +#include "Framework/Application/SlateApplication.h" +#include "Styling/SlateStyleRegistry.h" +#include "Interfaces/IPluginManager.h" + +TSharedPtr< FSlateStyleSet > FVersionUpdaterStyle::StyleInstance = NULL; + +void FVersionUpdaterStyle::Initialize() +{ + if (!StyleInstance.IsValid()) + { + StyleInstance = Create(); + FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance); + } +} + +void FVersionUpdaterStyle::Shutdown() +{ + FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance); + ensure(StyleInstance.IsUnique()); + StyleInstance.Reset(); +} + +FName FVersionUpdaterStyle::GetStyleSetName() +{ + static FName StyleSetName(TEXT("VersionUpdaterStyle")); + return StyleSetName; +} + +#define IMAGE_BRUSH( RelativePath, ... ) FSlateImageBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) +#define BOX_BRUSH( RelativePath, ... ) FSlateBoxBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) +#define BORDER_BRUSH( RelativePath, ... ) FSlateBorderBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) +#define TTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".ttf") ), __VA_ARGS__ ) +#define OTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".otf") ), __VA_ARGS__ ) + +const FVector2D Updater_Icon12x12(12.0f, 12.0f); +const FVector2D Updater_Icon16x16(16.0f, 16.0f); +const FVector2D Updater_Icon20x20(20.0f, 20.0f); +const FVector2D Updater_Icon40x40(40.0f, 40.0f); + +TSharedRef< FSlateStyleSet > FVersionUpdaterStyle::Create() +{ + TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("VersionUpdaterStyle")); + Style->SetContentRoot( FPaths::EngineContentDir() / TEXT("Editor/Slate") ); + Style->SetCoreContentRoot(FPaths::EngineContentDir() / TEXT("Slate")); + + Style->Set("Updater.GroupBorder", new BOX_BRUSH("Common/GroupBorder", FMargin(4.0f/16.0f))); + Style->Set("Updater.QuickLaunch", new IMAGE_BRUSH("Launcher/Launcher_Launch", Updater_Icon40x40)); + Style->Set("Updater.Star", new IMAGE_BRUSH("Sequencer/Star", Updater_Icon12x12)); + Style->Set("Updater.SpawnableIconOverlay", new IMAGE_BRUSH(TEXT("Sequencer/SpawnableIconOverlay"), FVector2D(13, 13))); + + return Style; +} + +const FSlateBrush* FVersionUpdaterStyle::GetBrush( FName PropertyName, const ANSICHAR* Specifier) +{ + return FVersionUpdaterStyle::StyleInstance->GetBrush( PropertyName, Specifier ); +} + +#undef IMAGE_BRUSH +#undef BOX_BRUSH +#undef BORDER_BRUSH +#undef TTF_FONT +#undef OTF_FONT + +void FVersionUpdaterStyle::ReloadTextures() +{ + if (FSlateApplication::IsInitialized()) + { + FSlateApplication::Get().GetRenderer()->ReloadTextureResources(); + } +} + +const ISlateStyle& FVersionUpdaterStyle::Get() +{ + return *StyleInstance; +} diff --git a/Source/Private/SlateWidget/SVersionUpdater/VersionUpdaterStyle.h b/Source/Private/SlateWidget/SVersionUpdater/VersionUpdaterStyle.h new file mode 100644 index 0000000..047872d --- /dev/null +++ b/Source/Private/SlateWidget/SVersionUpdater/VersionUpdaterStyle.h @@ -0,0 +1,32 @@ +// Copyright 2019 Lipeng Zha, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Styling/SlateStyle.h" + +class FVersionUpdaterStyle +{ +public: + + static void Initialize(); + + static void Shutdown(); + + /** reloads textures used by slate renderer */ + static void ReloadTextures(); + + /** @return The Slate style set for the Shooter game */ + static const ISlateStyle& Get(); + + static FName GetStyleSetName(); + + static const FSlateBrush* GetBrush( FName PropertyName, const ANSICHAR* Specifier = NULL ); +private: + + static TSharedRef< class FSlateStyleSet > Create(); + +private: + + static TSharedPtr< class FSlateStyleSet > StyleInstance; +}; \ No newline at end of file diff --git a/UE4Launcher.Build.cs b/UE4Launcher.Build.cs index 22d0af2..2d6480c 100644 --- a/UE4Launcher.Build.cs +++ b/UE4Launcher.Build.cs @@ -1,56 +1,62 @@ - -// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. - -using UnrealBuildTool; -using System.IO; - -public class UE4Launcher : ModuleRules -{ - public UE4Launcher(ReadOnlyTargetRules Target) : base(Target) - { - PublicIncludePaths.AddRange( - new string[] - { - "Runtime/Launch/Public", - "Programs/UE4Launcher/Source/Public", - "Runtime/Core/Public/Containers", - "Runtime/Core/Public/Misc" - }); - PrivateIncludePaths.AddRange( - new string[] - { - "Runtime/Launch/Private", // For LaunchEngineLoop.cpp include - "Programs/UE4Launcher/Source/Private" - }); - - PrivateDependencyModuleNames.AddRange( - new string[] { - "AppFramework", - "Core", - "ApplicationCore", - "Projects", - "DesktopPlatform", - "Slate", - "SlateCore", - "InputCore", - "SlateReflector", - "StandaloneRenderer", - "WebBrowser", - "SourceCodeAccess", - "OpenGL" - } - ); - PrivateIncludePathModuleNames.AddRange( - new string[] { - "SlateReflector", - } - ); - PublicIncludePathModuleNames.AddRange( - new string[] { - "SlateReflector", - } - ); - PublicDefinitions.Add("LAUNCHER_VERSION=\"v0.22\""); - } -} - + +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.IO; + +public class UE4Launcher : ModuleRules +{ + public UE4Launcher(ReadOnlyTargetRules Target) : base(Target) + { + PublicIncludePaths.AddRange( + new string[] + { + "Runtime/Launch/Public", + "Programs/UE4Launcher/Source/Public", + "Runtime/Core/Public/Containers", + "Runtime/Core/Public/Misc" + }); + PrivateIncludePaths.AddRange( + new string[] + { + "Runtime/Launch/Private", // For LaunchEngineLoop.cpp include + "Programs/UE4Launcher/Source/Private" + }); + + PrivateDependencyModuleNames.AddRange( + new string[] { + "AppFramework", + "Core", + "ApplicationCore", + "Projects", + "DesktopPlatform", + "Slate", + "SlateCore", + "InputCore", + "SlateReflector", + "StandaloneRenderer", + "WebBrowser", + "SourceCodeAccess", + "OpenGL", + "HTTP" + } + ); + PrivateIncludePathModuleNames.AddRange( + new string[] { + "SlateReflector", + } + ); + PublicIncludePathModuleNames.AddRange( + new string[] { + "SlateReflector", + } + ); + PublicDefinitions.AddRange(new string[] + { + "TOOL_NAME=\"UELauncher\"", + "CURRENT_VERSION_ID=23", + "REMOTE_VERSION_FILE=\"https://imzlp.com/opensource/version.json\"" + }); + } +} +