// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. #include "IntroTutorialsPrivatePCH.h" #include "InteractiveTutorials.h" #include "InteractivityData.h" #include "K2Node_TutorialExcerptComplete.h" #include "Editor/LevelEditor/Public/LevelEditor.h" #include "Editor/UnrealEd/Public/Toolkits/AssetEditorManager.h" #include "Editor/PlacementMode/Public/IPlacementModeModule.h" #include "Editor/ContentBrowser/Public/ContentBrowserModule.h" #include "Editor.h" #define LOCTEXT_NAMESPACE "IntroTutorials" FInteractiveTutorials::FInteractiveTutorials(FSimpleDelegate SectionCompleted) : ExcerptConditionsCompleted(SectionCompleted) { } void FInteractiveTutorials::SetupEditorHooks() { // Set up editor wide hooks first FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked( "LevelEditor" ); LevelEditorModule.OnActorSelectionChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); USelection::SelectionChangedEvent.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); USelection::SelectObjectEvent.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FCoreDelegates::OnObjectPropertyChanged.AddSP( this, &FInteractiveTutorials::OnDelegateTriggered ); FAssetEditorManager::Get().OnAssetEditorRequestedOpen().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); GLevelEditorModeTools().OnEditorModeChanged().AddSP( this, &FInteractiveTutorials::OnDelegateTriggered ); GLevelEditorModeTools().OnWidgetModeChanged().AddSP( this, &FInteractiveTutorials::OnDelegateTriggered ); GEditor->OnEndObjectMovement().AddSP( this, &FInteractiveTutorials::OnDelegateTriggered ); FEditorDelegates::BeginPIE.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::EndPIE.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnConfigureNewAssetProperties.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnNewAssetCreated.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnFinishPickingBlueprintClass.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnNewActorsDropped.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnApplyObjectToActor.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnGridSnappingChanged.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnLightingBuildStarted.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnLightingBuildKept.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnFocusViewportOnActors.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnMapOpened.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnEditorCameraMoved.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FEditorDelegates::OnDollyPerspectiveCamera.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); FContentBrowserModule& ContentBrowserModule = FModuleManager::GetModuleChecked( TEXT("ContentBrowser") ); ContentBrowserModule.GetOnFilterChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); ContentBrowserModule.GetOnSearchBoxChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); ContentBrowserModule.GetOnAssetSelectionChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); ContentBrowserModule.GetOnSourcesViewChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); ContentBrowserModule.GetOnAssetPathChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); IPlacementModeModule::Get().OnStartedPlacing().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered); UK2Node_TutorialExcerptComplete::OnTutorialExcerptComplete.AddSP(this, &FInteractiveTutorials::CompleteExcerpt); // Hook us up to the tutorial system to allow us to highlight particular widgets STutorialWrapper::OnWidgetHighlight().BindSP(this, &FInteractiveTutorials::IsWidgetHighlighted); // Then make sure to collect all our actual tutorial data PopulateInteractivityData(SharedThis(this)); } void FInteractiveTutorials::BindInteractivityData(const FString& InUDNPath, FBindInteractivityData InBindInteractivityData) { FString UDNPath = InUDNPath; FPaths::NormalizeDirectoryName(UDNPath); TSharedRef Tutorial = MakeShareable(new FInteractiveTutorial()); Tutorials.Add(UDNPath, Tutorial); if(InBindInteractivityData.IsBound()) { InBindInteractivityData.Execute(UDNPath, Tutorial); } } void FInteractiveTutorials::SetCurrentTutorial(const FString& InUDNPath) { FString UDNPath = InUDNPath; FPaths::NormalizeDirectoryName(UDNPath); // do we have interactivity data for this tutorial? TSharedPtr* Tutorial = Tutorials.Find(UDNPath); if(Tutorial != NULL) { CurrentTutorial = *Tutorial; } else { CurrentTutorial = nullptr; } } ETutorialStyle::Type FInteractiveTutorials::GetCurrentTutorialStyle() { if(CurrentTutorial.IsValid()) { return CurrentTutorial->GetTutorialStyle(); } else { return ETutorialStyle::Default; } } void FInteractiveTutorials::SetCurrentExcerpt(const FString& NewExcerpt) { if(CurrentTutorial.IsValid()) { CurrentTutorial->SetCurrentExcerpt(NewExcerpt); } } bool FInteractiveTutorials::IsExcerptInteractive(const FString& ExcerptName) { if(CurrentTutorial.IsValid()) { return CurrentTutorial->IsExcerptInteractive(ExcerptName); } return false; } bool FInteractiveTutorials::CanManuallyAdvanceExcerpt(const FString& ExcerptName) { if (CurrentTutorial.IsValid()) { return CurrentTutorial->CanManuallyAdvanceExcerpt(ExcerptName); } // allow by default return true; } bool FInteractiveTutorials::CanManuallyReverseExcerpt(const FString& ExcerptName) { if (CurrentTutorial.IsValid()) { return CurrentTutorial->CanManuallyReverseExcerpt(ExcerptName); } // allow by default return true; } bool FInteractiveTutorials::ShouldSkipExcerpt(const FString& ExcerptName) { bool bShouldSkip = false; if(CurrentTutorial.IsValid()) { const FShouldSkipExcerptDelegate* SkipDelegate = CurrentTutorial->FindSkipDelegate(ExcerptName); if(SkipDelegate != NULL && SkipDelegate->IsBound()) { bShouldSkip = SkipDelegate->Execute(); if (bShouldSkip) { CurrentTutorial->OnExcerptCompleted(ExcerptName); } } } return bShouldSkip; } UDialogueWave* FInteractiveTutorials::GetDialogueForExcerpt(const FString& ExcerptName) { if(CurrentTutorial.IsValid()) { return CurrentTutorial->FindDialogueAudio(ExcerptName); } return NULL; } void FInteractiveTutorials::OnExcerptCompleted(const FString& ExcerptName) { if (CurrentTutorial.IsValid()) { return CurrentTutorial->OnExcerptCompleted(ExcerptName); } } void FInteractiveTutorials::CompleteExcerpt(const FString& InExcerpt) { if(CurrentTutorial.IsValid()) { if (InExcerpt == CurrentTutorial->GetCurrentExcerpt()) { ExcerptConditionsCompleted.ExecuteIfBound(); } } } bool FInteractiveTutorials::IsWidgetHighlighted(const FName& InWidgetName) const { if(CurrentTutorial.IsValid()) { return CurrentTutorial->IsWidgetHighlighted(InWidgetName); } return false; } template DelegateSignature FInteractiveTutorials::GetTriggerDelegate(FBaseTriggerDelegate::Type DelegateType) { if(CurrentTutorial.IsValid()) { TSharedPtr Trigger = CurrentTutorial->FindCurrentTrigger(); if (Trigger.IsValid() && Trigger->DelegateType == DelegateType) { return StaticCastSharedPtr>(Trigger)->Delegate; } } return DelegateSignature(); } void FInteractiveTutorials::ExecuteCompletion(bool bSuccessfulCompletion) { if (bSuccessfulCompletion) { ExcerptConditionsCompleted.ExecuteIfBound(); } } template void FInteractiveTutorials::OnDelegateTriggered() { auto Delegate = GetTriggerDelegate(DelegateEnumType); if (Delegate.IsBound()) { ExecuteCompletion(Delegate.Execute()); } } template void FInteractiveTutorials::OnDelegateTriggered(Param1Type Param1) { auto Delegate = GetTriggerDelegate(DelegateEnumType); if (Delegate.IsBound()) { ExecuteCompletion(Delegate.Execute(Param1)); } } template void FInteractiveTutorials::OnDelegateTriggered(Param1Type Param1, Param2Type Param2) { auto Delegate = GetTriggerDelegate(DelegateEnumType); if (Delegate.IsBound()) { ExecuteCompletion(Delegate.Execute(Param1, Param2)); } } template void FInteractiveTutorials::OnDelegateTriggered(Param1Type Param1, Param2Type Param2, Param3Type Param3, Param4Type Param4) { auto Delegate = GetTriggerDelegate(DelegateEnumType); if (Delegate.IsBound()) { ExecuteCompletion(Delegate.Execute(Param1, Param2, Param3, Param4)); } } #undef LOCTEXT_NAMESPACE