2016-12-08 08:52:44 -05:00
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3209340 on 2016/11/23 by Ben.Marsh
Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h.
Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms.
* Every header now includes everything it needs to compile.
* There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first.
* There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h.
* Every .cpp file includes its matching .h file first.
* This helps validate that each header is including everything it needs to compile.
* No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more.
* You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there.
* There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible.
* No engine code explicitly includes a precompiled header any more.
* We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies.
* PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files.
Tool used to generate this transform is at Engine\Source\Programs\IncludeTool.
[CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
# include "Framework/MultiBox/MultiBoxCustomization.h"
# include "Misc/ConfigCacheIni.h"
# include "Serialization/JsonReader.h"
# include "Serialization/JsonSerializer.h"
# include "Framework/Commands/InputBindingManager.h"
# include "Widgets/Layout/SBorder.h"
# include "Misc/RemoteConfigIni.h"
# include "Framework/Commands/UICommandDragDropOp.h"
2014-03-14 14:13:41 -04:00
void SCustomToolbarPreviewWidget : : Construct ( const FArguments & InArgs )
{
Content = InArgs . _Content . Widget ;
}
void SCustomToolbarPreviewWidget : : BuildMultiBlockWidget ( const ISlateStyle * StyleSet , const FName & StyleName )
{
ChildSlot
[
SNew ( SBorder )
. Padding ( 0 )
. BorderImage ( FCoreStyle : : Get ( ) . GetBrush ( " NoBorder " ) )
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
[
Content . ToSharedRef ( )
]
] ;
2015-08-26 10:33:13 -04:00
// Add this widget to the search list of the multibox and hide it
if ( MultiBlock - > GetSearchable ( ) )
OwnerMultiBoxWidget . Pin ( ) - > AddSearchElement ( this - > AsWidget ( ) , FText : : GetEmpty ( ) ) ;
2014-03-14 14:13:41 -04:00
}
void SMultiBlockDragHandle : : Construct ( const FArguments & InArgs , TSharedRef < SMultiBoxWidget > InBaseWidget , TSharedRef < const FMultiBlock > InBlock , FName CustomizationName )
{
BaseWidget = InBaseWidget ;
Block = InBlock ;
MultiBoxCustomizationName = CustomizationName ;
}
FReply SMultiBlockDragHandle : : OnMouseButtonDown ( const FGeometry & MyGeometry , const FPointerEvent & MouseEvent )
{
if ( MouseEvent . GetEffectingButton ( ) = = EKeys : : LeftMouseButton & & Block - > GetAction ( ) . IsValid ( ) )
{
return FReply : : Handled ( ) . DetectDrag ( SharedThis ( this ) , MouseEvent . GetEffectingButton ( ) ) ;
}
return FReply : : Unhandled ( ) ;
}
void SMultiBlockDragHandle : : OnDragEnter ( const FGeometry & MyGeometry , const FDragDropEvent & DragDropEvent )
{
2014-04-23 18:00:50 -04:00
if ( DragDropEvent . GetOperationAs < FUICommandDragDropOp > ( ) . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
BaseWidget . Pin ( ) - > OnCustomCommandDragEnter ( Block . ToSharedRef ( ) , MyGeometry , DragDropEvent ) ;
}
}
FReply SMultiBlockDragHandle : : OnDragOver ( const FGeometry & MyGeometry , const FDragDropEvent & DragDropEvent )
{
2014-04-23 18:00:50 -04:00
if ( DragDropEvent . GetOperationAs < FUICommandDragDropOp > ( ) . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
BaseWidget . Pin ( ) - > OnCustomCommandDragged ( Block . ToSharedRef ( ) , MyGeometry , DragDropEvent ) ;
return FReply : : Handled ( ) ;
}
return FReply : : Unhandled ( ) ;
}
FReply SMultiBlockDragHandle : : OnDrop ( const FGeometry & MyGeometry , const FDragDropEvent & DragDropEvent )
{
2014-04-23 18:00:50 -04:00
if ( DragDropEvent . GetOperationAs < FUICommandDragDropOp > ( ) . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
BaseWidget . Pin ( ) - > OnCustomCommandDropped ( ) ;
return FReply : : Handled ( ) ;
}
return FReply : : Unhandled ( ) ;
}
FReply SMultiBlockDragHandle : : OnDragDetected ( const FGeometry & MyGeometry , const FPointerEvent & MouseEvent )
{
TSharedRef < FUICommandDragDropOp > NewOp = FUICommandDragDropOp : : New (
Block - > GetAction ( ) . ToSharedRef ( ) ,
MultiBoxCustomizationName ,
2014-11-20 19:21:21 -05:00
Block - > MakeWidget ( BaseWidget . Pin ( ) . ToSharedRef ( ) , EMultiBlockLocation : : None , Block - > HasIcon ( ) ) - > AsWidget ( ) ,
2014-03-14 14:13:41 -04:00
MyGeometry . AbsolutePosition - MouseEvent . GetScreenSpacePosition ( )
) ;
NewOp - > SetOnDropNotification ( FSimpleDelegate : : CreateSP ( BaseWidget . Pin ( ) . ToSharedRef ( ) , & SMultiBoxWidget : : OnDropExternal ) ) ;
TSharedRef < FDragDropOperation > DragDropOp = NewOp ;
return FReply : : Handled ( ) . BeginDragDrop ( DragDropOp ) ;
}
TSharedRef < class IMultiBlockBaseWidget > FDropPreviewBlock : : ConstructWidget ( ) const
{
return
SNew ( SCustomToolbarPreviewWidget )
. Visibility ( EVisibility : : Hidden )
. Content ( )
[
ActualWidget - > AsWidget ( )
] ;
}
void FMultiBoxCustomizationData : : LoadCustomizedBlocks ( )
{
Transactions . Empty ( ) ;
FString Content ;
2015-04-20 10:12:55 -04:00
GConfig - > GetString ( * GetConfigSectionName ( ) , * CustomizationName . ToString ( ) , Content , GEditorPerProjectIni ) ;
2014-03-14 14:13:41 -04:00
TSharedPtr < FJsonObject > SavedData ;
TSharedRef < TJsonReader < > > Reader = TJsonReaderFactory < > : : Create ( FRemoteConfig : : ReplaceIniSpecialCharWithChar ( Content ) . ReplaceEscapedCharWithChar ( ) ) ;
bool bResult = FJsonSerializer : : Deserialize ( Reader , SavedData ) ;
if ( bResult & & SavedData . IsValid ( ) )
{
TArray < TSharedPtr < FJsonValue > > CustomBlockData = SavedData - > GetArrayField ( TEXT ( " CustomBlocks " ) ) ;
for ( TArray < TSharedPtr < FJsonValue > > : : TConstIterator It ( CustomBlockData ) ; It ; + + It )
{
TSharedPtr < FJsonObject > SavedCommand = ( * It ) - > AsObject ( ) ;
if ( SavedCommand . IsValid ( ) )
{
FString CommandName = SavedCommand - > GetStringField ( TEXT ( " CommandName " ) ) ;
FString Context = SavedCommand - > GetStringField ( TEXT ( " Context " ) ) ;
2014-05-06 06:26:25 -04:00
int32 Index = FMath : : TruncToInt ( SavedCommand - > GetNumberField ( TEXT ( " Index " ) ) ) ;
FCustomBlockTransaction : : ETransactionType TransType = ( FCustomBlockTransaction : : ETransactionType ) FMath : : TruncToInt ( SavedCommand - > GetNumberField ( " TransactionType " ) ) ;
2014-03-14 14:13:41 -04:00
if ( ! CommandName . IsEmpty ( ) & & ! Context . IsEmpty ( ) & & Index > = 0 )
{
const TSharedPtr < const FUICommandInfo > FoundCommand = FInputBindingManager : : Get ( ) . FindCommandInContext ( FName ( * Context ) , FName ( * CommandName ) ) ;
if ( FoundCommand . IsValid ( ) )
{
FCustomBlockTransaction NewTransaction ;
if ( TransType = = FCustomBlockTransaction : : Add )
{
NewTransaction = FCustomBlockTransaction : : CreateAdd ( FoundCommand . ToSharedRef ( ) , Index ) ;
}
else
{
NewTransaction = FCustomBlockTransaction : : CreateRemove ( FoundCommand . ToSharedRef ( ) , Index ) ;
}
Transactions . Add ( NewTransaction ) ;
}
}
}
}
}
}
FString FMultiBoxCustomizationData : : GetConfigSectionName ( ) const
{
return TEXT ( " CustomMultiBoxes1_0 " ) ;
}
void FMultiBoxCustomizationData : : RemoveTransactionAt ( int32 RemoveIndex )
{
// Copy off the transaction we are going to remove.
FCustomBlockTransaction TransToRemove = Transactions [ RemoveIndex ] ;
const int32 TransToRemoveIndex = TransToRemove . BlockIndex ;
// Remove the transaction
Transactions . RemoveAt ( RemoveIndex ) ;
// Iterate over all transactions after this one to fix up indices.
for ( int32 StartIndex = RemoveIndex ; StartIndex < Transactions . Num ( ) ; + + StartIndex )
{
int32 & CheckIndex = Transactions [ StartIndex ] . BlockIndex ;
// If the index is greater than or equal to the index we are removing, this transaction is affected by this removal.
if ( CheckIndex > = TransToRemoveIndex )
{
// If the removed transaction was an add, subtract 1 from the index of this transaction. Otherwise, add one.
if ( TransToRemove . TransactionType = = FCustomBlockTransaction : : Add )
{
- - CheckIndex ;
}
else
{
+ + CheckIndex ;
}
}
}
}
bool FMultiBoxCustomizationData : : RemoveDuplicateTransaction ( )
{
if ( Transactions . Num ( ) > 0 )
{
FCustomBlockTransaction LastTrans = Transactions . Last ( ) ;
int32 CheckIndex = LastTrans . BlockIndex ;
// Skip the last item
for ( int32 TransIndex = Transactions . Num ( ) - 2 ; TransIndex > = 0 ; - - TransIndex )
{
FCustomBlockTransaction CurrentTrans = Transactions [ TransIndex ] ;
//ensure( !(CurrentTrans.TransactionType == LastTrans.TransactionType && CurrentTrans.Command == LastTrans.Command ) );
if ( CurrentTrans . Command = = LastTrans . Command & &
CurrentTrans . BlockIndex = = CheckIndex & &
CurrentTrans . TransactionType ! = LastTrans . TransactionType )
{
RemoveTransactionAt ( Transactions . Num ( ) - 1 ) ;
RemoveTransactionAt ( TransIndex ) ;
return true ;
}
if ( CheckIndex > = CurrentTrans . BlockIndex )
{
if ( CurrentTrans . TransactionType = = FCustomBlockTransaction : : Add )
{
- - CheckIndex ;
}
else
{
+ + CheckIndex ;
}
}
}
}
return false ;
}
bool FMultiBoxCustomizationData : : RemoveUnnecessaryTransactions ( const TArray < TSharedRef < const FMultiBlock > > & AllBlocks )
{
// A local struct describing the state of the menu
struct FCustomizationState
{
FCustomizationState ( const TArray < TSharedRef < const FMultiBlock > > & InAllBlocks )
{
for ( int32 BlockIdx = 0 ; BlockIdx < InAllBlocks . Num ( ) ; + + BlockIdx )
{
StateData . Add ( InAllBlocks [ BlockIdx ] - > GetAction ( ) ) ;
}
}
// Applies the inverse operation of the given transaction to mutate the state
void ApplyInverseOfTransaction ( const FCustomBlockTransaction & Trans )
{
if ( Trans . TransactionType = = FCustomBlockTransaction : : Add )
{
// Remove on an add operation
if ( ensure ( StateData . IsValidIndex ( Trans . BlockIndex ) ) )
{
ensure ( StateData [ Trans . BlockIndex ] = = Trans . Command ) ;
StateData . RemoveAt ( Trans . BlockIndex ) ;
}
}
else if ( Trans . TransactionType = = FCustomBlockTransaction : : Remove )
{
// Add on a remove transaction
StateData . Insert ( Trans . Command , Trans . BlockIndex ) ;
}
}
// Compares two states. If all elements of the states are the same then they are "equal"
bool operator = = ( const FCustomizationState & Other ) const
{
if ( StateData . Num ( ) ! = Other . StateData . Num ( ) )
{
return false ;
}
const int32 Length = StateData . Num ( ) ;
for ( int32 StateIdx = 0 ; StateIdx < Length ; + + StateIdx )
{
if ( StateData [ StateIdx ] ! = Other . StateData [ StateIdx ] )
{
return false ;
}
}
return true ;
}
private :
TArray < TWeakPtr < const FUICommandInfo > > StateData ;
} ;
if ( Transactions . Num ( ) > 0 )
{
// Take the current state and start applying the inverse of each transaction to it to determine the states before the current.
// If we found any state that is identical to the current state, all transactions between that state and the current state are unnecessary, so remove them
// Record the initial (current) state and initialize the Test state.
FCustomizationState InitialState ( AllBlocks ) ;
FCustomizationState TestState = InitialState ;
// Walk backwards through all transactions, applying the inverse of each transaction to the test state
for ( int32 TransIdx = Transactions . Num ( ) - 1 ; TransIdx > = 0 ; - - TransIdx )
{
TestState . ApplyInverseOfTransaction ( Transactions [ TransIdx ] ) ;
// If the test state is equal to the current state, all transactions between are unnecessary. Remove them.
if ( TestState = = InitialState )
{
for ( int32 RemoveIdx = Transactions . Num ( ) - 1 ; RemoveIdx > = TransIdx ; - - RemoveIdx )
{
RemoveTransactionAt ( RemoveIdx ) ;
}
// Return true to indicate we actually removed something.
return true ;
}
}
}
// All transactions were necessary to form the final state. Return false.
return false ;
}
void FMultiBoxCustomizationData : : SaveCustomizedBlocks ( )
{
FString SaveData ;
TSharedRef < TJsonWriter < > > Writer = TJsonWriterFactory < > : : Create ( & SaveData ) ;
Writer - > WriteObjectStart ( ) ;
Writer - > WriteArrayStart ( TEXT ( " CustomBlocks " ) ) ;
for ( TArray < FCustomBlockTransaction > : : TConstIterator It ( Transactions ) ; It ; + + It )
{
const FCustomBlockTransaction & Transaction = * It ;
if ( Transaction . Command . IsValid ( ) )
{
const FUICommandInfo & Command = * Transaction . Command . Pin ( ) ;
Writer - > WriteObjectStart ( ) ;
Writer - > WriteValue ( TEXT ( " CommandName " ) , Command . GetCommandName ( ) . ToString ( ) ) ;
Writer - > WriteValue ( TEXT ( " Context " ) , Command . GetBindingContext ( ) . ToString ( ) ) ;
Writer - > WriteValue ( TEXT ( " Index " ) , ( float ) Transaction . BlockIndex ) ;
Writer - > WriteValue ( TEXT ( " TransactionType " ) , ( float ) Transaction . TransactionType ) ;
Writer - > WriteObjectEnd ( ) ;
}
}
Writer - > WriteArrayEnd ( ) ;
Writer - > WriteObjectEnd ( ) ;
Writer - > Close ( ) ;
2015-04-20 10:12:55 -04:00
GConfig - > SetString ( * GetConfigSectionName ( ) , * CustomizationName . ToString ( ) , * FRemoteConfig : : ReplaceIniCharWithSpecialChar ( SaveData ) . ReplaceCharWithEscapedChar ( ) , GEditorPerProjectIni ) ;
2014-03-14 14:13:41 -04:00
}
void FMultiBoxCustomizationData : : BlockRemoved ( TSharedRef < const FMultiBlock > RemovedBlock , int32 Index , const TArray < TSharedRef < const FMultiBlock > > & AllBlocks )
{
FCustomBlockTransaction Remove = FCustomBlockTransaction : : CreateRemove ( RemovedBlock - > GetAction ( ) . ToSharedRef ( ) , Index ) ;
SaveTransaction ( Remove , AllBlocks ) ;
}
void FMultiBoxCustomizationData : : BlockAdded ( TSharedRef < const FMultiBlock > AddedBlock , int32 Index , const TArray < TSharedRef < const FMultiBlock > > & AllBlocks )
{
FCustomBlockTransaction Add = FCustomBlockTransaction : : CreateAdd ( AddedBlock - > GetAction ( ) . ToSharedRef ( ) , Index ) ;
SaveTransaction ( Add , AllBlocks ) ;
}
# define DEBUG_TRANSACTIONS 0
# if DEBUG_TRANSACTIONS
static void PrintTransactions ( const TArray < FCustomBlockTransaction > & Transactions )
{
FPlatformMisc : : LowLevelOutputDebugStringf ( TEXT ( " ==========BEGIN TRANSACTIONS======= \n " ) ) ;
for ( int32 i = 0 ; i < Transactions . Num ( ) ; + + i )
{
const FCustomBlockTransaction & Trans = Transactions [ i ] ;
FString TransType = Trans . TransactionType = = FCustomBlockTransaction : : Add ? TEXT ( " + " ) : TEXT ( " - " ) ;
FPlatformMisc : : LowLevelOutputDebugStringf ( TEXT ( " %s(%s,%d) \n " ) , * TransType , * Trans . Command . Pin ( ) - > GetCommandName ( ) . ToString ( ) , Trans . BlockIndex ) ;
}
FPlatformMisc : : LowLevelOutputDebugStringf ( TEXT ( " ============END TRANSACTIONS======= \n " ) ) ;
}
# endif
void FMultiBoxCustomizationData : : SaveTransaction ( const struct FCustomBlockTransaction & Transaction , const TArray < TSharedRef < const FMultiBlock > > & AllBlocks )
{
Transactions . Add ( Transaction ) ;
while ( RemoveDuplicateTransaction ( ) ) ;
while ( RemoveUnnecessaryTransactions ( AllBlocks ) ) ;
# if DEBUG_TRANSACTIONS
PrintTransactions ( Transactions ) ;
# endif
SaveCustomizedBlocks ( ) ;
}