2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-08-05 17:41:57 -04:00
# include "MergePrivatePCH.h"
2014-12-18 19:17:27 -05:00
# include "DiffUtils.h"
2014-08-05 17:41:57 -04:00
# include "DiffResults.h"
# include "GraphDiffControl.h"
2014-11-24 18:59:49 -05:00
# include "SDockTab.h"
2014-08-05 17:41:57 -04:00
# include "SMergeGraphView.h"
2014-11-24 18:59:49 -05:00
# include "SKismetInspector.h"
2014-08-05 17:41:57 -04:00
# define LOCTEXT_NAMESPACE "SMergeGraphView"
2014-11-24 18:59:49 -05:00
const FName MergeMyBluerpintTabId = FName ( TEXT ( " MergeMyBluerpintTab " ) ) ;
const FName MergeGraphTabId = FName ( TEXT ( " MergeGraphTab " ) ) ;
2014-08-05 17:41:57 -04:00
struct FBlueprintRevPair
{
FBlueprintRevPair ( const UBlueprint * InBlueprint , const FRevisionInfo & InRevData )
: Blueprint ( InBlueprint )
, RevData ( InRevData )
{
}
const UBlueprint * Blueprint ;
const FRevisionInfo & RevData ;
2014-12-17 19:27:27 -05:00
} ; ;
2014-08-05 17:41:57 -04:00
2014-10-27 19:34:03 -04:00
static UEdGraph * FindGraphByName ( UBlueprint const & FromBlueprint , const FName & GraphName )
2014-08-05 17:41:57 -04:00
{
TArray < UEdGraph * > Graphs ;
FromBlueprint . GetAllGraphs ( Graphs ) ;
2014-10-28 13:43:26 -04:00
UEdGraph * Ret = nullptr ;
2014-10-27 19:34:03 -04:00
if ( UEdGraph * * Result = Graphs . FindByPredicate ( FMatchFName ( GraphName ) ) )
2014-08-05 17:41:57 -04:00
{
Ret = * Result ;
}
return Ret ;
}
2014-12-17 19:27:27 -05:00
struct FMergeGraphRowEntry
2014-10-23 13:16:13 -04:00
{
2014-12-17 19:27:27 -05:00
FText Label ;
2014-10-23 13:16:13 -04:00
2014-12-17 19:27:27 -05:00
FName GraphName ;
2014-10-23 13:16:13 -04:00
2014-12-17 19:27:27 -05:00
UEdGraphNode * LocalNode ;
UEdGraphNode * BaseNode ;
UEdGraphNode * RemoteNode ;
UEdGraphPin * LocalPin ;
UEdGraphPin * BasePin ;
UEdGraphPin * RemotePin ;
FLinearColor DisplayColor ;
2014-12-18 18:17:28 -05:00
bool bHasConflicts ;
2014-12-17 19:27:27 -05:00
} ;
struct FMergeGraphEntry
{
FName GraphName ;
TArray < FMergeGraphRowEntry > Changes ;
bool bAnyConflics ;
bool bRemoteDifferences ;
bool bLocalDifferences ;
bool bExistsInRemote ;
bool bExistsInBase ;
bool bExistsInLocal ;
} ;
static TArray < FMergeGraphEntry > GenerateDiffListItems ( const FBlueprintRevPair & RemoteBlueprint , const FBlueprintRevPair & BaseBlueprint , const FBlueprintRevPair & LocalBlueprint )
2014-08-05 17:41:57 -04:00
{
// Index all the graphs by name, we use the name of the graph as the
// basis of comparison between the various versions of the blueprint.
2014-10-27 19:34:03 -04:00
TMap < FName , UEdGraph * > RemoteGraphMap , BaseGraphMap , LocalGraphMap ;
2014-08-05 17:41:57 -04:00
// We also want the set of all graph names in these blueprints, so that we
// can iterate over every graph.
2014-10-27 19:34:03 -04:00
TSet < FName > AllGraphNames ;
2014-08-05 17:41:57 -04:00
{
TArray < UEdGraph * > GraphsRemote , GraphsBase , GraphsLocal ;
RemoteBlueprint . Blueprint - > GetAllGraphs ( GraphsRemote ) ;
BaseBlueprint . Blueprint - > GetAllGraphs ( GraphsBase ) ;
LocalBlueprint . Blueprint - > GetAllGraphs ( GraphsLocal ) ;
2014-10-27 19:34:03 -04:00
const auto ToMap = [ & AllGraphNames ] ( const TArray < UEdGraph * > & InList , TMap < FName , UEdGraph * > & OutMap )
2014-08-05 17:41:57 -04:00
{
for ( auto Graph : InList )
{
2014-10-27 19:34:03 -04:00
OutMap . Add ( Graph - > GetFName ( ) , Graph ) ;
AllGraphNames . Add ( Graph - > GetFName ( ) ) ;
2014-08-05 17:41:57 -04:00
}
} ;
ToMap ( GraphsRemote , RemoteGraphMap ) ;
ToMap ( GraphsBase , BaseGraphMap ) ;
ToMap ( GraphsLocal , LocalGraphMap ) ;
}
2014-12-17 19:27:27 -05:00
TArray < FMergeGraphEntry > Ret ;
2014-08-05 17:41:57 -04:00
{
const auto GenerateDifferences = [ ] ( UEdGraph * GraphNew , UEdGraph * * GraphOld )
{
TArray < FDiffSingleResult > Results ;
2014-10-28 13:43:26 -04:00
FGraphDiffControl : : DiffGraphs ( GraphOld ? * GraphOld : nullptr , GraphNew , Results ) ;
2014-12-17 19:27:27 -05:00
struct SortDiff
{
bool operator ( ) ( const FDiffResultItem & A , const FDiffResultItem & B ) const
{
return A . Result . Diff < B . Result . Diff ;
}
} ;
Sort ( Results . GetData ( ) , Results . Num ( ) , SortDiff ( ) ) ;
2014-08-05 17:41:57 -04:00
return Results ;
} ;
for ( const auto & GraphName : AllGraphNames )
{
TArray < FDiffSingleResult > RemoteDifferences ;
TArray < FDiffSingleResult > LocalDifferences ;
bool bExistsInRemote , bExistsInBase , bExistsInLocal ;
2014-12-17 19:27:27 -05:00
FMergeGraphEntry GraphEntry ;
GraphEntry . GraphName = GraphName ;
2014-08-05 17:41:57 -04:00
{
UEdGraph * * RemoteGraph = RemoteGraphMap . Find ( GraphName ) ;
UEdGraph * * BaseGraph = BaseGraphMap . Find ( GraphName ) ;
UEdGraph * * LocalGraph = LocalGraphMap . Find ( GraphName ) ;
2014-12-17 19:27:27 -05:00
GraphEntry . bAnyConflics = false ;
GraphEntry . bExistsInRemote = RemoteGraph ! = nullptr ;
GraphEntry . bExistsInBase = BaseGraph ! = nullptr ;
GraphEntry . bExistsInLocal = LocalGraph ! = nullptr ;
2014-08-05 17:41:57 -04:00
if ( RemoteGraph )
{
RemoteDifferences = GenerateDifferences ( * RemoteGraph , BaseGraph ) ;
}
if ( LocalGraph )
{
LocalDifferences = GenerateDifferences ( * LocalGraph , BaseGraph ) ;
}
2014-10-23 13:16:13 -04:00
// 'join' the local differences and remote differences by noting changes
// that affected the same common base:
{
2014-12-17 19:27:27 -05:00
TMap < const FDiffSingleResult * , const FDiffSingleResult * > ConflictMap ;
2014-10-23 13:16:13 -04:00
for ( const auto & RemoteDifference : RemoteDifferences )
{
2014-10-27 19:34:03 -04:00
const FDiffSingleResult * ConflictingDifference = nullptr ;
2014-10-23 13:16:13 -04:00
for ( const auto & LocalDifference : LocalDifferences )
{
2014-12-17 19:27:27 -05:00
if ( RemoteDifference . Node1 = = LocalDifference . Node1 )
2014-10-23 13:16:13 -04:00
{
2014-12-17 19:27:27 -05:00
if ( RemoteDifference . Diff = = EDiffType : : NODE_REMOVED | |
2014-10-27 19:34:03 -04:00
LocalDifference . Diff = = EDiffType : : NODE_REMOVED | |
2014-12-17 19:27:27 -05:00
RemoteDifference . Pin1 = = LocalDifference . Pin1 )
2014-10-27 19:34:03 -04:00
{
ConflictingDifference = & LocalDifference ;
break ;
}
2014-10-23 13:16:13 -04:00
}
2014-12-17 19:27:27 -05:00
else if ( RemoteDifference . Pin1 ! = nullptr & & ( RemoteDifference . Pin1 = = LocalDifference . Pin1 ) )
2014-10-28 13:43:26 -04:00
{
// it's possible the users made the same change to the same pin, but given the wide
// variety of changes that can be made to a pin it is difficult to identify the change
// as identical, for now I'm just flagging all changes to the same pin as a conflict:
ConflictingDifference = & LocalDifference ;
break ;
}
2014-10-23 13:16:13 -04:00
}
2014-10-27 19:34:03 -04:00
if ( ConflictingDifference ! = nullptr )
2014-10-23 13:16:13 -04:00
{
// For now, we don't want to create a hard conflict for changes that don't effect runtime behavior:
if ( RemoteDifference . Diff = = EDiffType : : NODE_MOVED | |
RemoteDifference . Diff = = EDiffType : : NODE_COMMENT )
{
continue ;
}
2014-10-27 19:34:03 -04:00
2014-12-18 18:17:28 -05:00
ConflictMap . Add ( & RemoteDifference , ConflictingDifference ) ;
ConflictMap . Add ( ConflictingDifference , & RemoteDifference ) ;
2014-10-23 13:16:13 -04:00
}
}
2014-12-17 19:27:27 -05:00
for ( const auto & Difference : RemoteDifferences )
{
FText Label ;
const FDiffSingleResult * * ConflictingDifference = ConflictMap . Find ( & Difference ) ;
if ( ConflictingDifference )
{
2015-01-07 09:52:40 -05:00
Label = FText : : Format ( NSLOCTEXT ( " SMergeGraphView " , " ConflictIdentifier " , " CONFLICT: {0} conflicts with {1} " ) , ( * ConflictingDifference ) - > DisplayString , Difference . DisplayString ) ;
2014-12-17 19:27:27 -05:00
}
else
{
2015-01-07 09:52:40 -05:00
Label = Difference . DisplayString ;
2014-12-17 19:27:27 -05:00
}
FMergeGraphRowEntry NewEntry = {
Label
, Difference . OwningGraph
, ConflictingDifference ? ( * ConflictingDifference ) - > Node2 : nullptr /*UEdGraphNode* LocalNode*/
, Difference . Node1 /*UEdGraphNode* BaseNode*/
, Difference . Node2 /*UEdGraphNode* RemoteNode*/
, ConflictingDifference ? ( * ConflictingDifference ) - > Pin2 : nullptr /*UEdGraphPin* LocalPin*/
, Difference . Pin1 /*UEdGraphPin* BasePin*/
, Difference . Pin2 /*UEdGraphPin* RemotePin*/
, Difference . DisplayColor
2014-12-18 18:17:28 -05:00
, ConflictingDifference ? true : false
2014-12-17 19:27:27 -05:00
} ;
2014-12-18 18:17:28 -05:00
GraphEntry . bAnyConflics | = NewEntry . bHasConflicts ;
2014-12-17 19:27:27 -05:00
GraphEntry . Changes . Push ( NewEntry ) ;
}
for ( const auto & Difference : LocalDifferences )
{
FText Label ;
const FDiffSingleResult * * ConflictingDifference = ConflictMap . Find ( & Difference ) ;
if ( ! ConflictingDifference )
{
FMergeGraphRowEntry NewEntry = {
2015-01-07 09:52:40 -05:00
Difference . DisplayString
2014-12-17 19:27:27 -05:00
, Difference . OwningGraph
, Difference . Node2 /*UEdGraphNode* LocalNode*/
, Difference . Node1 /*UEdGraphNode* BaseNode*/
, nullptr
, Difference . Pin2 /*UEdGraphPin* LocalPin*/
, Difference . Pin1 /*UEdGraphPin* BasePin*/
, nullptr
, Difference . DisplayColor
2014-12-18 18:17:28 -05:00
, false
2014-12-17 19:27:27 -05:00
} ;
GraphEntry . Changes . Push ( NewEntry ) ;
}
}
GraphEntry . bLocalDifferences = LocalDifferences . Num ( ) ! = 0 ;
GraphEntry . bRemoteDifferences = RemoteDifferences . Num ( ) ! = 0 ;
2014-10-23 13:16:13 -04:00
}
2014-12-17 19:27:27 -05:00
Ret . Add ( GraphEntry ) ;
2014-10-28 13:43:26 -04:00
bExistsInRemote = RemoteGraph ! = nullptr ;
bExistsInBase = BaseGraph ! = nullptr ;
bExistsInLocal = LocalGraph ! = nullptr ;
2014-08-05 17:41:57 -04:00
}
}
}
return Ret ;
}
static void LockViews ( TArray < FDiffPanel > & Views , bool bAreLocked )
{
for ( auto & Panel : Views )
{
auto GraphEditor = Panel . GraphEditor . Pin ( ) ;
if ( GraphEditor . IsValid ( ) )
{
// lock this panel to ever other panel:
for ( auto & OtherPanel : Views )
{
auto OtherGraphEditor = OtherPanel . GraphEditor . Pin ( ) ;
if ( OtherGraphEditor . IsValid ( ) & &
OtherGraphEditor ! = GraphEditor )
{
if ( bAreLocked )
{
GraphEditor - > LockToGraphEditor ( OtherGraphEditor ) ;
}
else
{
GraphEditor - > UnlockFromGraphEditor ( OtherGraphEditor ) ;
}
}
}
}
}
}
FDiffPanel & GetDiffPanelForNode ( const UEdGraphNode & Node , TArray < FDiffPanel > & Panels )
{
for ( auto & Panel : Panels )
{
auto GraphEditor = Panel . GraphEditor . Pin ( ) ;
if ( GraphEditor . IsValid ( ) )
{
if ( Node . GetGraph ( ) = = GraphEditor - > GetCurrentGraph ( ) )
{
return Panel ;
}
}
}
checkf ( false , TEXT ( " Looking for node %s but it cannot be found in provided panels " ) , * Node . GetName ( ) ) ;
static FDiffPanel Default ;
return Default ;
}
2014-12-17 19:27:27 -05:00
void SMergeGraphView : : Construct ( const FArguments InArgs
, const FBlueprintMergeData & InData
, FOnMergeNodeSelected SelectionCallback
, TArray < TSharedPtr < FBlueprintDifferenceTreeEntry > > & OutTreeEntries
, TArray < TSharedPtr < FBlueprintDifferenceTreeEntry > > & OutRealDifferences
, TArray < TSharedPtr < FBlueprintDifferenceTreeEntry > > & OutConflicts
)
2014-08-05 17:41:57 -04:00
{
2014-11-24 18:59:49 -05:00
const TSharedRef < SDockTab > MajorTab = SNew ( SDockTab )
. TabRole ( ETabRole : : MajorTab ) ;
TabManager = FGlobalTabmanager : : Get ( ) - > NewTabManager ( MajorTab ) ;
TabManager - > RegisterTabSpawner ( MergeGraphTabId ,
FOnSpawnTab : : CreateRaw ( this , & SMergeGraphView : : CreateGraphDiffViews ) )
. SetDisplayName ( LOCTEXT ( " MergeGraphsTabTitle " , " Graphs " ) )
. SetTooltipText ( LOCTEXT ( " MergeGraphsTooltipText " , " Differences in the various graphs present in the blueprint " ) ) ;
TabManager - > RegisterTabSpawner ( MergeMyBluerpintTabId ,
FOnSpawnTab : : CreateRaw ( this , & SMergeGraphView : : CreateMyBlueprintsViews ) )
. SetDisplayName ( LOCTEXT ( " MergeMyBlueprintTabTitle " , " My Blueprint " ) )
. SetTooltipText ( LOCTEXT ( " MergeMyBlueprintTooltipText " , " Differences in the 'My Blueprints' attributes of the blueprint " ) ) ;
2014-08-05 17:41:57 -04:00
Data = InData ;
bViewsAreLocked = true ;
2014-12-17 19:27:27 -05:00
2014-08-05 17:41:57 -04:00
TArray < FBlueprintRevPair > BlueprintsForDisplay ;
2014-11-24 18:59:49 -05:00
// EMergeParticipant::Remote
2014-08-15 17:19:11 -04:00
BlueprintsForDisplay . Add ( FBlueprintRevPair ( InData . BlueprintRemote , InData . RevisionRemote ) ) ;
2014-11-24 18:59:49 -05:00
// EMergeParticipant::Base
2014-08-05 17:41:57 -04:00
BlueprintsForDisplay . Add ( FBlueprintRevPair ( InData . BlueprintBase , InData . RevisionBase ) ) ;
2014-11-24 18:59:49 -05:00
// EMergeParticipant::Local
2014-08-05 17:41:57 -04:00
BlueprintsForDisplay . Add ( FBlueprintRevPair ( InData . BlueprintLocal , FRevisionInfo ( ) ) ) ;
2014-11-24 18:59:49 -05:00
const TSharedRef < FTabManager : : FLayout > DefaultLayout = FTabManager : : NewLayout ( " BlueprintMerge_Layout_v1 " )
- > AddArea
(
FTabManager : : NewPrimaryArea ( )
- > Split
(
FTabManager : : NewStack ( )
- > AddTab ( MergeMyBluerpintTabId , ETabState : : OpenedTab )
- > AddTab ( MergeGraphTabId , ETabState : : OpenedTab )
)
) ;
2014-08-05 17:41:57 -04:00
2014-11-24 18:59:49 -05:00
for ( int32 i = 0 ; i < EMergeParticipant : : Max_None ; + + i )
2014-08-05 17:41:57 -04:00
{
2014-11-24 18:59:49 -05:00
DiffPanels . Add ( FDiffPanel ( ) ) ;
FDiffPanel & NewPanel = DiffPanels [ i ] ;
NewPanel . Blueprint = BlueprintsForDisplay [ i ] . Blueprint ;
NewPanel . RevisionInfo = BlueprintsForDisplay [ i ] . RevData ;
NewPanel . bShowAssetName = false ;
2014-08-05 17:41:57 -04:00
}
2014-11-24 18:59:49 -05:00
auto GraphPanelContainer = TabManager - > RestoreFrom ( DefaultLayout , TSharedPtr < SWindow > ( ) ) . ToSharedRef ( ) ;
for ( auto & Panel : DiffPanels )
2014-08-05 17:41:57 -04:00
{
2014-11-24 18:59:49 -05:00
Panel . InitializeDiffPanel ( ) ;
2014-08-05 17:41:57 -04:00
}
2014-11-24 18:59:49 -05:00
auto DetailsPanelContainer = SNew ( SSplitter ) ;
for ( auto & Panel : DiffPanels )
{
DetailsPanelContainer - > AddSlot ( )
[
Panel . DetailsView . ToSharedRef ( )
] ;
}
2014-12-17 19:27:27 -05:00
Differences = TSharedPtr < TArray < FMergeGraphEntry > > ( new TArray < FMergeGraphEntry > (
GenerateDiffListItems ( BlueprintsForDisplay [ EMergeParticipant : : Remote ]
, BlueprintsForDisplay [ EMergeParticipant : : Base ]
, BlueprintsForDisplay [ EMergeParticipant : : Local ] ) ) ) ;
2014-08-05 17:41:57 -04:00
2014-12-17 19:27:27 -05:00
for ( const auto & Difference : * Differences )
2014-08-05 17:41:57 -04:00
{
2014-12-17 19:27:27 -05:00
TArray < TSharedPtr < FBlueprintDifferenceTreeEntry > > Children ;
for ( const auto & Change : Difference . Changes )
2014-08-05 17:41:57 -04:00
{
2014-12-17 19:27:27 -05:00
const auto ChangeWidget = [ ] ( FText Label , FLinearColor Color ) - > TSharedRef < SWidget >
2014-08-05 17:41:57 -04:00
{
2014-12-17 19:27:27 -05:00
return SNew ( STextBlock )
. Text ( Label )
. ColorAndOpacity ( Color ) ;
} ;
2015-03-03 12:30:55 -05:00
const auto SelectGraphNode = [ ] ( FOnMergeNodeSelected InSelectionCallback , FMergeGraphRowEntry DiffEntry , SMergeGraphView * Parent )
2014-08-05 17:41:57 -04:00
{
2015-03-03 12:30:55 -05:00
InSelectionCallback . ExecuteIfBound ( ) ;
2014-12-17 19:27:27 -05:00
Parent - > HighlightEntry ( DiffEntry ) ;
} ;
TSharedPtr < FBlueprintDifferenceTreeEntry > Entry = TSharedPtr < FBlueprintDifferenceTreeEntry > ( new FBlueprintDifferenceTreeEntry (
FOnDiffEntryFocused : : CreateStatic ( SelectGraphNode , SelectionCallback , Change , this )
, FGenerateDiffEntryWidget : : CreateStatic ( ChangeWidget , Change . Label , Change . DisplayColor )
, TArray < TSharedPtr < FBlueprintDifferenceTreeEntry > > ( )
) ) ;
Children . Push ( Entry ) ;
OutRealDifferences . Push ( Entry ) ;
if ( Change . LocalNode & & Change . RemoteNode )
{
OutConflicts . Push ( Entry ) ;
2014-08-05 17:41:57 -04:00
}
2014-12-17 19:27:27 -05:00
}
2014-08-05 17:41:57 -04:00
2015-03-03 12:30:55 -05:00
const auto Widget = [ ] ( const FMergeGraphEntry * InDifference ) - > TSharedRef < SWidget >
2014-08-05 17:41:57 -04:00
{
2014-12-17 19:27:27 -05:00
// blue indicates added, red indicates changed, yellow indicates removed, white indicates no change:
const auto ComputeColor = [ ] ( const bool bAnyConflicts , const bool bAnyDifferences ) - > FLinearColor
{
if ( bAnyConflicts )
{
return DiffViewUtils : : Conflicting ( ) ;
}
else if ( bAnyDifferences )
{
return DiffViewUtils : : Differs ( ) ;
}
return DiffViewUtils : : Identical ( ) ;
} ;
2014-08-05 17:41:57 -04:00
2014-12-17 19:27:27 -05:00
const auto Box = [ ] ( bool bIsPresent , FLinearColor Color ) - > SHorizontalBox : : FSlot &
{
return SHorizontalBox : : Slot ( )
. AutoWidth ( )
. HAlign ( HAlign_Right )
. VAlign ( VAlign_Center )
. MaxWidth ( 8.0f )
[
SNew ( SImage )
. ColorAndOpacity ( Color )
. Image ( bIsPresent ? FEditorStyle : : GetBrush ( " BlueprintDif.HasGraph " ) : FEditorStyle : : GetBrush ( " BlueprintDif.MissingGraph " ) )
] ;
} ;
2015-03-03 12:30:55 -05:00
FLinearColor RemoteColor = ComputeColor ( InDifference - > bAnyConflics , InDifference - > bRemoteDifferences ) ;
FLinearColor BaseColor = ComputeColor ( InDifference - > bAnyConflics , false ) ;
FLinearColor LocalColor = ComputeColor ( InDifference - > bAnyConflics , InDifference - > bLocalDifferences ) ;
FLinearColor TextColor = ComputeColor ( InDifference - > bAnyConflics , InDifference - > bLocalDifferences | | InDifference - > bRemoteDifferences ) ;
2014-12-17 19:27:27 -05:00
return SNew ( SHorizontalBox )
2014-08-05 17:41:57 -04:00
+ SHorizontalBox : : Slot ( )
[
SNew ( STextBlock )
2014-12-17 19:27:27 -05:00
. ColorAndOpacity ( TextColor )
2015-03-03 12:30:55 -05:00
. Text ( FText : : FromString ( InDifference - > GraphName . GetPlainNameString ( ) ) )
2014-08-05 17:41:57 -04:00
]
2015-03-03 12:30:55 -05:00
+ DiffViewUtils : : Box ( InDifference - > bExistsInRemote , RemoteColor )
+ DiffViewUtils : : Box ( InDifference - > bExistsInBase , BaseColor )
+ DiffViewUtils : : Box ( InDifference - > bExistsInLocal , LocalColor ) ;
2014-12-17 19:27:27 -05:00
} ;
2014-08-05 17:41:57 -04:00
2015-03-03 12:30:55 -05:00
const auto FocusGraph = [ ] ( FOnMergeNodeSelected InSelectionCallback , SMergeGraphView * Parent , FName GraphName )
2014-12-17 19:27:27 -05:00
{
2015-03-03 12:30:55 -05:00
InSelectionCallback . ExecuteIfBound ( ) ;
2014-12-17 19:27:27 -05:00
Parent - > FocusGraph ( GraphName ) ;
} ;
if ( Children . Num ( ) = = 0 )
{
Children . Push ( FBlueprintDifferenceTreeEntry : : NoDifferencesEntry ( ) ) ;
}
OutTreeEntries . Push (
TSharedPtr < FBlueprintDifferenceTreeEntry > ( new FBlueprintDifferenceTreeEntry (
FOnDiffEntryFocused : : CreateStatic ( FocusGraph , SelectionCallback , this , Difference . GraphName )
, FGenerateDiffEntryWidget : : CreateStatic ( Widget , & Difference )
, Children
) )
) ;
}
2014-10-28 13:43:26 -04:00
2014-08-05 17:41:57 -04:00
ChildSlot
2014-12-17 19:27:27 -05:00
[
SNew ( SSplitter )
. Orientation ( Orient_Horizontal )
+ SSplitter : : Slot ( )
. Value ( 0.9f )
2014-08-05 17:41:57 -04:00
[
SNew ( SSplitter )
2014-12-17 19:27:27 -05:00
. Orientation ( Orient_Vertical )
2014-08-05 17:41:57 -04:00
+ SSplitter : : Slot ( )
2014-12-17 19:27:27 -05:00
. Value ( .8f )
2014-08-05 17:41:57 -04:00
[
2014-12-17 19:27:27 -05:00
GraphPanelContainer
2014-08-05 17:41:57 -04:00
]
+ SSplitter : : Slot ( )
2014-12-17 19:27:27 -05:00
. Value ( .2f )
[
DetailsPanelContainer
]
]
] ;
2014-08-05 17:41:57 -04:00
}
2014-12-17 19:27:27 -05:00
void SMergeGraphView : : FocusGraph ( FName GraphName )
2014-08-15 17:19:11 -04:00
{
2014-08-05 17:41:57 -04:00
UEdGraph * GraphRemote = FindGraphByName ( * GetRemotePanel ( ) . Blueprint , GraphName ) ;
UEdGraph * GraphBase = FindGraphByName ( * GetBasePanel ( ) . Blueprint , GraphName ) ;
UEdGraph * GraphLocal = FindGraphByName ( * GetLocalPanel ( ) . Blueprint , GraphName ) ;
2014-12-17 19:27:27 -05:00
GetBasePanel ( ) . GeneratePanel ( GraphBase , nullptr ) ;
GetRemotePanel ( ) . GeneratePanel ( GraphRemote , GraphBase ) ;
GetLocalPanel ( ) . GeneratePanel ( GraphLocal , GraphBase ) ;
2014-08-05 17:41:57 -04:00
LockViews ( DiffPanels , bViewsAreLocked ) ;
}
2014-12-17 19:27:27 -05:00
void SMergeGraphView : : HighlightEntry ( const struct FMergeGraphRowEntry & Conflict )
2014-08-05 17:41:57 -04:00
{
2014-12-17 19:27:27 -05:00
FocusGraph ( Conflict . GraphName ) ;
2014-08-05 17:41:57 -04:00
2014-12-17 19:27:27 -05:00
const auto FocusPinOrNode = [ this ] ( UEdGraphPin * Pin , UEdGraphNode * Node )
2014-08-05 17:41:57 -04:00
{
2014-12-17 19:27:27 -05:00
if ( Pin )
2014-08-05 17:41:57 -04:00
{
2014-12-17 19:27:27 -05:00
// then look for the diff panel and focus on the change:
GetDiffPanelForNode ( * Pin - > GetOwningNode ( ) , DiffPanels ) . FocusDiff ( * Pin ) ;
2014-08-05 17:41:57 -04:00
}
2014-12-17 19:27:27 -05:00
else if ( Node )
2014-08-05 17:41:57 -04:00
{
2014-12-17 19:27:27 -05:00
GetDiffPanelForNode ( * Node , DiffPanels ) . FocusDiff ( * Node ) ;
2014-08-05 17:41:57 -04:00
}
2014-12-17 19:27:27 -05:00
} ;
2014-08-05 17:41:57 -04:00
2014-12-17 19:27:27 -05:00
// highlight the change made to the remote graph:
FocusPinOrNode ( Conflict . RemotePin , Conflict . RemoteNode ) ;
FocusPinOrNode ( Conflict . LocalPin , Conflict . LocalNode ) ;
FocusPinOrNode ( Conflict . BasePin , Conflict . BaseNode ) ;
2014-08-05 17:41:57 -04:00
}
2014-11-24 18:59:49 -05:00
TSharedRef < SDockTab > SMergeGraphView : : CreateGraphDiffViews ( const FSpawnTabArgs & Args )
{
auto PanelContainer = SNew ( SSplitter ) ;
for ( auto & Panel : DiffPanels )
{
PanelContainer - > AddSlot ( )
[
SAssignNew ( Panel . GraphEditorBorder , SBox )
. VAlign ( VAlign_Fill )
[
SBlueprintDiff : : DefaultEmptyPanel ( )
]
] ;
}
return SNew ( SDockTab )
[
PanelContainer
] ;
}
TSharedRef < SDockTab > SMergeGraphView : : CreateMyBlueprintsViews ( const FSpawnTabArgs & Args )
{
auto PanelContainer = SNew ( SSplitter ) ;
for ( auto & Panel : DiffPanels )
{
PanelContainer - > AddSlot ( )
[
Panel . GenerateMyBlueprintPanel ( )
] ;
}
return SNew ( SDockTab )
[
PanelContainer
] ;
}
2014-08-05 17:41:57 -04:00
FReply SMergeGraphView : : OnToggleLockView ( )
{
bViewsAreLocked = ! bViewsAreLocked ;
LockViews ( DiffPanels , bViewsAreLocked ) ;
return FReply : : Handled ( ) ;
}
const FSlateBrush * SMergeGraphView : : GetLockViewImage ( ) const
{
return bViewsAreLocked ? FEditorStyle : : GetBrush ( " GenericLock " ) : FEditorStyle : : GetBrush ( " GenericUnlock " ) ;
}
2014-09-08 15:22:04 -04:00
# undef LOCTEXT_NAMESPACE