2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-08-05 09:04:35 -04:00
# include "IntroTutorialsPrivatePCH.h"
# include "STutorialOverlay.h"
# include "STutorialContent.h"
# include "EditorTutorial.h"
# include "IntroTutorials.h"
2014-08-28 09:58:30 -04:00
# include "Kismet2/KismetEditorUtilities.h"
2014-08-14 07:02:50 -04:00
# include "LevelEditor.h"
2014-08-28 09:38:24 -04:00
# include "BlueprintEditorUtils.h"
# include "Guid.h"
2014-10-20 08:15:36 -04:00
# include "BlueprintEditor.h"
2014-08-05 09:04:35 -04:00
2014-09-18 09:27:57 -04:00
static FName IntroTutorialsModuleName ( " IntroTutorials " ) ;
2014-09-16 10:26:36 -04:00
void STutorialOverlay : : Construct ( const FArguments & InArgs , UEditorTutorial * InTutorial , FTutorialStage * const InStage )
2014-08-05 09:04:35 -04:00
{
ParentWindow = InArgs . _ParentWindow ;
bIsStandalone = InArgs . _IsStandalone ;
OnClosed = InArgs . _OnClosed ;
2014-09-18 09:27:57 -04:00
bHasValidContent = InStage ! = nullptr ;
2014-09-22 09:42:52 -04:00
OnWidgetWasDrawn = InArgs . _OnWidgetWasDrawn ;
2014-09-18 09:27:57 -04:00
2014-08-05 09:04:35 -04:00
TSharedPtr < SOverlay > Overlay ;
ChildSlot
[
SAssignNew ( Overlay , SOverlay )
+ SOverlay : : Slot ( )
[
SAssignNew ( OverlayCanvas , SCanvas )
]
] ;
if ( InStage ! = nullptr )
{
// add non-widget content, if any
if ( InArgs . _AllowNonWidgetContent & & InStage - > Content . Type ! = ETutorialContent : : None )
{
Overlay - > AddSlot ( )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
. HAlign ( HAlign_Center )
[
2014-09-16 10:26:36 -04:00
SNew ( STutorialContent , InTutorial , InStage - > Content )
2014-08-05 09:04:35 -04:00
. OnClosed ( InArgs . _OnClosed )
2014-09-16 10:26:36 -04:00
. OnNextClicked ( InArgs . _OnNextClicked )
. OnHomeClicked ( InArgs . _OnHomeClicked )
. OnBackClicked ( InArgs . _OnBackClicked )
. IsBackEnabled ( InArgs . _IsBackEnabled )
. IsHomeEnabled ( InArgs . _IsHomeEnabled )
. IsNextEnabled ( InArgs . _IsNextEnabled )
2014-08-05 09:04:35 -04:00
. IsStandalone ( InArgs . _IsStandalone )
. WrapTextAt ( 600.0f )
]
] ;
}
if ( InStage - > WidgetContent . Num ( ) > 0 )
{
FIntroTutorials & IntroTutorials = FModuleManager : : Get ( ) . GetModuleChecked < FIntroTutorials > ( " IntroTutorials " ) ;
// now add canvas slots for widget-bound content
2014-08-28 09:38:24 -04:00
for ( const FTutorialWidgetContent & WidgetContent : InStage - > WidgetContent )
2014-08-05 09:04:35 -04:00
{
2014-08-28 09:38:24 -04:00
if ( WidgetContent . Content . Type ! = ETutorialContent : : None )
2014-08-05 09:04:35 -04:00
{
2014-08-28 09:38:24 -04:00
TSharedPtr < STutorialContent > ContentWidget =
2014-09-16 10:26:36 -04:00
SNew ( STutorialContent , InTutorial , WidgetContent . Content )
2014-08-28 09:38:24 -04:00
. HAlign ( WidgetContent . HorizontalAlignment )
. VAlign ( WidgetContent . VerticalAlignment )
. Offset ( WidgetContent . Offset )
. IsStandalone ( bIsStandalone )
2014-09-18 08:10:29 -04:00
. OnClosed ( InArgs . _OnClosed )
2014-09-16 10:26:36 -04:00
. OnNextClicked ( InArgs . _OnNextClicked )
. OnHomeClicked ( InArgs . _OnHomeClicked )
. OnBackClicked ( InArgs . _OnBackClicked )
. IsBackEnabled ( InArgs . _IsBackEnabled )
. IsHomeEnabled ( InArgs . _IsHomeEnabled )
. IsNextEnabled ( InArgs . _IsNextEnabled )
2014-08-28 09:38:24 -04:00
. WrapTextAt ( WidgetContent . ContentWidth )
2014-09-18 13:30:40 -04:00
. Anchor ( WidgetContent . WidgetAnchor )
2014-09-22 09:42:52 -04:00
. AllowNonWidgetContent ( InArgs . _AllowNonWidgetContent )
2014-09-30 11:37:26 -04:00
. OnWasWidgetDrawn ( InArgs . _OnWasWidgetDrawn )
. NextButtonText ( InStage - > NextButtonText ) ;
2014-08-28 09:38:24 -04:00
PerformWidgetInteractions ( WidgetContent ) ;
OverlayCanvas - > AddSlot ( )
2014-08-14 07:02:50 -04:00
. Position ( TAttribute < FVector2D > : : Create ( TAttribute < FVector2D > : : FGetter : : CreateSP ( ContentWidget . Get ( ) , & STutorialContent : : GetPosition ) ) )
. Size ( TAttribute < FVector2D > : : Create ( TAttribute < FVector2D > : : FGetter : : CreateSP ( ContentWidget . Get ( ) , & STutorialContent : : GetSize ) ) )
[
ContentWidget . ToSharedRef ( )
] ;
2014-08-05 09:04:35 -04:00
2014-08-28 09:38:24 -04:00
OnPaintNamedWidget . AddSP ( ContentWidget . Get ( ) , & STutorialContent : : HandlePaintNamedWidget ) ;
OnResetNamedWidget . AddSP ( ContentWidget . Get ( ) , & STutorialContent : : HandleResetNamedWidget ) ;
OnCacheWindowSize . AddSP ( ContentWidget . Get ( ) , & STutorialContent : : HandleCacheWindowSize ) ;
2014-08-05 09:04:35 -04:00
}
}
}
}
}
int32 STutorialOverlay : : OnPaint ( const FPaintArgs & Args , const FGeometry & AllottedGeometry , const FSlateRect & MyClippingRect , FSlateWindowElementList & OutDrawElements , int32 LayerId , const FWidgetStyle & InWidgetStyle , bool bParentEnabled ) const
{
if ( ParentWindow . IsValid ( ) )
{
2014-09-18 09:27:57 -04:00
bool bIsPicking = false ;
FName WidgetNameToHighlight = NAME_None ;
FIntroTutorials & IntroTutorials = FModuleManager : : Get ( ) . GetModuleChecked < FIntroTutorials > ( IntroTutorialsModuleName ) ;
if ( IntroTutorials . OnIsPicking ( ) . IsBound ( ) )
{
bIsPicking = IntroTutorials . OnIsPicking ( ) . Execute ( WidgetNameToHighlight ) ;
}
if ( bIsPicking | | bHasValidContent )
{
TSharedPtr < SWindow > PinnedWindow = ParentWindow . Pin ( ) ;
OnResetNamedWidget . Broadcast ( ) ;
OnCacheWindowSize . Broadcast ( PinnedWindow - > GetWindowGeometryInWindow ( ) . Size ) ;
LayerId = TraverseWidgets ( PinnedWindow . ToSharedRef ( ) , PinnedWindow - > GetWindowGeometryInWindow ( ) , MyClippingRect , OutDrawElements , LayerId ) ;
}
2014-08-05 09:04:35 -04:00
}
return SCompoundWidget : : OnPaint ( Args , AllottedGeometry , MyClippingRect , OutDrawElements , LayerId , InWidgetStyle , bParentEnabled ) ;
}
int32 STutorialOverlay : : TraverseWidgets ( TSharedRef < SWidget > InWidget , const FGeometry & InGeometry , const FSlateRect & MyClippingRect , FSlateWindowElementList & OutDrawElements , int32 LayerId ) const
{
2014-10-20 08:15:36 -04:00
bool bIsPicking = false ;
bool bShouldHighlight = false ;
bool bShouldDraw = false ;
FName WidgetNameToHighlight = NAME_None ;
FIntroTutorials & IntroTutorials = FModuleManager : : Get ( ) . GetModuleChecked < FIntroTutorials > ( IntroTutorialsModuleName ) ;
if ( IntroTutorials . OnValidatePickingCandidate ( ) . IsBound ( ) )
{
bIsPicking = IntroTutorials . OnValidatePickingCandidate ( ) . Execute ( InWidget , WidgetNameToHighlight , bShouldHighlight ) ;
}
// First draw the widget if we should
2014-08-28 04:32:19 -04:00
TSharedPtr < FTagMetaData > MetaData = InWidget - > GetMetaData < FTagMetaData > ( ) ;
2014-10-20 08:15:36 -04:00
const FName Tag = ( MetaData . IsValid ( ) & & MetaData - > Tag . IsValid ( ) ) ? MetaData - > Tag : InWidget - > GetTag ( ) ;
if ( Tag ! = NAME_None | | MetaData . IsValid ( ) )
2014-08-05 09:04:35 -04:00
{
// we are a named widget - ask it to draw
OnPaintNamedWidget . Broadcast ( InWidget , InGeometry ) ;
2014-09-22 09:42:52 -04:00
OnWidgetWasDrawn . ExecuteIfBound ( Tag ) ;
2014-10-20 08:15:36 -04:00
}
2014-08-05 09:04:35 -04:00
2014-10-20 08:15:36 -04:00
// Next check and draw the highlight as appropriate
if ( bIsPicking = = true )
{
// if we are picking, we need to draw an outline here
if ( WidgetNameToHighlight ! = NAME_None )
2014-08-05 09:04:35 -04:00
{
2014-10-20 08:15:36 -04:00
if ( bIsPicking = = true )
2014-08-05 09:04:35 -04:00
{
2014-10-20 08:15:36 -04:00
const FLinearColor Color = bIsPicking & & bShouldHighlight ? FLinearColor : : Green : FLinearColor : : White ;
2014-08-05 09:04:35 -04:00
FSlateDrawElement : : MakeBox ( OutDrawElements , LayerId + + , InGeometry . ToPaintGeometry ( ) , FCoreStyle : : Get ( ) . GetBrush ( TEXT ( " Debug.Border " ) ) , MyClippingRect , ESlateDrawEffect : : None , Color ) ;
}
}
}
FArrangedChildren ArrangedChildren ( EVisibility : : Visible ) ;
InWidget - > ArrangeChildren ( InGeometry , ArrangedChildren ) ;
for ( int32 ChildIndex = 0 ; ChildIndex < ArrangedChildren . Num ( ) ; ChildIndex + + )
{
2014-08-25 12:51:49 -04:00
const FArrangedWidget & ArrangedWidget = ArrangedChildren [ ChildIndex ] ;
2014-08-05 09:04:35 -04:00
LayerId = TraverseWidgets ( ArrangedWidget . Widget , ArrangedWidget . Geometry , MyClippingRect , OutDrawElements , LayerId ) ;
}
return LayerId ;
2014-08-13 03:41:45 -04:00
}
2014-08-28 09:38:24 -04:00
void STutorialOverlay : : PerformWidgetInteractions ( const FTutorialWidgetContent & WidgetContent )
{
// Open any browser we need too
OpenBrowserForWidgetAnchor ( WidgetContent ) ;
FocusOnAnyBlueprintNodes ( WidgetContent ) ;
}
2014-08-13 03:41:45 -04:00
void STutorialOverlay : : OpenBrowserForWidgetAnchor ( const FTutorialWidgetContent & WidgetContent )
{
2014-10-20 08:15:36 -04:00
//bool bTabOpened = false;
TSharedPtr < FTabManager > TabManager ;
TArray < FString > AssetPaths ;
FString Name ;
// Try looking for the object via the ID first
Name = WidgetContent . WidgetAnchor . WrapperIdentifier . ToString ( ) ;
AssetPaths . Add ( Name ) ;
// Opening the editor will force the object to be loaded if it exists
FAssetEditorManager : : Get ( ) . OpenEditorsForAssets ( AssetPaths ) ;
UObject * AssetObject = FindObject < UObject > ( ANY_PACKAGE , * Name ) ;
IAssetEditorInstance * AssetEditor = FAssetEditorManager : : Get ( ) . FindEditorForAsset ( AssetObject , false ) ;
// If we now have a valid asset editor get its tabmanager - we will use this to open/focus a tab if there is one
if ( AssetEditor ! = nullptr )
2014-08-13 03:41:45 -04:00
{
2014-10-20 08:15:36 -04:00
FAssetEditorToolkit * ToolkitEditor = static_cast < FAssetEditorToolkit * > ( FAssetEditorManager : : Get ( ) . FindEditorForAsset ( AssetObject , false ) ) ;
if ( ( ToolkitEditor ! = nullptr ) & & ( WidgetContent . WidgetAnchor . TabToFocusOrOpen . IsEmpty ( ) = = false ) )
{
TabManager = ToolkitEditor - > GetTabManager ( ) ;
}
2014-09-11 08:13:08 -04:00
}
2014-10-20 08:15:36 -04:00
// If we don't have a valid tab manager we should now check to see if we can find a blueprint relevant to this node and open the editor for that (Then try to get the tabmanager from that)
if ( TabManager . IsValid ( ) = = false )
2014-09-11 08:13:08 -04:00
{
2014-10-20 08:15:36 -04:00
// Remove the prefix from the name
AssetPaths . Empty ( ) ;
int32 Space = WidgetContent . WidgetAnchor . OuterName . Find ( TEXT ( " " ) ) ;
Name = WidgetContent . WidgetAnchor . OuterName . RightChop ( Space + 1 ) ;
AssetPaths . Add ( Name ) ;
FAssetEditorManager : : Get ( ) . OpenEditorsForAssets ( AssetPaths ) ;
UObject * Blueprint = FindObject < UObject > ( ANY_PACKAGE , * Name ) ;
// If we found a blueprint
if ( Blueprint ! = nullptr )
{
IBlueprintEditor * BlueprintEditor = ( FBlueprintEditor * ) FAssetEditorManager : : Get ( ) . FindEditorForAsset ( Blueprint , false ) ;
if ( ( BlueprintEditor ! = nullptr ) & & ( WidgetContent . WidgetAnchor . TabToFocusOrOpen . IsEmpty ( ) = = false ) )
{
TabManager = BlueprintEditor - > GetTabManager ( ) ;
}
}
}
// Invoke any tab
if ( WidgetContent . WidgetAnchor . TabToFocusOrOpen . IsEmpty ( ) = = false )
{
if ( TabManager . IsValid ( ) = = true )
{
TSharedRef < SDockTab > IT = TabManager - > InvokeTab ( FTabId ( * WidgetContent . WidgetAnchor . TabToFocusOrOpen ) ) ;
}
else
{
FLevelEditorModule & LevelEditorModule = FModuleManager : : GetModuleChecked < FLevelEditorModule > ( TEXT ( " LevelEditor " ) ) ;
TSharedPtr < FTabManager > LevelEditorTabManager = LevelEditorModule . GetLevelEditorTabManager ( ) ;
LevelEditorTabManager - > InvokeTab ( FName ( * WidgetContent . WidgetAnchor . TabToFocusOrOpen ) ) ;
}
2014-08-13 03:41:45 -04:00
}
}
2014-08-28 09:38:24 -04:00
void STutorialOverlay : : FocusOnAnyBlueprintNodes ( const FTutorialWidgetContent & WidgetContent )
{
if ( WidgetContent . bAutoFocus = = false )
{
return ;
}
2014-09-03 08:26:29 -04:00
FString Name = WidgetContent . WidgetAnchor . OuterName ;
int32 NameIndex ;
Name . FindLastChar ( TEXT ( ' . ' ) , NameIndex ) ;
FString BlueprintName = Name . RightChop ( NameIndex + 1 ) ;
UBlueprint * Blueprint = FindObject < UBlueprint > ( ANY_PACKAGE , * BlueprintName ) ;
// If we find a blueprint
if ( Blueprint ! = nullptr )
2014-08-28 09:38:24 -04:00
{
2014-09-03 08:26:29 -04:00
// Try to grab guid
FGuid NodeGuid ;
FGuid : : Parse ( WidgetContent . WidgetAnchor . GUIDString , NodeGuid ) ;
UEdGraphNode * OutNode = NULL ;
if ( UEdGraphNode * GraphNode = FBlueprintEditorUtils : : GetNodeByGUID ( Blueprint , NodeGuid ) )
2014-08-28 09:38:24 -04:00
{
2014-09-03 08:26:29 -04:00
FKismetEditorUtilities : : BringKismetToFocusAttentionOnObject ( GraphNode , false ) ;
2014-08-28 09:38:24 -04:00
}
}
}