Files
UnrealEngineUWP/Engine/Source/Editor/IntroTutorials/Private/InteractiveTutorials.cpp

282 lines
11 KiB
C++
Raw Normal View History

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "IntroTutorialsPrivatePCH.h"
#include "InteractiveTutorials.h"
#include "InteractivityData.h"
#include "K2Node_TutorialExcerptComplete.h"
Merging UE4-Pretest @ 2042161 to UE4 Change 1996384 by Andrew Brown: 322252 - EDITOR: Asset picker displays incorrect text when there are no filter results. Change 1996385 by Andrew Brown: 321858 - CRASH: Assertion failed: (Index >= 0) Function: STransformViewportToolBar::GetLocationGridLabel() STextBlock::CacheDesiredSize() Change 1996977 by Andrew Brown: 309685 - UE4: Adding an event/renaming an event on an event track in Matinee does not update the MatineeActor node in blueprint Change 2034873 by Jaroslaw Palczynski: More robust VS installation detection. Change 2039693 by Jaroslaw Palczynski: 327268 - RocketGDC: POSTLAUNCH: DEV: Make engine more robust against bad Visual Studio environment variables Change 1978978 by Jaroslaw Surowiec: - Removed obsolete AllowEliminatingReferences from the FArchive Change 2020326 by Maciej Mroz: pretest BP K2Node: RemovePinsFromOldPins function moved from K2Node to RemovePinsFromOldPins Change 2017608 by Maciej Mroz: pretest Some changes in SFortMissionEventSelector caused by FPinTypeTreeInfo Change 2017463 by Maciej Mroz: PinTypeSelector can lins unloaded UDStructs Change 2019979 by Maciej Mroz: pretest BP: Crash when performing Diff against Depot with blueprints containing Format Text nodes Change 2024469 by Maciej Mroz: MemberReference variable added to PinType. It's necessary for delegate's signature. Change 2024049 by Maciej Mroz: HasExternalBlueprintDependencies added to UK2Node_DynamicCast Change 2024586 by Maciej Mroz: FillSimpleMemberReference fix Change 2024472 by Maciej Mroz: workaround for delegates signature in pintype removed. Change 2023997 by Maciej Mroz: BP, UDStruc: Class UserDefinedStructEditorData added. It fixes many problems with undo/redo. Change 2021934 by Maciej Mroz: typo in a comment Change 2020355 by Maciej Mroz: Back out changelist 2020342 Change 2022178 by Maciej Mroz: CRASH: PRETEST: EDITOR: UDS: Crash when undo then redo new variable in struct that is used by blueprint Change 2021958 by Maciej Mroz: CRASH: PRETEST: EDITOR: UDS: Crash using variable of a type of copied struct in blueprint Change 1986247 by Maciej Mroz: User Defined Structures: circle dependency fixed. Early version. Change 1985107 by Maciej Mroz: UserDefinedStruct cannot have a field of a non-native type Change 1986278 by Maciej Mroz: pretest ensureMsgf in Struct::link Change 1986250 by Maciej Mroz: User Defined Struct: Non native classes are accepted types od values in structures. Change 1980955 by Maciej Mroz: Using AssetPtr and LazyPtr as UFunction parameter (intput or return) is explicitly disallowed. Change 2041215 by Maciej Mroz: ttp331249 BLOCKER: PRETEST: UI: Survive the Storm is missing the Mission HUD. Change 1984316 by Maciej Mroz: New User Defined Structure. WIP - there are still problems with circular dependencies. Change 2011616 by Maciej Mroz: UserDefinedStructures - various problems fixed. Change 2011609 by Maciej Mroz: more robust HasExternalBlueprintDependencies implementation Change 2016697 by Maciej Mroz: pretest BP: UDStruct - default value propagation in cooked build Change 2016288 by Maciej Mroz: pretest BP: UDStruct: Renaming variables wont break links from make/break nodes Change 1987637 by Maciej Mroz: CustomStruct icons placeholders Change 1987422 by Maciej Mroz: Better tooltips for variables in MyBlueprint Change 1991387 by Maciej Mroz: UDStructures fixes: Change 2029165 by Maciej Mroz: BP: better comment for incomatible pins Change 2030016 by Maciej Mroz: 8PRETEST: EDITOR: UDS: Defaults values aren't updated in struct type variables in blueprints Change 2030017 by Maciej Mroz: Unused UDStructure code removed (PPF_UseDefaultsForUDStructures) Change 2028856 by Maciej Mroz: BP: Pins with PC_Struct type are compatible only with exactly the same structure. (No derived structures are not handled as compatible). Change 2026701 by Maciej Mroz: k2: odd error on an add item node within a function (see attached image in details) Change 2028160 by Maciej Mroz: PRETEST: EDITOR: UDS: When deleting structures just after creating there is always some references in the memory Change 2028165 by Maciej Mroz: BP: BreakHitResult function has proper icon. Change 2033340 by Maciej Mroz: ttp330786 PRETEST: EDITOR: UDS: Changes of default values aren't apllied to breeak nodes for text type of variables Change 2034255 by Maciej Mroz: EDITOR: UDS: Changes of default values aren't apllied to make nodes for text type of variables ttp#330620 Change 2037682 by Maciej Mroz: ttp331309 BLOCKER: PRETEST: CRASH: EDITOR: Crash occurs when performing Diff Against Depot on any Blueprint Change 2033142 by Maciej Mroz: CreateDelegate Node uses internally FMemberReference. Refactor. Change 2032329 by Maciej Mroz: ttp330608 CRASH: PRETEST: EDITOR: UDS: Crash when trying to use struct named 'Color' in blueprint Change 2032420 by Maciej Mroz: ttp330620 PRETEST: EDITOR: UDS: Changes of default values aren't apllied to make nodes for text type of variables Change 2033139 by Maciej Mroz: Functions generated from CustomEvents can be also identified by GUID Change 2026631 by Maciej Mroz: BP. UDStruct: Invalid structs are handled better. Change 2025344 by Maciej Mroz: UDStruct enabled by default Change 2026672 by Maciej Mroz: EDITOR: BP: Can't easily remove 'pass-by-reference' pins on ReturnNodes Change 2026411 by Maciej Mroz: ExposeOnSpawn updated, it supports UDStructs, custom native Structs, and it throws compiler error. Change 2025342 by Maciej Mroz: GenerateBlueprintSkeleton moved from BLueprint::Serialize to RegenerateBlueprintClass, because SkeletonClass compilation requires all external dependencies to be loaded and linked. Change 2025570 by Steve Robb: Moved dependency processing to its own function. Change 2033235 by Steve Robb: String improvements Change 2035830 by Steve Robb: Workaround for FriendsAndChat crash in Fortnite. Change 2035115 by Steve Robb: UBT build time regression fixes. Change 2034162 by Steve Robb: 312775: UObject improvement: Ensure that *.generated.inl is included somewhere Change 2034181 by Steve Robb: Removal of any references to .generated.inl Change 2020165 by Steve Robb: BuildPublicAndPrivateUObjectHeaders factored out into its own function. Change 2020187 by Steve Robb: CreateModuleCompileEnvironment function factored out. Change 2020055 by Steve Robb: Refactoring of Unity.cs to remove complex and duplicate iteration. Change 2020083 by Steve Robb: Another use of dictionary utilities. Change 2031049 by Steve Robb: 312775: UObject improvement: Ensure that *.generated.inl is included somewhere Change 2025728 by Steve Robb: Refactored the application of a shared PCH file to multiple file into a single ApplySharedPCH function. Change 2020068 by Steve Robb: A couple of helpful utility functions for populating dictionaries. Change 2032307 by Steve Robb: 312775: UObject improvement: Ensure that *.generated.inl is included somewhere [CL 2054495 by Robert Manuszewski in Main branch]
2014-04-23 20:18:55 -04:00
#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<FLevelEditorModule>( "LevelEditor" );
LevelEditorModule.OnActorSelectionChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FActorSelectionChangedTrigger, FBaseTriggerDelegate::ActorSelectionChanged>);
USelection::SelectionChangedEvent.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnSelectionChanged, FBaseTriggerDelegate::OnSelectionChanged>);
USelection::SelectObjectEvent.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnSelectObject, FBaseTriggerDelegate::OnSelectObject>);
FCoreDelegates::OnObjectPropertyChanged.AddSP( this, &FInteractiveTutorials::OnDelegateTriggered<FObjectPropertyChangedTrigger, FBaseTriggerDelegate::ObjectPropertyChanged> );
FAssetEditorManager::Get().OnAssetEditorRequestedOpen().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FAssetEditorRequestedOpenTrigger, FBaseTriggerDelegate::AssetEditorRequestedOpen>);
GLevelEditorModeTools().OnEditorModeChanged().AddSP( this, &FInteractiveTutorials::OnDelegateTriggered<FEditorModeChangedTrigger, FBaseTriggerDelegate::EditorModeChanged> );
GLevelEditorModeTools().OnWidgetModeChanged().AddSP( this, &FInteractiveTutorials::OnDelegateTriggered<FOnWidgetModeChanged, FBaseTriggerDelegate::OnWidgetModeChanged> );
GEditor->OnEndObjectMovement().AddSP( this, &FInteractiveTutorials::OnDelegateTriggered<FOnEndTransformObject, FBaseTriggerDelegate::OnEndTransformObject> );
FEditorDelegates::BeginPIE.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnBeginPIETrigger, FBaseTriggerDelegate::OnBeginPIE>);
FEditorDelegates::EndPIE.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnEndPIETrigger, FBaseTriggerDelegate::OnEndPIE>);
FEditorDelegates::OnConfigureNewAssetProperties.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnNewAssetCreated, FBaseTriggerDelegate::OnNewAssetBeginConfiguration>);
FEditorDelegates::OnNewAssetCreated.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnNewAssetCreated, FBaseTriggerDelegate::OnNewAssetCreated>);
FEditorDelegates::OnFinishPickingBlueprintClass.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnNewBlueprintClassPicked, FBaseTriggerDelegate::OnNewBlueprintClassPicked>);
FEditorDelegates::OnNewActorsDropped.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnNewActorsDropped, FBaseTriggerDelegate::OnNewActorsDropped>);
FEditorDelegates::OnApplyObjectToActor.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnDropAssetOnActor, FBaseTriggerDelegate::OnDropAssetOnActor>);
FEditorDelegates::OnGridSnappingChanged.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnGridSnappingChanged, FBaseTriggerDelegate::OnGridSnappingChanged>);
FEditorDelegates::OnLightingBuildStarted.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnLightingBuildStarted, FBaseTriggerDelegate::OnLightingBuildStarted>);
FEditorDelegates::OnLightingBuildKept.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnLightingBuildKept, FBaseTriggerDelegate::OnLightingBuildKept>);
FEditorDelegates::OnFocusViewportOnActors.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnFocusViewportOnActors, FBaseTriggerDelegate::OnFocusViewportOnActors>);
FEditorDelegates::OnMapOpened.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnMapOpened, FBaseTriggerDelegate::OnMapOpened>);
FEditorDelegates::OnEditorCameraMoved.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnEditorCameraMoved, FBaseTriggerDelegate::EditorCameraMoved>);
FEditorDelegates::OnDollyPerspectiveCamera.AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnEditorCameraZoom, FBaseTriggerDelegate::EditorCameraZoomed>);
FContentBrowserModule& ContentBrowserModule = FModuleManager::GetModuleChecked<FContentBrowserModule>( TEXT("ContentBrowser") );
ContentBrowserModule.GetOnFilterChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnCBFilterChanged, FBaseTriggerDelegate::OnCBFilterChanged>);
ContentBrowserModule.GetOnSearchBoxChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnCBSearchBoxChanged, FBaseTriggerDelegate::OnCBSearchBoxChanged>);
ContentBrowserModule.GetOnAssetSelectionChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnCBAssetSelectionChanged, FBaseTriggerDelegate::OnCBAssetSelectionChanged>);
ContentBrowserModule.GetOnSourcesViewChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnCBSourcesViewChanged, FBaseTriggerDelegate::OnCBSourcesViewChanged>);
ContentBrowserModule.GetOnAssetPathChanged().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnCBAssetPathChanged, FBaseTriggerDelegate::OnCBAssetPathChanged>);
IPlacementModeModule::Get().OnStartedPlacing().AddSP(this, &FInteractiveTutorials::OnDelegateTriggered<FOnStartedPlacing, FBaseTriggerDelegate::OnStartedPlacing>);
UK2Node_TutorialExcerptComplete::OnTutorialExcerptComplete.AddSP(this, &FInteractiveTutorials::CompleteExcerpt);
// 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<FInteractiveTutorial> 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<FInteractiveTutorial>* 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<typename DelegateSignature>
DelegateSignature FInteractiveTutorials::GetTriggerDelegate(FBaseTriggerDelegate::Type DelegateType)
{
if(CurrentTutorial.IsValid())
{
TSharedPtr<FBaseTriggerDelegate> Trigger = CurrentTutorial->FindCurrentTrigger();
if (Trigger.IsValid() && Trigger->DelegateType == DelegateType)
{
return StaticCastSharedPtr<FDerivedTriggerDelegate<DelegateSignature>>(Trigger)->Delegate;
}
}
return DelegateSignature();
}
void FInteractiveTutorials::ExecuteCompletion(bool bSuccessfulCompletion)
{
if (bSuccessfulCompletion)
{
ExcerptConditionsCompleted.ExecuteIfBound();
}
}
template<typename DelegateType, FBaseTriggerDelegate::Type DelegateEnumType>
void FInteractiveTutorials::OnDelegateTriggered()
{
auto Delegate = GetTriggerDelegate<DelegateType>(DelegateEnumType);
if (Delegate.IsBound())
{
ExecuteCompletion(Delegate.Execute());
}
}
template<typename DelegateType, FBaseTriggerDelegate::Type DelegateEnumType, typename Param1Type>
void FInteractiveTutorials::OnDelegateTriggered(Param1Type Param1)
{
auto Delegate = GetTriggerDelegate<DelegateType>(DelegateEnumType);
if (Delegate.IsBound())
{
ExecuteCompletion(Delegate.Execute(Param1));
}
}
template<typename DelegateType, FBaseTriggerDelegate::Type DelegateEnumType, typename Param1Type, typename Param2Type>
void FInteractiveTutorials::OnDelegateTriggered(Param1Type Param1, Param2Type Param2)
{
auto Delegate = GetTriggerDelegate<DelegateType>(DelegateEnumType);
if (Delegate.IsBound())
{
ExecuteCompletion(Delegate.Execute(Param1, Param2));
}
}
template<typename DelegateType, FBaseTriggerDelegate::Type DelegateEnumType, typename Param1Type, typename Param2Type, typename Param3Type, typename Param4Type>
void FInteractiveTutorials::OnDelegateTriggered(Param1Type Param1, Param2Type Param2, Param3Type Param3, Param4Type Param4)
{
auto Delegate = GetTriggerDelegate<DelegateType>(DelegateEnumType);
if (Delegate.IsBound())
{
ExecuteCompletion(Delegate.Execute(Param1, Param2, Param3, Param4));
}
}
#undef LOCTEXT_NAMESPACE