You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 2967465 on 2016/05/05 by Marc.Audy Fix VS2015 shadow variables fixes Change 2970637 on 2016/05/09 by Martin.Wilson Fix incorrect conflict resolve in merge from main Change 2976393 on 2016/05/12 by Zak.Middleton #ue4 - Set AudioComponent bUseAttachParentBounds=true to reduce cost of transform updates (avoids virtual CalcBounds() when transform changes). #tests PIE w/ audio Change 2976770 on 2016/05/13 by Lina.Halper Improvement on mirroring fix branch #code review: Zak.Middleton Change 2976774 on 2016/05/13 by Lukasz.Furman fixed missing memory callbacks for instanced behavior tree nodes #jira UE-30305 Change 2976775 on 2016/05/13 by Lukasz.Furman fixed multiple calls to behavior tree's instance cleanup #jira UE-30593 Change 2976801 on 2016/05/13 by Jon.Nabozny Add an optional argument FSkeletalMeshMerge. When set to EMeshBufferAccess::ForceCPUAndGPU, keeps a reference to the vertex buffer on CPU (e.g. for spawning particle effects). #JIRA UE-30405 Change 2976985 on 2016/05/13 by Jon.Nabozny Fix initializer list ordering for FSkeletalMeshMerge. Change 2977532 on 2016/05/13 by Marc.Audy PR #2348: [Local Multiplayer] Gamepad player assignment improvements (Contributed by kukiric) #jira UE-30162 Change 2977637 on 2016/05/13 by Marc.Audy Add Get/Set controller ID for a player in gameplay statics #jira UE-28718 Change 2979387 on 2016/05/16 by Jon.Nabozny Initialize FBox used to store results for CalculateQuatACF96Bounds. #JIRA UE-30846 Change 2979968 on 2016/05/17 by bruce.nesbit Added comment in FCanvasLineItem to warn only SE_BLEND_Opaque will be used when rendering. Change 2979969 on 2016/05/17 by bruce.nesbit Added comment in AddLine/AddPoint to warn only SE_BLEND_Opaque will be used when rendering. Change 2980271 on 2016/05/17 by Lina.Halper Improved comment #code review: Benn.Gallagher Change 2980317 on 2016/05/17 by Lukasz.Furman removing NavCollision from static mesh on property change and PostLoad if static mesh is not supposed to have one #ue4 Change 2980717 on 2016/05/17 by Zak.Middleton #ue4 - Optimize UCapsuleComponent::CalcBounds() to remove sqrt and use tighter bounding sphere radius. Change 2981193 on 2016/05/17 by Lukasz.Furman fixed missing observers in behavior tree when dynamic subtree is changed while waiting for full restart (out of nodes) #ue4 Change 2981927 on 2016/05/18 by Lina.Halper - Remove vertex animation code - Removing UVertexAnimation - Fixed reinitialization issue that was triggered by SetVertexAnimation - todo: consolidate UMorphtarget and UVertexAnimBase #code review: James.Golding, Martin.Wilson Change 2981957 on 2016/05/18 by Lina.Halper Add recursive stack check on update animation #code review: Martin.Wilson Change 2982116 on 2016/05/18 by Benn.Gallagher Removed optimize macros accidentally left after bounds extension feature for skel meshes Change 2982255 on 2016/05/18 by Jon.Nabozny FSkeletalMeshMerge constructor "MeshBufferAccess" default should be EMeshBufferAccess:Default instead of EMeshBufferAccess::ForceCPUAndGPU. Change2982607on 2016/05/18 by Marc.Audy Cleanup places calling GetWorld() multiple times Change 2982621 on 2016/05/18 by Marc.Audy Make UActorComponent::GetWorld final and inlined to avoid unnecessary function calls Put uncached logic in to a separate function Change 2983424 on 2016/05/19 by Marc.Audy Minor tweaks to reduce GetWorld calls Change 2983465 on 2016/05/19 by Lina.Halper Combine VertexAnimBase and MorphTarget to just MorphTarget - VertexAnimBase is gone - Modified most of VertexAnim to MorphTarget - Removed state, time related data #code review: James.Golding, Rolando.Caloca Change 2983609 on 2016/05/19 by Marc.Audy Inline AActor::GetLevel Half GetWorld() calls from AActor::GetNetMode() Change 2983772 on 2016/05/19 by Marc.Audy Fix Mac compile Change 2983931 on 2016/05/19 by Marc.Audy Remove pointless AccelMouse function Change 2984061 on 2016/05/19 by Marc.Audy Reorg some headers to fix compilation issues Change 2984409 on 2016/05/19 by Aaron.McLeran #jira UE-31049 Updating the Oculus Audio SDK to vs 1.02 Implementing 2984316 from Releases/4.12 to Dev-Framework Change 2984574 on 2016/05/19 by Aaron.McLeran Fix for platform headroom scalar. Using correct dB to linear formula (not one for power) dB = 20 * log(Linear), not dB = 10 * log(Linear) Change 2985041 on 2016/05/20 by Jon.Nabozny ConvertQueryOverlap only returns the base actor if multiple actors have bSimulatePhysics enabled and are welded together. #JIRA UE-30484 Change 2985118 on 2016/05/20 by Marc.Audy Another attempt to convince Mac to build Change 2985192 on 2016/05/20 by Marc.Audy Properly forward declare ABrush Change 2985724 on 2016/05/20 by Zak.Middleton #ue4 - Optimize NaN and Infinite checks for FVector, FQuat, FRotator, FMatrix, FTransform. SIMD version VectorContainsNaNOrInfinite() also optimized on relevant platforms. Added startup tests for VectorContainsNaNOrInfinite(). - All our "ContainsNaN()" tests are in fact "IsNaN() || IsInfinite()", which is the same as "!IsFinite()", so exploited this to simplify the tests. Both NaN and +/-Inf are not finite (http://en.cppreference.com/w/cpp/numeric/math/isfinite). In the future we should rename ContainsNaN(). - Still need to audit some uses in shipping configs. #jira UE-30999 Change 2986016 on 2016/05/20 by Zak.Middleton #ue4 - Fix uint32 used for int32 values. Behavior was unaffected. Change 2986017 on 2016/05/20 by Zak.Middleton #ue4 - Fix overlaps being dropped from within a FScopedMoveUpdate when rotation occurs. Remove invalid assert. Change 2986833 on 2016/05/23 by Zak.Middleton #ue4 - Move ETeleportType from ActorComponent.h to EngineTypes.h. Add comment to FHitResult for ImpactPoint when it's penetrating. Change 2986916 on 2016/05/23 by Rolando.Caloca DF - GPU morph targets proof of concept - Disabled by default - Not compatible with gpu skin cache - No extra memory required yet until it's used; creates buffers per frame (very slow!) Change 2987539 on 2016/05/23 by Rolando.Caloca DF - Remove unused member and downgrade FActiveMorphTarget to not be a USTRUCT Change 2987981 on 2016/05/24 by James.Golding PR #2162 : Exported AAudioVolume so that projects can derive custom classes. https://github.com/EpicGames/UnrealEngine/pull/2162 #github 2162 #jira UE-28533 Change 2987982 on 2016/05/24 by James.Golding PR #2318 : Fix memory allocation in CustomMeshComponent.cpp https://github.com/EpicGames/UnrealEngine/pull/2318 #github 2318 #jira UE-29864 Change 2987983 on 2016/05/24 by James.Golding Merging engine changes back from GDC demo: - Export FFIRFilterTimeBased from Engine module - Add FFIRFilterTimeBased::SetWindowDuration - Add FBaseCompactPose::CopyBonesTo Change 2987984 on 2016/05/24 by James.Golding UE-30137 No longer include collision in StatiMeshComponent bounds (bounds no longer user for any collision calculation) Change 2987985 on 2016/05/24 by James.Golding UE-27801 Export ConvertToCollisionChannel, ConvertToObjectType, and ConvertToTraceType members of UCollisionProfile Change 2987987 on 2016/05/24 by James.Golding OR-17910 : Support 'show collision' in Test configuration Change 2988123 on 2016/05/24 by Jon.Nabozny Prevent FBodyInstance::Weld causing duplicate PhsyXShapes to be created / added to ShapeToBodiesMap when toggling SimulatePhysics on PrimitiveComponent. #JIRA UE-31189 Change 2988449 on 2016/05/24 by Rolando.Caloca DF - Split FActiveMorphTarget's weight into its own array in prep for GPU friendly data Change 2988485 on 2016/05/24 by Jon.Nabozny Swap order of setRigidBodyFlag and setRigidDynamicFlag inside UpdateInstanceSimulatePhysics to prevent PhysX error about Kinematic bodies not using CCD. #JIRA UE-30993 Change2988969on 2016/05/24 by Rolando.Caloca DF - GPU morph targets - Enable using r.MorphTarget.Mode 1 Change 2989645 on 2016/05/25 by Marc.Audy Apply CL# 2989481 to Dev-Framework #jira UE-31055 Change 2989987 on 2016/05/25 by Wes.Hunt Redo of CL#2982707 2982716 2982723 2983780 2983864 from //Orion/Dev-General in preparation for continuing Analytics refactor in a Dev branch. AnalyticsET support for arbitrary Json events. * AnalyticsET supports a new API, RecordEventJson. * API supports rvalue refs to avoid unnecessary copies of the attribute array. #AUTOMERGE using branch Orion-Dev-General-To-UE4-Dev-Framework of change#2982707 by Wes.Hunt on 2016/05/18 17:22:20. Remove Analytics code to divert legacy code to source data collector. #AUTOMERGE using branch Orion-Dev-General-To-UE4-Dev-Framework of change#2982716 by Wes.Hunt on 2016/05/18 17:27:25. Analytics no longer adds IsEditor attribute to all events. Wasn't actually used by anyone anymore. #AUTOMERGE using branch Orion-Dev-General-To-UE4-Dev-Framework of change#2982723 by Wes.Hunt on 2016/05/18 17:29:40. Modernize FAnalyticsEventAttribute usage. Replaced FAnalyticsEventAttribute various ctors with a perfect forwarding one that can convert them to strings. * The Name must be convertible to a string * The value must be convertible to a string via an AnalyticsConversion::ToString() overload. * Added/expanded the supported conversions to strings to analytics attribute values. See AnalyticsConversion.h which contains all the previously supported conversions and more. Added MakeAnalyticsEventAttributeArray(), which uses variadic templates to create an array of event attributes inline, which can be passed to RecordEvent[Json] and efficiently taken ownership of: RecordEvent("EventName", MakeAnalyticsEventAttributeArray( "Attr1", false, "Attr2", 42.0, "Attr3", SomeMap, "Attr4", SomeArray); #AUTOMERGE using branch Orion-Dev-General-To-UE4-Dev-Framework of change#2983780 by Wes.Hunt on 2016/05/19 13:51:48. Added missing assignment copy/move ops to FAnalyticsEventAttribute. Doh, should have looked at more usages of PLATFORM_COMPILER_HAS_DEFAULTED_FUNCTIONS... #AUTOMERGE using branch Orion-Dev-General-To-UE4-Dev-Framework of change#2983864 by Wes.Hunt on 2016/05/19 14:17:05. Change 2989988 on 2016/05/25 by Wes.Hunt Fix usage of FAnalyticsEventAttribute constructor using a bitfield that was invalidated by the change to make FAnalyticsEventAttribute use a perfect forwarding constructor. bitfields cannot be perfect-forwarded... :( Change 2990493 on 2016/05/25 by Joe.Graf Added tooltips to the collision analyzer's buttons #CodeReview: james.golding Change 2991064 on 2016/05/26 by James.Golding - Remove many Animation headers from Engine.h - Remove AnimationAsset.h from SkeletalMeshComponent.h, Character.h, CharacterMovementComponent.h Change 2991113 on 2016/05/26 by Benn.Gallagher Fixed edge case in random sequence player where we might trigger an extra loop when waiting on a blend to finish. And made it impossible for a shuffle list to start with the animation that is currently playing (seemingly duplicating the anim). Change 2991163 on 2016/05/26 by Rolando.Caloca DF - Rename and refactor some morph target compute shader in prep for interop with skin cache Change2991167on 2016/05/26 by Jon.Nabozny Add `#include "DataTable.h"` to GameplayTagsManager.h. FGameplayTagTableRow is derived from FTableRowBase which isn't necessarily included. This issue is hidden in most cases as "Engine.h" includes "DataTable.h". Change 2991183 on 2016/05/26 by Wes.Hunt Disable general forwarding constructor for AnalyticsEventAttribute for non arithmetic types, so they are free to choose other overloads more appropriately. Change2991199on 2016/05/26 by Wes.Hunt Drastically reducing the headers dependencies on analytics headers. Analytics headers no longer appear in PCH files, and rarely if ever appear in a header file. IAnalyticsProviderModule.h only touches 8 source files. Analytics.h only touches 8 source files. IAnalyticsProvider.h only touches 5 headers and 97 source files. AnalyticsET.h only touches 12 source files. Change 2991301 on 2016/05/26 by James.Golding Fix CIS for Fortnite Change 2991319 on 2016/05/26 by James.Golding Fix CIS for Orion Change 2991373 on 2016/05/26 by Joe.Graf Tweaked the tooltip text for the collision analyzer record button to be correct for both states Added a common button style so that the buttons have a consistent look #CodeReview: james.golding Change 2991401 on 2016/05/26 by James.Golding Fix UT CIS Change 2991406 on 2016/05/26 by James.Golding Fix Ocean CIS Change 2991491 on 2016/05/26 by Lina.Halper Moved MorphTarget.h - Checked in modified functions fo AnimationRuntime for other features coming up - Should not change any behavior of existing content #code review: James.Golding, Rolando.Caloca Change 2991494 on 2016/05/26 by Wes.Hunt Fix for Unity error in AnalyticsET module after hedaer dependency reduction Change 2991503 on 2016/05/26 by Jon.Nabozny Fix issue where FConstraintInstance (inside UPhysicsConstraintComponent) is not editable in InstanceEditor but is editable in BlueprintEditor. #JIRA UE-31267 Change 2991562 on 2016/05/26 by Zak.Middleton #ue4 - Reduce allocations during movement and overlap queries and when grabbing shapes from physx actors. Change 2991586 on 2016/05/26 by James.Golding More CIS fixes for Orion and Fortnite Change 2991673 on 2016/05/26 by Wes.Hunt Another non-unity fix for Analytics include dependency reduction. Change 2991733 on 2016/05/26 by Zak.Middleton #dev - Test map, 50 walking dudes. Change 2991781 on 2016/05/26 by Lina.Halper Back out revision 15 from //UE4/Dev-Framework/Engine/Source/Runtime/Engine/Private/Animation/AnimationRuntime.cpp - Back out a part of changes that I didn't mean to check in. Change 2991922 on 2016/05/26 by Zak.Middleton #ue4 - Maybe fix Mac build. Change 2991957 on 2016/05/26 by Joe.Graf Fixed the collision analyzer file open text (said project instead of collision) Change 2991991 on 2016/05/26 by Lina.Halper Fix compile error Change 2992089 on 2016/05/26 by Zak.Middleton #ue4 - Fix Mac/PS4 build. Change 2992108 on 2016/05/26 by Wes.Hunt Yet another non-unity fix for Analytics header inclusion reduction. Change 2992190 on 2016/05/26 by Zak.Middleton #ue4 - Mark FHitResult, FOverlapResult, FOverlapInfo as POD types. Avoids destructors etc when in TArrays. Change 2992593 on 2016/05/27 by Martin.Wilson Build fixes for non editor platforms Change 2992885 on 2016/05/27 by Rolando.Caloca DF - Fix crash on thumbnails #jira UE-31398 Change 2993058 on 2016/05/27 by Lukasz.Furman fixed behavior tree getting stuck on ResumeLogic call #jira OR-22498 Change 2993064 on 2016/05/27 by Zak.Middleton #ue4 - Fix root motion network corrections not clearing root motion data. udn: https://udn.unrealengine.com/questions/294985/jittering-in-character-movement-during-networked-m.html #jira UE-31316 Change2993215on 2016/05/27 by Lukasz.Furman gameplay debugger fixes: navmesh rendering is not hidden after disabling tool, player stuck in spectator mode after disabling tool, confusing version description for categories without data packs added replicated input bindings for debugger's categories #ue4 Change 2993521 on 2016/05/27 by Zak.Middleton #ue4 - Reduce allocations in UI Canvas items. Change 2993995 on 2016/05/30 by Mieszko.Zielinski Temporary fix for BBKeySelector not handling properly multiple UObject subtypes #UE4 #jira UE-31435 Change 2993998 on 2016/05/30 by Mieszko.Zielinski Improves handling of a special case in EQS score normalization, where all items have the same score #UE4 We used to set the normalized score of 1 for all items, which was counter intuitive if all items have scored 0 in an unnormalized test. The improve handling detects that and assigns score of 0 in that case. Change 2993999 on 2016/05/30 by Mieszko.Zielinski Fixed FEQSParametrizedQueryExecutionRequest converting non-BB values into EQS params wrong #UE4 Change 2994000 on 2016/05/30 by Mieszko.Zielinski Exposed UNavigationInvokerComponent as part of ENGINE_API so that it can be spawned procedurally in C++ in game specific code #UE4 Change 2994003 on 2016/05/30 by Mieszko.Zielinski Fixed naming of console variable controllin v-logging of FGameplayAttribute #UE4 The old name was copy-pasted from somewhere. Change 2994007 on 2016/05/30 by Mieszko.Zielinski Fixed unregistering listeners from perception system not clearing up all data #UE4 Also, introduced two precisely named functions, GetCurrentlyPerceivedActors and GetKnownPerceivedActors to replace ambiguous GetPerceivedActors Also, renamed UAIPerceptionComponent::TActorPerceptionContainer to UAIPerceptionComponent::FActorPerceptionContainer Change 2994475 on 2016/05/31 by Wes.Hunt Fix Unity build failure for analytics inclusion reduction for IOSFlurry. [CL 2994701 by Marc Audy in Main branch]
890 lines
30 KiB
C++
890 lines
30 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "MainFramePrivatePCH.h"
|
|
#include "CompilerResultsLog.h"
|
|
#include "Editor/EditorLiveStreaming/Public/IEditorLiveStreaming.h"
|
|
#include "Developer/HotReload/Public/IHotReload.h"
|
|
#include "NotificationManager.h"
|
|
#include "SNotificationList.h"
|
|
#include "GenericCommands.h"
|
|
#include "IAnalyticsProvider.h"
|
|
#include "EngineAnalytics.h"
|
|
|
|
DEFINE_LOG_CATEGORY(LogMainFrame);
|
|
#define LOCTEXT_NAMESPACE "FMainFrameModule"
|
|
|
|
|
|
const FText StaticGetApplicationTitle( const bool bIncludeGameName )
|
|
{
|
|
static const FText ApplicationTitle = NSLOCTEXT("UnrealEditor", "ApplicationTitle", "Unreal Editor");
|
|
|
|
if (bIncludeGameName && FApp::HasGameName())
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("GameName"), FText::FromString( FString( FApp::GetGameName())));
|
|
Args.Add(TEXT("AppTitle"), ApplicationTitle);
|
|
|
|
const EBuildConfigurations::Type BuildConfig = FApp::GetBuildConfiguration();
|
|
|
|
if (BuildConfig != EBuildConfigurations::Shipping && BuildConfig != EBuildConfigurations::Development && BuildConfig != EBuildConfigurations::Unknown)
|
|
{
|
|
Args.Add( TEXT("Config"), EBuildConfigurations::ToText(BuildConfig));
|
|
|
|
return FText::Format( NSLOCTEXT("UnrealEditor", "AppTitleGameNameWithConfig", "{GameName} [{Config}] - {AppTitle}"), Args );
|
|
}
|
|
|
|
return FText::Format( NSLOCTEXT("UnrealEditor", "AppTitleGameName", "{GameName} - {AppTitle}"), Args );
|
|
}
|
|
|
|
return ApplicationTitle;
|
|
}
|
|
|
|
|
|
/* IMainFrameModule implementation
|
|
*****************************************************************************/
|
|
|
|
void FMainFrameModule::CreateDefaultMainFrame( const bool bStartImmersive, const bool bStartPIE )
|
|
{
|
|
if (!IsWindowInitialized())
|
|
{
|
|
FRootWindowLocation DefaultWindowLocation;
|
|
|
|
bool bEmbedTitleAreaContent = true;
|
|
bool bIsUserSizable = true;
|
|
bool bSupportsMaximize = true;
|
|
bool bSupportsMinimize = true;
|
|
FText WindowTitle;
|
|
if ( ShouldShowProjectDialogAtStartup() )
|
|
{
|
|
// Force tabs restored from layout that have no window (the LevelEditor tab) to use a docking area with
|
|
// embedded title area content. We need to override the behavior here because we're creating the actual
|
|
// window ourselves instead of letting the tab management system create it for us.
|
|
bEmbedTitleAreaContent = false;
|
|
|
|
// Do not maximize the window initially. Keep a small dialog feel.
|
|
DefaultWindowLocation.InitiallyMaximized = false;
|
|
|
|
DefaultWindowLocation.WindowSize = GetProjectBrowserWindowSize();
|
|
DefaultWindowLocation.ScreenPosition = DefaultWindowLocation.GetCenteredScreenPosition();
|
|
|
|
bIsUserSizable = true;
|
|
bSupportsMaximize = true;
|
|
bSupportsMinimize = true;
|
|
|
|
// When opening the project dialog, show "Project Browser" in the window title
|
|
WindowTitle = LOCTEXT("ProjectBrowserDialogTitle", "Unreal Project Browser");
|
|
}
|
|
else
|
|
{
|
|
if( bStartImmersive )
|
|
{
|
|
// Start maximized if we are in immersive mode
|
|
DefaultWindowLocation.InitiallyMaximized = true;
|
|
}
|
|
|
|
const bool bIncludeGameName = true;
|
|
WindowTitle = GetApplicationTitle( bIncludeGameName );
|
|
}
|
|
|
|
TSharedRef<SWindow> RootWindow = SNew(SWindow)
|
|
.AutoCenter( EAutoCenter::None )
|
|
.Title( WindowTitle )
|
|
.IsInitiallyMaximized( DefaultWindowLocation.InitiallyMaximized )
|
|
.ScreenPosition( DefaultWindowLocation.ScreenPosition )
|
|
.ClientSize( DefaultWindowLocation.WindowSize )
|
|
.CreateTitleBar( !bEmbedTitleAreaContent )
|
|
.SizingRule( bIsUserSizable ? ESizingRule::UserSized : ESizingRule::FixedSize )
|
|
.SupportsMaximize( bSupportsMaximize )
|
|
.SupportsMinimize( bSupportsMinimize );
|
|
|
|
const bool bShowRootWindowImmediately = false;
|
|
FSlateApplication::Get().AddWindow( RootWindow, bShowRootWindowImmediately );
|
|
|
|
FGlobalTabmanager::Get()->SetRootWindow(RootWindow);
|
|
FSlateNotificationManager::Get().SetRootWindow(RootWindow);
|
|
|
|
TSharedPtr<SWidget> MainFrameContent;
|
|
bool bLevelEditorIsMainTab = false;
|
|
if ( ShouldShowProjectDialogAtStartup() )
|
|
{
|
|
MainFrameContent = FGameProjectGenerationModule::Get().CreateGameProjectDialog(/*bAllowProjectOpening=*/true, /*bAllowProjectCreate=*/true);
|
|
}
|
|
else
|
|
{
|
|
// Get desktop metrics
|
|
FDisplayMetrics DisplayMetrics;
|
|
FSlateApplication::Get().GetDisplayMetrics( DisplayMetrics );
|
|
|
|
// Setup a position and size for the main frame window that's centered in the desktop work area
|
|
const float CenterScale = 0.65f;
|
|
const FVector2D DisplaySize(
|
|
DisplayMetrics.PrimaryDisplayWorkAreaRect.Right - DisplayMetrics.PrimaryDisplayWorkAreaRect.Left,
|
|
DisplayMetrics.PrimaryDisplayWorkAreaRect.Bottom - DisplayMetrics.PrimaryDisplayWorkAreaRect.Top );
|
|
const FVector2D WindowSize = CenterScale * DisplaySize;
|
|
|
|
TSharedRef<FTabManager::FLayout> LoadedLayout = FLayoutSaveRestore::LoadFromConfig(GEditorLayoutIni,
|
|
// We persist the positioning of the level editor and the content browser.
|
|
// The asset editors currently do not get saved.
|
|
FTabManager::NewLayout( "UnrealEd_Layout_v1.4" )
|
|
->AddArea
|
|
(
|
|
// level editor window
|
|
FTabManager::NewPrimaryArea()
|
|
->Split
|
|
(
|
|
FTabManager::NewStack()
|
|
->SetSizeCoefficient(2.0f)
|
|
->AddTab("LevelEditor", ETabState::OpenedTab)
|
|
->AddTab("DockedToolkit", ETabState::ClosedTab)
|
|
)
|
|
)
|
|
->AddArea
|
|
(
|
|
// content browser window
|
|
FTabManager::NewArea(WindowSize)
|
|
->Split
|
|
(
|
|
FTabManager::NewStack()
|
|
->SetSizeCoefficient(1.0f)
|
|
->AddTab("ContentBrowser1Tab", ETabState::ClosedTab)
|
|
)
|
|
)
|
|
->AddArea
|
|
(
|
|
// toolkits window
|
|
FTabManager::NewArea(WindowSize)
|
|
->SetOrientation(Orient_Vertical)
|
|
->Split
|
|
(
|
|
FTabManager::NewStack()
|
|
->SetSizeCoefficient(1.0f)
|
|
->AddTab("StandaloneToolkit", ETabState::ClosedTab)
|
|
)
|
|
->Split
|
|
(
|
|
FTabManager::NewStack()
|
|
->SetSizeCoefficient(0.35f)
|
|
->AddTab("MergeTool", ETabState::ClosedTab)
|
|
)
|
|
)
|
|
->AddArea
|
|
(
|
|
// settings window
|
|
FTabManager::NewArea(WindowSize)
|
|
->Split
|
|
(
|
|
FTabManager::NewStack()
|
|
->SetSizeCoefficient(1.0f)
|
|
->AddTab("EditorSettings", ETabState::ClosedTab)
|
|
->AddTab("ProjectSettings", ETabState::ClosedTab)
|
|
->AddTab("PluginsEditor", ETabState::ClosedTab)
|
|
)
|
|
)
|
|
);
|
|
|
|
MainFrameContent = FGlobalTabmanager::Get()->RestoreFrom( LoadedLayout, RootWindow, bEmbedTitleAreaContent );
|
|
bLevelEditorIsMainTab = true;
|
|
}
|
|
|
|
RootWindow->SetContent(MainFrameContent.ToSharedRef());
|
|
|
|
TSharedPtr<SDockTab> MainTab;
|
|
if ( bLevelEditorIsMainTab )
|
|
{
|
|
MainTab = FGlobalTabmanager::Get()->InvokeTab( FTabId("LevelEditor") );
|
|
|
|
// make sure we only allow the message log to be shown when we have a level editor main tab
|
|
FMessageLogModule& MessageLogModule = FModuleManager::LoadModuleChecked<FMessageLogModule>(TEXT("MessageLog"));
|
|
MessageLogModule.EnableMessageLogDisplay(true);
|
|
}
|
|
|
|
// Initialize the main frame window
|
|
MainFrameHandler->OnMainFrameGenerated( MainTab, RootWindow );
|
|
|
|
// Show the window!
|
|
MainFrameHandler->ShowMainFrameWindow( RootWindow, bStartImmersive, bStartPIE );
|
|
|
|
MRUFavoritesList = new FMainMRUFavoritesList;
|
|
MRUFavoritesList->ReadFromINI();
|
|
|
|
MainFrameCreationFinishedEvent.Broadcast(RootWindow, ShouldShowProjectDialogAtStartup());
|
|
}
|
|
}
|
|
|
|
|
|
TSharedRef<SWidget> FMainFrameModule::MakeMainMenu( const TSharedPtr<FTabManager>& TabManager, const TSharedRef< FExtender > Extender ) const
|
|
{
|
|
return FMainMenu::MakeMainMenu( TabManager, Extender );
|
|
}
|
|
|
|
|
|
TSharedRef<SWidget> FMainFrameModule::MakeMainTabMenu( const TSharedPtr<FTabManager>& TabManager, const TSharedRef< FExtender > Extender ) const
|
|
{
|
|
return FMainMenu::MakeMainTabMenu( TabManager, Extender );
|
|
}
|
|
|
|
|
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
TSharedRef<SWidget> FMainFrameModule::MakeDeveloperTools() const
|
|
{
|
|
struct Local
|
|
{
|
|
static FText GetFrameRateAsString()
|
|
{
|
|
// Clamp to avoid huge averages at startup or after hitches
|
|
const float AverageFPS = 1.0f / FSlateApplication::Get().GetAverageDeltaTime();
|
|
const float ClampedFPS = ( AverageFPS < 0.0f || AverageFPS > 4000.0f ) ? 0.0f : AverageFPS;
|
|
|
|
static const FNumberFormattingOptions FormatOptions = FNumberFormattingOptions()
|
|
.SetMinimumFractionalDigits(1)
|
|
.SetMaximumFractionalDigits(1);
|
|
return FText::AsNumber( ClampedFPS, &FormatOptions );
|
|
}
|
|
|
|
static FText GetFrameTimeAsString()
|
|
{
|
|
// Clamp to avoid huge averages at startup or after hitches
|
|
const float AverageMS = FSlateApplication::Get().GetAverageDeltaTime() * 1000.0f;
|
|
const float ClampedMS = ( AverageMS < 0.0f || AverageMS > 4000.0f ) ? 0.0f : AverageMS;
|
|
|
|
static const FNumberFormattingOptions FormatOptions = FNumberFormattingOptions()
|
|
.SetMinimumFractionalDigits(1)
|
|
.SetMaximumFractionalDigits(1);
|
|
static const FText FrameTimeFmt = FText::FromString(TEXT("{0} ms"));
|
|
return FText::Format( FrameTimeFmt, FText::AsNumber( ClampedMS, &FormatOptions ) );
|
|
}
|
|
|
|
static FText GetMemoryAsString()
|
|
{
|
|
// Only refresh process memory allocated after every so often, to reduce fixed frame time overhead
|
|
static SIZE_T StaticLastTotalAllocated = 0;
|
|
static int32 QueriesUntilUpdate = 1;
|
|
if( --QueriesUntilUpdate <= 0 )
|
|
{
|
|
// Query OS for process memory used
|
|
FPlatformMemoryStats MemoryStats = FPlatformMemory::GetStats();
|
|
StaticLastTotalAllocated = MemoryStats.UsedPhysical;
|
|
|
|
// Wait 60 queries until we refresh memory again
|
|
QueriesUntilUpdate = 60;
|
|
}
|
|
|
|
static const FNumberFormattingOptions FormatOptions = FNumberFormattingOptions()
|
|
.SetMinimumFractionalDigits(2)
|
|
.SetMaximumFractionalDigits(2);
|
|
static const FText MemorySizeFmt = FText::FromString(TEXT("{0} mb"));
|
|
return FText::Format( MemorySizeFmt, FText::AsNumber( (float)StaticLastTotalAllocated / ( 1024.0f * 1024.0f ), &FormatOptions ) );
|
|
}
|
|
|
|
static FText GetUObjectCountAsString()
|
|
{
|
|
return FText::AsNumber(GUObjectArray.GetObjectArrayNumMinusAvailable());
|
|
}
|
|
|
|
static void OpenVideo( FString SourceFilePath )
|
|
{
|
|
FPlatformProcess::ExploreFolder( *( FPaths::GetPath(SourceFilePath) ) );
|
|
}
|
|
|
|
/** Clicked the SaveVideo button available */
|
|
static FReply OnClickSaveVideo()
|
|
{
|
|
// Default the result to fail it will be set to SNotificationItem::CS_Success if saved ok
|
|
SNotificationItem::ECompletionState SaveResultState = SNotificationItem::CS_Fail;
|
|
// The string we will use to tell the user the result of the save
|
|
FText VideoSaveResultText;
|
|
FString HyperLinkText;
|
|
|
|
// Capture unavailable or inactive error string
|
|
ICrashTrackerModule* CrashTracker = FModuleManager::LoadModulePtr<ICrashTrackerModule>("CrashTracker");
|
|
if(CrashTracker)
|
|
{
|
|
FString VideoSaveName;
|
|
EWriteUserCaptureVideoError::Type WriteResult = CrashTracker->WriteUserVideoNow( VideoSaveName );
|
|
// If this returns None the capture was successful, otherwise report the error
|
|
if( WriteResult == EWriteUserCaptureVideoError::None )
|
|
{
|
|
// Setup the string with the path and name of the file
|
|
VideoSaveResultText = LOCTEXT( "VideoSavedAs", "Video capture saved as" );
|
|
HyperLinkText = FPaths::ConvertRelativePathToFull(VideoSaveName);
|
|
// Flag success
|
|
SaveResultState = SNotificationItem::CS_Success;
|
|
}
|
|
else
|
|
{
|
|
// Write returned an error - differentiate between directory creation failure and the capture unavailable
|
|
if( WriteResult == EWriteUserCaptureVideoError::FailedToCreateDirectory )
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add( TEXT("VideoCaptureDirectory"), FText::FromString( FPaths::ConvertRelativePathToFull(FPaths::VideoCaptureDir()) ) );
|
|
VideoSaveResultText = LOCTEXT( "VideoSavedFailedFailedToCreateDir", "Video capture save failed - Failed to create directory\n{VideoCaptureDirectory}" );
|
|
}
|
|
else
|
|
{
|
|
VideoSaveResultText = LOCTEXT( "VideoSavedFailedNotRunning", "Video capture save failed - Capture not active or unavailable" );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This shouldn't happen as the button is hidden when there is no crash tracker
|
|
VideoSaveResultText = LOCTEXT( "VideoSavedFailedNoTracker", "Video capture failed - CrashTracker inactive" );
|
|
}
|
|
|
|
// Inform the user of the result of the operation
|
|
FNotificationInfo Info( VideoSaveResultText );
|
|
Info.ExpireDuration = 5.0f;
|
|
Info.FadeOutDuration = 0.5f;
|
|
Info.bUseSuccessFailIcons = false;
|
|
Info.bUseLargeFont = false;
|
|
if( HyperLinkText != "" )
|
|
{
|
|
Info.Hyperlink = FSimpleDelegate::CreateStatic(&Local::OpenVideo, HyperLinkText );
|
|
Info.HyperlinkText = FText::FromString( HyperLinkText );
|
|
}
|
|
|
|
TWeakPtr<SNotificationItem> SaveMessagePtr;
|
|
SaveMessagePtr = FSlateNotificationManager::Get().AddNotification(Info);
|
|
SaveMessagePtr.Pin()->SetCompletionState(SaveResultState);
|
|
|
|
return FReply::Handled();
|
|
}
|
|
|
|
|
|
/** @return Returns true if frame rate and memory should be displayed in the UI */
|
|
static EVisibility ShouldShowFrameRateAndMemory()
|
|
{
|
|
return GetDefault<UEditorPerProjectUserSettings>()->bShowFrameRateAndMemory ? EVisibility::SelfHitTestInvisible : EVisibility::Collapsed;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
const FSuperSearchModule& SuperSearchModule = FModuleManager::LoadModuleChecked< FSuperSearchModule >(TEXT("SuperSearch"));
|
|
|
|
// We need the output log module in order to instantiate SConsoleInputBox widgets
|
|
const FOutputLogModule& OutputLogModule = FModuleManager::LoadModuleChecked< FOutputLogModule >(TEXT("OutputLog"));
|
|
|
|
const FSlateFontInfo& SmallFixedFont = FEditorStyle::GetFontStyle(TEXT("MainFrame.DebugTools.SmallFont") );
|
|
const FSlateFontInfo& NormalFixedFont = FEditorStyle::GetFontStyle(TEXT("MainFrame.DebugTools.NormalFont") );
|
|
const FSlateFontInfo& LabelFont = FEditorStyle::GetFontStyle(TEXT("MainFrame.DebugTools.LabelFont") );
|
|
|
|
TSharedPtr< SWidget > DeveloperTools;
|
|
TSharedPtr< SEditableTextBox > ExposedEditableTextBox;
|
|
|
|
ICrashTrackerModule* CrashTracker = FModuleManager::LoadModulePtr<ICrashTrackerModule>("CrashTracker");
|
|
bool bCrashTrackerVideoAvailable = false;
|
|
if (CrashTracker)
|
|
{
|
|
bCrashTrackerVideoAvailable = CrashTracker->IsVideoCaptureAvailable();
|
|
}
|
|
|
|
TSharedRef<SWidget> FrameRateAndMemoryWidget =
|
|
SNew( SHorizontalBox )
|
|
.Visibility_Static( &Local::ShouldShowFrameRateAndMemory )
|
|
|
|
// FPS
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( 0.0f, 0.0f, 4.0f, 0.0f )
|
|
[
|
|
SNew( SHorizontalBox )
|
|
.Visibility( GIsDemoMode ? EVisibility::Collapsed : EVisibility::HitTestInvisible )
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Bottom)
|
|
[
|
|
SNew( STextBlock )
|
|
.Text( LOCTEXT("FrameRateLabel", "FPS: ") )
|
|
.Font( LabelFont )
|
|
.ColorAndOpacity( FLinearColor( 0.3f, 0.3f, 0.3f ) )
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Bottom)
|
|
[
|
|
SNew( STextBlock )
|
|
.Text_Static( &Local::GetFrameRateAsString )
|
|
.Font(NormalFixedFont)
|
|
.ColorAndOpacity( FLinearColor( 0.6f, 0.6f, 0.6f ) )
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Bottom)
|
|
.Padding( 4.0f, 0.0f, 0.0f, 0.0f )
|
|
[
|
|
SNew( STextBlock )
|
|
.Text( LOCTEXT("FrameRate/FrameTime", "/") )
|
|
.Font( SmallFixedFont )
|
|
.ColorAndOpacity( FLinearColor( 0.4f, 0.4f, 0.4f ) )
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Bottom)
|
|
.Padding( 4.0f, 0.0f, 0.0f, 0.0f )
|
|
[
|
|
SNew( STextBlock )
|
|
.Text_Static( &Local::GetFrameTimeAsString )
|
|
.Font( SmallFixedFont )
|
|
.ColorAndOpacity( FLinearColor( 0.4f, 0.4f, 0.4f ) )
|
|
]
|
|
]
|
|
|
|
// Memory
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( 4.0f, 0.0f, 4.0f, 0.0f )
|
|
[
|
|
SNew( SHorizontalBox )
|
|
.Visibility( GIsDemoMode ? EVisibility::Collapsed : EVisibility::HitTestInvisible )
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Bottom)
|
|
[
|
|
SNew( STextBlock )
|
|
.Text( LOCTEXT("MemoryLabel", "Mem: ") )
|
|
.Font( LabelFont )
|
|
.ColorAndOpacity( FLinearColor( 0.3f, 0.3f, 0.3f ) )
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Bottom)
|
|
[
|
|
SNew( STextBlock )
|
|
.Text_Static( &Local::GetMemoryAsString )
|
|
.Font(NormalFixedFont)
|
|
.ColorAndOpacity( FLinearColor( 0.6f, 0.6f, 0.6f ) )
|
|
]
|
|
]
|
|
|
|
// UObject count
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( 4.0f, 0.0f, 4.0f, 0.0f )
|
|
[
|
|
SNew( SHorizontalBox )
|
|
.Visibility( GIsDemoMode ? EVisibility::Collapsed : EVisibility::HitTestInvisible )
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Bottom)
|
|
[
|
|
SNew( STextBlock )
|
|
.Text( LOCTEXT("UObjectCountLabel", "Objs: ") )
|
|
.Font( LabelFont )
|
|
.ColorAndOpacity( FLinearColor( 0.3f, 0.3f, 0.3f ) )
|
|
]
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Bottom)
|
|
[
|
|
SNew( STextBlock )
|
|
.Text_Static( &Local::GetUObjectCountAsString )
|
|
.Font(NormalFixedFont)
|
|
.ColorAndOpacity( FLinearColor( 0.6f, 0.6f, 0.6f ) )
|
|
]
|
|
]
|
|
;
|
|
|
|
bool bUseSuperSearch = true;
|
|
|
|
// Invisible border, so that we can animate our box panel size
|
|
return SNew( SBorder )
|
|
.Visibility( EVisibility::SelfHitTestInvisible )
|
|
.Padding( FMargin(0.0f, 0.0f, 0.0f, 1.0f) )
|
|
.VAlign(VAlign_Bottom)
|
|
.BorderImage( FEditorStyle::GetBrush("NoBorder") )
|
|
[
|
|
SNew( SHorizontalBox )
|
|
.Visibility( EVisibility::SelfHitTestInvisible )
|
|
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( 0.0f )
|
|
[
|
|
FrameRateAndMemoryWidget
|
|
]
|
|
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Bottom)
|
|
.Padding( 0.0f )
|
|
[
|
|
SNew(SBox)
|
|
.Padding( FMargin( 4.0f, 0.0f, 0.0f, 0.0f ) )
|
|
[
|
|
bUseSuperSearch ? SuperSearchModule.MakeSearchBox( ExposedEditableTextBox ) : OutputLogModule.MakeConsoleInputBox( ExposedEditableTextBox )
|
|
]
|
|
]
|
|
// Editor live streaming toggle button
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign( VAlign_Bottom )
|
|
[
|
|
SNew(SButton)
|
|
.Visibility_Static( []() -> EVisibility { return IEditorLiveStreaming::Get().IsLiveStreamingAvailable() ? EVisibility::Visible : EVisibility::Collapsed; } )
|
|
.ToolTipText( LOCTEXT( "BroadcastTooltip", "Starts or stops broadcasting of this editor session to a live internet streaming service." ) )
|
|
.OnClicked_Static( []
|
|
{
|
|
// Toggle broadcasting on or off
|
|
if( IEditorLiveStreaming::Get().IsBroadcastingEditor() )
|
|
{
|
|
IEditorLiveStreaming::Get().StopBroadcastingEditor();
|
|
}
|
|
else
|
|
{
|
|
IEditorLiveStreaming::Get().StartBroadcastingEditor();
|
|
}
|
|
return FReply::Handled();
|
|
} )
|
|
.ButtonStyle( FEditorStyle::Get(), "NoBorder" )
|
|
.ContentPadding(FMargin(1,0))
|
|
[
|
|
SNew(SImage)
|
|
.Image( FEditorStyle::GetBrush("EditorLiveStreaming.BroadcastButton") )
|
|
.ColorAndOpacity_Static( []
|
|
{
|
|
// Pulsate the button graphics while we're broadcasting
|
|
FSlateColor Color( FLinearColor::White );
|
|
if( IEditorLiveStreaming::Get().IsBroadcastingEditor() )
|
|
{
|
|
Color = FLinearColor( 1.0f, 1.0f, 1.0f, FMath::MakePulsatingValue( FSlateApplication::Get().GetCurrentTime(), 2.0f ) );
|
|
}
|
|
return Color;
|
|
} )
|
|
]
|
|
]
|
|
|
|
// Crash report "save video" button
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign( VAlign_Bottom )
|
|
[
|
|
SNew(SButton)
|
|
.Visibility( bCrashTrackerVideoAvailable ? EVisibility::Visible : EVisibility::Collapsed )
|
|
.ToolTipText( LOCTEXT( "SaveReplayTooltip", "Saves a video of the last 20 seconds of your work." ) )
|
|
.OnClicked_Static( &Local::OnClickSaveVideo )
|
|
.ButtonStyle( FEditorStyle::Get(), "NoBorder" )
|
|
.ContentPadding(FMargin(1,0))
|
|
[
|
|
SNew(SImage)
|
|
. Image( FEditorStyle::GetBrush("CrashTracker.Record") )
|
|
]
|
|
]
|
|
];
|
|
}
|
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
|
|
|
|
void FMainFrameModule::SetLevelNameForWindowTitle( const FString& InLevelFileName )
|
|
{
|
|
LoadedLevelName = (InLevelFileName.Len() > 0)
|
|
? FPaths::GetBaseFilename(InLevelFileName)
|
|
: NSLOCTEXT("UnrealEd", "Untitled", "Untitled" ).ToString();
|
|
}
|
|
|
|
|
|
/* IModuleInterface implementation
|
|
*****************************************************************************/
|
|
|
|
void FMainFrameModule::StartupModule( )
|
|
{
|
|
MRUFavoritesList = NULL;
|
|
|
|
ensureMsgf(!IsRunningGame(), TEXT("The MainFrame module should only be loaded when running the editor. Code that extends the editor, adds menu items, etc... should not run when running in -game mode or in a non-WITH_EDITOR build"));
|
|
MainFrameHandler = MakeShareable(new FMainFrameHandler);
|
|
|
|
FGenericCommands::Register();
|
|
FMainFrameCommands::Register();
|
|
|
|
SetLevelNameForWindowTitle(TEXT(""));
|
|
|
|
// Register to find out about when hot reload completes, so we can show a notification
|
|
IHotReloadModule& HotReloadModule = IHotReloadModule::Get();
|
|
HotReloadModule.OnModuleCompilerStarted().AddRaw( this, &FMainFrameModule::HandleLevelEditorModuleCompileStarted );
|
|
HotReloadModule.OnModuleCompilerFinished().AddRaw( this, &FMainFrameModule::HandleLevelEditorModuleCompileFinished );
|
|
HotReloadModule.OnHotReload().AddRaw( this, &FMainFrameModule::HandleHotReloadFinished );
|
|
|
|
#if WITH_EDITOR
|
|
ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::LoadModuleChecked<ISourceCodeAccessModule>("SourceCodeAccess");
|
|
SourceCodeAccessModule.OnLaunchingCodeAccessor().AddRaw( this, &FMainFrameModule::HandleCodeAccessorLaunching );
|
|
SourceCodeAccessModule.OnDoneLaunchingCodeAccessor().AddRaw( this, &FMainFrameModule::HandleCodeAccessorLaunched );
|
|
SourceCodeAccessModule.OnOpenFileFailed().AddRaw( this, &FMainFrameModule::HandleCodeAccessorOpenFileFailed );
|
|
#endif
|
|
|
|
// load sounds
|
|
CompileStartSound = LoadObject<USoundBase>(NULL, TEXT("/Engine/EditorSounds/Notifications/CompileStart_Cue.CompileStart_Cue"));
|
|
CompileStartSound->AddToRoot();
|
|
CompileSuccessSound = LoadObject<USoundBase>(NULL, TEXT("/Engine/EditorSounds/Notifications/CompileSuccess_Cue.CompileSuccess_Cue"));
|
|
CompileSuccessSound->AddToRoot();
|
|
CompileFailSound = LoadObject<USoundBase>(NULL, TEXT("/Engine/EditorSounds/Notifications/CompileFailed_Cue.CompileFailed_Cue"));
|
|
CompileFailSound->AddToRoot();
|
|
|
|
ModuleCompileStartTime = 0.0f;
|
|
|
|
// migrate old layout settings
|
|
FLayoutSaveRestore::MigrateConfig(GEditorPerProjectIni, GEditorLayoutIni);
|
|
}
|
|
|
|
|
|
void FMainFrameModule::ShutdownModule( )
|
|
{
|
|
// Destroy the main frame window
|
|
TSharedPtr< SWindow > ParentWindow( GetParentWindow() );
|
|
if( ParentWindow.IsValid() )
|
|
{
|
|
ParentWindow->DestroyWindowImmediately();
|
|
}
|
|
|
|
MainFrameHandler.Reset();
|
|
|
|
FMainFrameCommands::Unregister();
|
|
|
|
if( IHotReloadModule::IsAvailable() )
|
|
{
|
|
IHotReloadModule& HotReloadModule = IHotReloadModule::Get();
|
|
HotReloadModule.OnHotReload().RemoveAll( this );
|
|
HotReloadModule.OnModuleCompilerStarted().RemoveAll( this );
|
|
HotReloadModule.OnModuleCompilerFinished().RemoveAll( this );
|
|
}
|
|
|
|
#if WITH_EDITOR
|
|
if(FModuleManager::Get().IsModuleLoaded("SourceCodeAccess"))
|
|
{
|
|
ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::GetModuleChecked<ISourceCodeAccessModule>("SourceCodeAccess");
|
|
SourceCodeAccessModule.OnLaunchingCodeAccessor().RemoveAll( this );
|
|
SourceCodeAccessModule.OnDoneLaunchingCodeAccessor().RemoveAll( this );
|
|
SourceCodeAccessModule.OnOpenFileFailed().RemoveAll( this );
|
|
}
|
|
#endif
|
|
|
|
if(CompileStartSound != NULL)
|
|
{
|
|
if (!GExitPurge)
|
|
{
|
|
CompileStartSound->RemoveFromRoot();
|
|
}
|
|
CompileStartSound = NULL;
|
|
}
|
|
|
|
if(CompileSuccessSound != NULL)
|
|
{
|
|
if (!GExitPurge)
|
|
{
|
|
CompileSuccessSound->RemoveFromRoot();
|
|
}
|
|
CompileSuccessSound = NULL;
|
|
}
|
|
|
|
if(CompileFailSound != NULL)
|
|
{
|
|
if (!GExitPurge)
|
|
{
|
|
CompileFailSound->RemoveFromRoot();
|
|
}
|
|
CompileFailSound = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/* FMainFrameModule implementation
|
|
*****************************************************************************/
|
|
|
|
bool FMainFrameModule::ShouldShowProjectDialogAtStartup( ) const
|
|
{
|
|
return !FApp::HasGameName();
|
|
}
|
|
|
|
|
|
/* FMainFrameModule event handlers
|
|
*****************************************************************************/
|
|
|
|
void FMainFrameModule::HandleLevelEditorModuleCompileStarted( bool bIsAsyncCompile )
|
|
{
|
|
ModuleCompileStartTime = FPlatformTime::Seconds();
|
|
|
|
if (CompileNotificationPtr.IsValid())
|
|
{
|
|
CompileNotificationPtr.Pin()->ExpireAndFadeout();
|
|
}
|
|
|
|
if ( GEditor )
|
|
{
|
|
GEditor->PlayEditorSound(CompileStartSound);
|
|
}
|
|
|
|
FNotificationInfo Info( NSLOCTEXT("MainFrame", "RecompileInProgress", "Compiling C++ Code") );
|
|
Info.Image = FEditorStyle::GetBrush(TEXT("LevelEditor.RecompileGameCode"));
|
|
Info.ExpireDuration = 5.0f;
|
|
Info.bFireAndForget = false;
|
|
|
|
// We can only show the cancel button on async builds
|
|
if (bIsAsyncCompile)
|
|
{
|
|
Info.ButtonDetails.Add(FNotificationButtonInfo(LOCTEXT("CancelC++Compilation", "Cancel"), FText(), FSimpleDelegate::CreateRaw(this, &FMainFrameModule::OnCancelCodeCompilationClicked)));
|
|
}
|
|
|
|
CompileNotificationPtr = FSlateNotificationManager::Get().AddNotification(Info);
|
|
|
|
if (CompileNotificationPtr.IsValid())
|
|
{
|
|
CompileNotificationPtr.Pin()->SetCompletionState(SNotificationItem::CS_Pending);
|
|
}
|
|
}
|
|
|
|
void FMainFrameModule::OnCancelCodeCompilationClicked()
|
|
{
|
|
IHotReloadModule::Get().RequestStopCompilation();
|
|
}
|
|
|
|
void FMainFrameModule::HandleLevelEditorModuleCompileFinished(const FString& LogDump, ECompilationResult::Type CompilationResult, bool bShowLog)
|
|
{
|
|
// Track stats
|
|
{
|
|
const float ModuleCompileDuration = (float)(FPlatformTime::Seconds() - ModuleCompileStartTime);
|
|
UE_LOG(LogMainFrame, Log, TEXT("MainFrame: Module compiling took %.3f seconds"), ModuleCompileDuration);
|
|
|
|
if( FEngineAnalytics::IsAvailable() )
|
|
{
|
|
TArray< FAnalyticsEventAttribute > CompileAttribs;
|
|
CompileAttribs.Add(FAnalyticsEventAttribute(TEXT("Duration"), FString::Printf(TEXT("%.3f"), ModuleCompileDuration)));
|
|
CompileAttribs.Add(FAnalyticsEventAttribute(TEXT("Result"), ECompilationResult::ToString(CompilationResult)));
|
|
FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Modules.Recompile"), CompileAttribs);
|
|
}
|
|
}
|
|
|
|
TSharedPtr<SNotificationItem> NotificationItem = CompileNotificationPtr.Pin();
|
|
|
|
if (NotificationItem.IsValid())
|
|
{
|
|
if (!ECompilationResult::Failed(CompilationResult))
|
|
{
|
|
if ( GEditor )
|
|
{
|
|
GEditor->PlayEditorSound(CompileSuccessSound);
|
|
}
|
|
|
|
NotificationItem->SetText(NSLOCTEXT("MainFrame", "RecompileComplete", "Compile Complete!"));
|
|
NotificationItem->SetExpireDuration( 5.0f );
|
|
NotificationItem->SetCompletionState(SNotificationItem::CS_Success);
|
|
}
|
|
else
|
|
{
|
|
struct Local
|
|
{
|
|
static void ShowCompileLog()
|
|
{
|
|
FMessageLogModule& MessageLogModule = FModuleManager::GetModuleChecked<FMessageLogModule>("MessageLog");
|
|
MessageLogModule.OpenMessageLog(FCompilerResultsLog::GetLogName());
|
|
}
|
|
};
|
|
|
|
if ( GEditor )
|
|
{
|
|
GEditor->PlayEditorSound(CompileFailSound);
|
|
}
|
|
|
|
if (CompilationResult == ECompilationResult::FailedDueToHeaderChange)
|
|
{
|
|
NotificationItem->SetText(NSLOCTEXT("MainFrame", "RecompileFailedDueToHeaderChange", "Compile failed due to the header changes. Close the editor and recompile project in IDE to apply changes."));
|
|
}
|
|
else if (CompilationResult == ECompilationResult::Canceled)
|
|
{
|
|
NotificationItem->SetText(NSLOCTEXT("MainFrame", "RecompileCanceled", "Compile Canceled!"));
|
|
}
|
|
else
|
|
{
|
|
NotificationItem->SetText(NSLOCTEXT("MainFrame", "RecompileFailed", "Compile Failed!"));
|
|
}
|
|
|
|
NotificationItem->SetCompletionState(SNotificationItem::CS_Fail);
|
|
NotificationItem->SetHyperlink(FSimpleDelegate::CreateStatic(&Local::ShowCompileLog));
|
|
NotificationItem->SetExpireDuration(30.0f);
|
|
}
|
|
|
|
NotificationItem->ExpireAndFadeout();
|
|
|
|
CompileNotificationPtr.Reset();
|
|
}
|
|
}
|
|
|
|
|
|
void FMainFrameModule::HandleHotReloadFinished( bool bWasTriggeredAutomatically )
|
|
{
|
|
// Only play the notification for hot reloads that were triggered automatically. If the user triggered the hot reload, they'll
|
|
// have a different visual cue for that, such as the "Compiling Complete!" notification
|
|
if( bWasTriggeredAutomatically )
|
|
{
|
|
FNotificationInfo Info( LOCTEXT("HotReloadFinished", "Hot Reload Complete!") );
|
|
Info.Image = FEditorStyle::GetBrush(TEXT("LevelEditor.RecompileGameCode"));
|
|
Info.FadeInDuration = 0.1f;
|
|
Info.FadeOutDuration = 0.5f;
|
|
Info.ExpireDuration = 1.5f;
|
|
Info.bUseThrobber = false;
|
|
Info.bUseSuccessFailIcons = true;
|
|
Info.bUseLargeFont = true;
|
|
Info.bFireAndForget = false;
|
|
Info.bAllowThrottleWhenFrameRateIsLow = false;
|
|
auto NotificationItem = FSlateNotificationManager::Get().AddNotification( Info );
|
|
NotificationItem->SetCompletionState(SNotificationItem::CS_Success);
|
|
NotificationItem->ExpireAndFadeout();
|
|
|
|
GEditor->PlayEditorSound(CompileSuccessSound);
|
|
}
|
|
}
|
|
|
|
|
|
void FMainFrameModule::HandleCodeAccessorLaunched( const bool WasSuccessful )
|
|
{
|
|
TSharedPtr<SNotificationItem> NotificationItem = CodeAccessorNotificationPtr.Pin();
|
|
|
|
if (NotificationItem.IsValid())
|
|
{
|
|
ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::LoadModuleChecked<ISourceCodeAccessModule>("SourceCodeAccess");
|
|
const FText AccessorNameText = SourceCodeAccessModule.GetAccessor().GetNameText();
|
|
|
|
if (WasSuccessful)
|
|
{
|
|
NotificationItem->SetText( FText::Format(LOCTEXT("CodeAccessorLoadComplete", "{0} loaded!"), AccessorNameText) );
|
|
NotificationItem->SetCompletionState(SNotificationItem::CS_Success);
|
|
}
|
|
else
|
|
{
|
|
NotificationItem->SetText( FText::Format(LOCTEXT("CodeAccessorLoadFailed", "{0} failed to launch!"), AccessorNameText) );
|
|
NotificationItem->SetCompletionState(SNotificationItem::CS_Fail);
|
|
}
|
|
|
|
NotificationItem->ExpireAndFadeout();
|
|
CodeAccessorNotificationPtr.Reset();
|
|
}
|
|
}
|
|
|
|
|
|
void FMainFrameModule::HandleCodeAccessorLaunching( )
|
|
{
|
|
if (CodeAccessorNotificationPtr.IsValid())
|
|
{
|
|
CodeAccessorNotificationPtr.Pin()->ExpireAndFadeout();
|
|
}
|
|
|
|
ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::LoadModuleChecked<ISourceCodeAccessModule>("SourceCodeAccess");
|
|
const FText AccessorNameText = SourceCodeAccessModule.GetAccessor().GetNameText();
|
|
|
|
FNotificationInfo Info( FText::Format(LOCTEXT("CodeAccessorLoadInProgress", "Loading {0}"), AccessorNameText) );
|
|
Info.bFireAndForget = false;
|
|
|
|
CodeAccessorNotificationPtr = FSlateNotificationManager::Get().AddNotification(Info);
|
|
CodeAccessorNotificationPtr.Pin()->SetCompletionState(SNotificationItem::CS_Pending);
|
|
}
|
|
|
|
void FMainFrameModule::HandleCodeAccessorOpenFileFailed(const FString& Filename)
|
|
{
|
|
auto* Info = new FNotificationInfo(FText::Format(LOCTEXT("FileNotFound", "Could not find code file ({Filename})"), FText::FromString(Filename)));
|
|
Info->ExpireDuration = 3.0f;
|
|
FSlateNotificationManager::Get().QueueNotification(Info);
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|
|
|
|
|
|
IMPLEMENT_MODULE(FMainFrameModule, MainFrame);
|