// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. #include "IntroTutorialsPrivatePCH.h" #include "STutorialRoot.h" #include "SEditorTutorials.h" #include "EditorTutorialSettings.h" #define LOCTEXT_NAMESPACE "STutorialRoot" void STutorialRoot::Construct(const FArguments& InArgs) { CurrentTutorial = nullptr; CurrentTutorialStage = 0; ChildSlot [ SNullWidget::NullWidget ]; } void STutorialRoot::MaybeAddOverlay(TSharedRef InWindow) { if(InWindow->HasOverlay()) { // check we dont already have a widget overlay for this window TWeakPtr* FoundWidget = TutorialWidgets.Find(InWindow); if(FoundWidget == nullptr) { TSharedPtr TutorialWidget = nullptr; InWindow->AddOverlaySlot() [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .VAlign(VAlign_Fill) .HAlign(HAlign_Fill) [ SAssignNew(TutorialWidget, SEditorTutorials) .ParentWindow(InWindow) .OnNextClicked(FOnNextClicked::CreateSP(this, &STutorialRoot::HandleNextClicked)) .OnBackClicked(FSimpleDelegate::CreateSP(this, &STutorialRoot::HandleBackClicked)) .OnHomeClicked(FSimpleDelegate::CreateSP(this, &STutorialRoot::HandleHomeClicked)) .OnGetCurrentTutorial(FOnGetCurrentTutorial::CreateSP(this, &STutorialRoot::HandleGetCurrentTutorial)) .OnGetCurrentTutorialStage(FOnGetCurrentTutorialStage::CreateSP(this, &STutorialRoot::HandleGetCurrentTutorialStage)) .OnLaunchTutorial(FOnLaunchTutorial::CreateSP(this, &STutorialRoot::LaunchTutorial)) ] ]; FoundWidget = &TutorialWidgets.Add(InWindow, TutorialWidget); FoundWidget->Pin()->RebuildCurrentContent(); } } TArray> ChildWindows = InWindow->GetChildWindows(); for(auto& ChildWindow : ChildWindows) { MaybeAddOverlay(ChildWindow); } } void STutorialRoot::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) { TArray> Windows = FSlateApplication::Get().GetInteractiveTopLevelWindows(); for(auto& Window : Windows) { MaybeAddOverlay(Window); } } void STutorialRoot::SummonTutorialBrowser(TSharedRef InWindow, const FString& InFilter) { TWeakPtr* FoundWidget = TutorialWidgets.Find(InWindow); if(FoundWidget != nullptr && FoundWidget->IsValid()) { FoundWidget->Pin()->ShowBrowser(InFilter); } } void STutorialRoot::LaunchTutorial(UEditorTutorial* InTutorial, bool bInRestart, TWeakPtr InNavigationWindow) { if(InTutorial != nullptr) { CurrentTutorial = InTutorial; bool bHaveSeenTutorial = false; CurrentTutorialStage = bInRestart ? 0 : GetDefault()->GetProgress(CurrentTutorial, bHaveSeenTutorial); // launch tutorial for all windows we wrap - any tutorial can display over any window for(auto& TutorialWidget : TutorialWidgets) { if(TutorialWidget.Value.IsValid()) { bool bIsNavigationWindow = InNavigationWindow.IsValid() && TutorialWidget.Value.Pin()->GetParentWindow() == InNavigationWindow.Pin(); TutorialWidget.Value.Pin()->LaunchTutorial(bIsNavigationWindow); } } } } void STutorialRoot::HandleNextClicked(TWeakPtr InNavigationWindow) { GoToNextStage(InNavigationWindow); for(auto& TutorialWidget : TutorialWidgets) { if(TutorialWidget.Value.IsValid()) { TSharedPtr PinnedTutorialWidget = TutorialWidget.Value.Pin(); PinnedTutorialWidget->RebuildCurrentContent(); } } } void STutorialRoot::HandleBackClicked() { GoToPreviousStage(); for(auto& TutorialWidget : TutorialWidgets) { if(TutorialWidget.Value.IsValid()) { TSharedPtr PinnedTutorialWidget = TutorialWidget.Value.Pin(); PinnedTutorialWidget->RebuildCurrentContent(); } } } void STutorialRoot::HandleHomeClicked() { if(CurrentTutorial != nullptr) { GetMutableDefault()->RecordProgress(CurrentTutorial, CurrentTutorialStage); GetMutableDefault()->SaveProgress(); } CurrentTutorial = nullptr; CurrentTutorialStage = 0; for(auto& TutorialWidget : TutorialWidgets) { if(TutorialWidget.Value.IsValid()) { TSharedPtr PinnedTutorialWidget = TutorialWidget.Value.Pin(); PinnedTutorialWidget->RebuildCurrentContent(); } } } UEditorTutorial* STutorialRoot::HandleGetCurrentTutorial() { return CurrentTutorial; } int32 STutorialRoot::HandleGetCurrentTutorialStage() { return CurrentTutorialStage; } void STutorialRoot::AddReferencedObjects( FReferenceCollector& Collector ) { if(CurrentTutorial != nullptr) { Collector.AddReferencedObject(CurrentTutorial); } } void STutorialRoot::GoToPreviousStage() { if(CurrentTutorial != nullptr) { CurrentTutorialStage = FMath::Max(0, CurrentTutorialStage - 1); } } void STutorialRoot::GoToNextStage(TWeakPtr InNavigationWindow) { if(CurrentTutorial != nullptr) { if(CurrentTutorialStage + 1 >= CurrentTutorial->Stages.Num() && FName(*CurrentTutorial->NextTutorial.AssetLongPathname) != NAME_None) { TSubclassOf NextTutorialClass = LoadClass(NULL, *CurrentTutorial->NextTutorial.AssetLongPathname, NULL, LOAD_None, NULL); if(NextTutorialClass != nullptr) { LaunchTutorial(NextTutorialClass->GetDefaultObject(), true, InNavigationWindow); } else { FSlateNotificationManager::Get().AddNotification(FNotificationInfo(FText::Format(LOCTEXT("TutorialNotFound", "Could not start next tutorial {0}"), FText::FromString(CurrentTutorial->NextTutorial.AssetLongPathname)))); } } else { CurrentTutorialStage = FMath::Min(CurrentTutorialStage + 1, CurrentTutorial->Stages.Num() - 1); GetMutableDefault()->RecordProgress(CurrentTutorial, CurrentTutorialStage); } } } #undef LOCTEXT_NAMESPACE