haxis/Plugins/SkillTree/Source/SkillTreeEditor/Private/SkillTreeEditorViewport.cpp

532 lines
18 KiB
C++

// Project Lab - NHTV IGAD
//////////////////////////////////////////
// Author: Yoshi van Belkom - 130118
//////////////////////////////////////////
#include "SkillTreeEditorPrivatePCH.h"
#include "SkillTreeEditorViewport.h"
#include "SceneViewport.h"
#include "GraphEditor.h"
#include "SDockTab.h"
#include "SEditorViewport.h"
#include "SCommonEditorViewportToolbarBase.h"
#include "ISkillTree.h"
#include "SkillTreeEditorViewportClient.h"
#include "SSkillTreeEditorViewportToolbar.h"
#include "SkillTreeObject.h"
#include "SkillObject.h"
#include "WorkspaceMenuStructureModule.h"
#include "SkillTreeEditorCommands.h"
#include "SSingleObjectDetailsPanel.h"
#include "SkillTreeDetailsCustomization.h"
#define LOCTEXT_NAMESPACE "SkillTreeEditor"
const FName skillTreeEditorAppName = FName( TEXT( "SkillTreeEditorApp" ) );
// Tab identifiers.
struct FSkillTreeEditorTabs
{
static const FName skillTreeViewportID;
static const FName skillTreeDetailViewportID;
static const FName skillViewportID;
static const FName skillDetailViewportID;
};
const FName FSkillTreeEditorTabs::skillTreeViewportID( TEXT( "STViewport" ) );
const FName FSkillTreeEditorTabs::skillViewportID( TEXT( "SViewport" ) );
const FName FSkillTreeEditorTabs::skillTreeDetailViewportID( TEXT( "STDViewport" ) );
const FName FSkillTreeEditorTabs::skillDetailViewportID( TEXT( "SDViewport" ) );
//TODO: Make separate headers for these classes.
/////////////////////////////////////////////////////
// SSkillTreePropertiesTabBody
class SSkillTreePropertiesTabBody : public SSingleObjectDetailsPanel
{
public:
SLATE_BEGIN_ARGS( SSkillTreePropertiesTabBody ) {}
SLATE_END_ARGS()
private:
// Pointer back to owning skill tree editor instance.
TWeakPtr<class FSkillTreeEditorViewport> m_skillTreeEditorPtr;
public:
void Construct( const FArguments& a_args, TSharedPtr<FSkillTreeEditorViewport> a_skillTreeEditor )
{
m_skillTreeEditorPtr = a_skillTreeEditor;
SSingleObjectDetailsPanel::Construct( SSingleObjectDetailsPanel::FArguments().HostCommandList( a_skillTreeEditor->GetToolkitCommands() ), true, true );
FOnGetDetailCustomizationInstance customizeSkillTreeForEditor = FOnGetDetailCustomizationInstance::CreateStatic( &FSkillTreeDetailsCustomization::MakeInstanceForSkillTreeEditor );
PropertyView->RegisterInstancedCustomPropertyLayout( USkillTreeObject::StaticClass(), customizeSkillTreeForEditor );
}
// SSingleObjectDetailsPanel interface
virtual UObject* GetObjectToObserve() const override
{
return m_skillTreeEditorPtr.Pin()->GetSkillTreeBeingEdited();
}
virtual TSharedRef<SWidget> PopulateSlot( TSharedRef<SWidget> a_propertyEditorWidget ) override
{
return SNew( SVerticalBox )
+ SVerticalBox::Slot()
.FillHeight( 1 )
[
a_propertyEditorWidget
];
}
// End of SSingleObjectDetailsPanel interface
};
/////////////////////////////////////////////////////
// SSkillPropertiesTabBody
class SSkillPropertiesTabBody : public SSingleObjectDetailsPanel
{
public:
SLATE_BEGIN_ARGS( SSkillPropertiesTabBody ) {}
SLATE_END_ARGS()
private:
// Pointer back to owning sprite editor instance (the keeper of state)
TWeakPtr<class FSkillTreeEditorViewport> m_skillTreeEditorPtr;
public:
void Construct( const FArguments& InArgs, TSharedPtr<FSkillTreeEditorViewport> a_skillTreeEditor )
{
m_skillTreeEditorPtr = a_skillTreeEditor;
SSingleObjectDetailsPanel::Construct( SSingleObjectDetailsPanel::FArguments().HostCommandList( a_skillTreeEditor->GetToolkitCommands() ), true, true );
FOnGetDetailCustomizationInstance customizeSkillTreeForEditor = FOnGetDetailCustomizationInstance::CreateStatic( &FSkillDetailsCustomization::MakeInstanceForSkillTreeEditor );
PropertyView->RegisterInstancedCustomPropertyLayout( USkillObject::StaticClass(), customizeSkillTreeForEditor );
}
// SSingleObjectDetailsPanel interface
virtual UObject* GetObjectToObserve() const override
{
return m_skillTreeEditorPtr.Pin()->GetSkillBeingEdited();
}
virtual TSharedRef<SWidget> PopulateSlot( TSharedRef<SWidget> a_propertyEditorWidget ) override
{
return SNew( SVerticalBox )
+ SVerticalBox::Slot()
.FillHeight( 1 )
[
a_propertyEditorWidget
];
}
// End of SSingleObjectDetailsPanel interface
};
/////////////////////////////////////////////////////
// SSkillTreeEditorViewport
class SSkillTreeEditorViewport : public SEditorViewport, public ICommonEditorViewportToolbarInfoProvider
{
public:
SLATE_BEGIN_ARGS( SSkillTreeEditorViewport ) {}
SLATE_END_ARGS()
void Construct( const FArguments& a_args, TSharedPtr<FSkillTreeEditorViewport> a_spriteEditor );
// SEditorViewport interface
virtual void BindCommands() override;
virtual TSharedRef<FEditorViewportClient> MakeEditorViewportClient() override;
virtual TSharedPtr<SWidget> MakeViewportToolbar() override;
virtual EVisibility GetTransformToolbarVisibility() const override;
virtual void OnFloatingButtonClicked() override;
// End of SEditorViewport interface
// ICommonEditorViewportToolbarInfoProvider interface
virtual TSharedRef<class SEditorViewport> GetViewportWidget() override;
virtual TSharedPtr<FExtender> GetExtenders() const override;
// End of ICommonEditorViewportToolbarInfoProvider interface
void ActivateEditMode()
{
m_editorViewportClient->ActivateEditMode();
}
void IsSkill( bool a_state )
{
m_editorViewportClient->IsSkill( a_state );
}
private:
// Pointer back to owning Skill Tree editor instance (the keeper of state).
TWeakPtr<class FSkillTreeEditorViewport> m_skillTreeEditorPtr;
// Viewport client
TSharedPtr<FSkillTreeEditorViewportClient> m_editorViewportClient;
};
void SSkillTreeEditorViewport::Construct( const FArguments& a_args, TSharedPtr<FSkillTreeEditorViewport> a_skillTreeEditor )
{
m_skillTreeEditorPtr = a_skillTreeEditor;
SEditorViewport::Construct( SEditorViewport::FArguments() );
}
void SSkillTreeEditorViewport::BindCommands()
{
SEditorViewport::BindCommands();
const FSkillTreeEditorCommands& commands = FSkillTreeEditorCommands::Get();
TSharedRef<FSkillTreeEditorViewportClient> editorViewportClientRef = m_editorViewportClient.ToSharedRef();
// Show toggles
//TODO: Remove.
CommandList->MapAction(
commands.setShowGrid,
FExecuteAction::CreateSP( editorViewportClientRef, &FEditorViewportClient::SetShowGrid ),
FCanExecuteAction(),
FIsActionChecked::CreateSP( editorViewportClientRef, &FEditorViewportClient::IsSetShowGridChecked ) );
// Editing modes
//TODO: Remove.
CommandList->MapAction(
commands.enterViewMode,
FExecuteAction::CreateSP( editorViewportClientRef, &FSkillTreeEditorViewportClient::EnterViewMode ),
FCanExecuteAction(),
FIsActionChecked::CreateSP( editorViewportClientRef, &FSkillTreeEditorViewportClient::IsInViewMode ) );
}
// Make a new client for the viewport.
TSharedRef<FEditorViewportClient> SSkillTreeEditorViewport::MakeEditorViewportClient()
{
m_editorViewportClient = MakeShareable( new FSkillTreeEditorViewportClient( m_skillTreeEditorPtr, SharedThis( this ) ) );
return m_editorViewportClient.ToSharedRef();
}
TSharedPtr<SWidget> SSkillTreeEditorViewport::MakeViewportToolbar()
{
return SNew( SSkillTreeEditorViewportToolbar, SharedThis( this ) );
}
EVisibility SSkillTreeEditorViewport::GetTransformToolbarVisibility() const
{
return EVisibility::Visible;
}
TSharedRef<class SEditorViewport> SSkillTreeEditorViewport::GetViewportWidget()
{
return SharedThis( this );
}
TSharedPtr<FExtender> SSkillTreeEditorViewport::GetExtenders() const
{
TSharedPtr<FExtender> Result( MakeShareable( new FExtender ) );
return Result;
}
//Needed to be implemented but not used.
void SSkillTreeEditorViewport::OnFloatingButtonClicked()
{
}
/////////////////////////////////////////////////////
// FSkillTreeEditorViewport
TSharedRef<SDockTab> FSkillTreeEditorViewport::SpawnTab_SKViewport( const FSpawnTabArgs& a_args )
{
return SNew( SDockTab )
.Label( LOCTEXT( "SKViewportTab_Title", "Skill Tree" ) )
[
SNew( SOverlay )
// The Skill Tree editor viewport
+ SOverlay::Slot()
[
m_skillTreeViewport.ToSharedRef()
]
// Bottom-right corner text indicating the preview nature of the viewport.
+ SOverlay::Slot()
.Padding( 10 )
.VAlign( VAlign_Bottom )
.HAlign( HAlign_Right )
[
SNew( STextBlock )
.Visibility( EVisibility::HitTestInvisible )
.TextStyle( FEditorStyle::Get(), "Graph.CornerText" )
.Text( LOCTEXT( "SKViewportTab_CornerText", "Edit Skill Tree" ) )
]
];
}
TSharedRef<SDockTab> FSkillTreeEditorViewport::SpawnTab_SViewport( const FSpawnTabArgs& a_args )
{
return SNew( SDockTab )
.Label( LOCTEXT( "SViewportTab_Title", "Skill" ) )
[
SNew( SOverlay )
// The sprite editor viewport
+ SOverlay::Slot()
[
m_skillViewport.ToSharedRef()
]
// Bottom-right corner text indicating the preview nature of the viewport.
+ SOverlay::Slot()
.Padding( 10 )
.VAlign( VAlign_Bottom )
.HAlign( HAlign_Right )
[
SNew( STextBlock )
.Visibility( EVisibility::HitTestInvisible )
.TextStyle( FEditorStyle::Get(), "Graph.CornerText" )
.Text( LOCTEXT("SViewportTab_CornerText", "Edit Skill") )
]
];
}
TSharedRef<SDockTab> FSkillTreeEditorViewport::SpawnTab_SKDViewport( const FSpawnTabArgs& a_args )
{
TSharedPtr<FSkillTreeEditorViewport> editorPtr = SharedThis( this );
// Spawn the tab
return SNew( SDockTab )
.Label( LOCTEXT( "SKDViewportTab_Title", "Skill Tree Details" ) )
[
SNew( SSkillTreePropertiesTabBody, editorPtr )
];
}
TSharedRef<SDockTab> FSkillTreeEditorViewport::SpawnTab_SDViewport( const FSpawnTabArgs& a_args )
{
TSharedPtr<FSkillTreeEditorViewport> editorPtr = SharedThis( this );
// Spawn the tab
return SNew( SDockTab )
.Label( LOCTEXT( "SDViewportTab_Title", "Skill Details" ) )
[
SNew( SSkillPropertiesTabBody, editorPtr )
];
}
void FSkillTreeEditorViewport::RegisterTabSpawners( const TSharedRef<class FTabManager>& a_tabManager )
{
WorkspaceMenuCategory = a_tabManager->AddLocalWorkspaceMenuCategory( LOCTEXT( "WorkspaceMenu_SpriteEditor", "Skill Tree Editor" ) );
auto workspaceMenuCategoryRef = WorkspaceMenuCategory.ToSharedRef();
FAssetEditorToolkit::RegisterTabSpawners( a_tabManager );
a_tabManager->RegisterTabSpawner( FSkillTreeEditorTabs::skillTreeViewportID, FOnSpawnTab::CreateSP( this, &FSkillTreeEditorViewport::SpawnTab_SKViewport ) )
.SetDisplayName( LOCTEXT( "SKViewportTab", "Skill Tree" ) )
.SetGroup( workspaceMenuCategoryRef )
.SetIcon( FSlateIcon( FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Viewports" ) );
a_tabManager->RegisterTabSpawner( FSkillTreeEditorTabs::skillTreeDetailViewportID, FOnSpawnTab::CreateSP( this, &FSkillTreeEditorViewport::SpawnTab_SKDViewport ) )
.SetDisplayName( LOCTEXT( "SKDViewportTab", "Skill Tree Details" ) )
.SetGroup( workspaceMenuCategoryRef )
.SetIcon( FSlateIcon( FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Viewports" ) );
a_tabManager->RegisterTabSpawner( FSkillTreeEditorTabs::skillViewportID, FOnSpawnTab::CreateSP( this, &FSkillTreeEditorViewport::SpawnTab_SViewport ) )
.SetDisplayName( LOCTEXT( "SViewportTab", "Skill" ) )
.SetGroup( workspaceMenuCategoryRef )
.SetIcon( FSlateIcon( FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Viewports" ) );
a_tabManager->RegisterTabSpawner( FSkillTreeEditorTabs::skillDetailViewportID, FOnSpawnTab::CreateSP( this, &FSkillTreeEditorViewport::SpawnTab_SDViewport ) )
.SetDisplayName( LOCTEXT( "SDViewportTab", "Skill Details" ) )
.SetGroup( workspaceMenuCategoryRef )
.SetIcon( FSlateIcon( FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Viewports" ) );
}
void FSkillTreeEditorViewport::UnregisterTabSpawners( const TSharedRef<class FTabManager>& a_tabManager )
{
FAssetEditorToolkit::UnregisterTabSpawners( a_tabManager );
a_tabManager->UnregisterTabSpawner( FSkillTreeEditorTabs::skillTreeViewportID );
a_tabManager->UnregisterTabSpawner( FSkillTreeEditorTabs::skillTreeDetailViewportID );
a_tabManager->UnregisterTabSpawner( FSkillTreeEditorTabs::skillViewportID );
a_tabManager->UnregisterTabSpawner( FSkillTreeEditorTabs::skillDetailViewportID );
}
FName FSkillTreeEditorViewport::GetToolkitFName() const
{
return FName( "SkillTreeEditor" );
}
void FSkillTreeEditorViewport::SetSkillBeingEdited( USkillObject* a_skill )
{
if ( (a_skill != m_skillBeingEdited) && (a_skill != nullptr) )
{
USkillObject* oldSkill = m_skillBeingEdited;
m_skillBeingEdited = a_skill;
//No longer needed.
/*
RemoveEditingObject( oldSkill );
AddEditingObject( a_skill );
*/
}
}
FText FSkillTreeEditorViewport::GetBaseToolkitName() const
{
return LOCTEXT( "SkillTreeEditorAppLabel", "Skill Tree" );
}
FText FSkillTreeEditorViewport::GetToolkitName() const
{
bool dirtyState = (m_skillTreeBeingEdited->GetOutermost()->IsDirty() || m_skillBeingEdited->GetOutermost()->IsDirty());
FFormatNamedArguments args;
args.Add( TEXT( "SkillTreeName" ), FText::FromString( m_skillTreeBeingEdited->GetName() ) );
args.Add( TEXT( "DirtyState" ), dirtyState ? FText::FromString( TEXT( "*" ) ) : FText::GetEmpty() );
return FText::Format( LOCTEXT( "SkillTreeEditorAppLabel", "{SkillTreeName}{DirtyState}" ), args );
}
FText FSkillTreeEditorViewport::GetToolkitToolTipText() const
{
return LOCTEXT( "SkillTreeToolTip", "Test tooltip text" );
}
FString FSkillTreeEditorViewport::GetWorldCentricTabPrefix() const
{
return TEXT( "SkillTreeEditor" );
}
FString FSkillTreeEditorViewport::GetDocumentationLink() const
{
return TEXT( "http://iamfromtheinternet.nl/wiki/index.php/Skill_Tree" );
}
FLinearColor FSkillTreeEditorViewport::GetWorldCentricTabColorScale() const
{
return FLinearColor::White;
}
void FSkillTreeEditorViewport::CreateModeToolbarWidgets( FToolBarBuilder& a_ignoredBuilder )
{
FToolBarBuilder toolbarBuilder( m_skillTreeViewport->GetCommandList(), FMultiBoxCustomization::None );
toolbarBuilder.AddToolBarButton( FSkillTreeEditorCommands::Get().enterViewMode );
AddToolbarWidget( toolbarBuilder.MakeWidget() );
}
void FSkillTreeEditorViewport::InitSkillTreeEditor( const EToolkitMode::Type a_mode, const TSharedPtr< class IToolkitHost >& a_toolkitHost, class USkillTreeObject* a_skillTree, class USkillObject* a_skill )
{
m_skillTreeBeingEdited = a_skillTree;
m_tmpSkills = m_skillTreeBeingEdited->skills;
if ( !a_skill )
{
m_skillBeingEdited = NewObject<USkillObject>();
m_skillBeingEdited->hexMap.width = 0;
m_skillBeingEdited->hexMap.height = 0;
}
else
{
m_skillBeingEdited = a_skill;
selectedY = m_tmpSkills.Find( TSubclassOf<USkillObject>((UClass*)m_skillBeingEdited) );
}
FSkillTreeEditorCommands::Register();
TSharedPtr<FSkillTreeEditorViewport> skillTreeEditorPtr = SharedThis( this );
m_skillTreeViewport = SNew( SSkillTreeEditorViewport, skillTreeEditorPtr );
m_skillViewport = SNew( SSkillTreeEditorViewport, skillTreeEditorPtr );
m_skillViewport->IsSkill( true );
const TSharedRef<FTabManager::FLayout> defaultLayout = FTabManager::NewLayout( "SkillTreeEditor_Layout_v2" )
->AddArea
(
FTabManager::NewPrimaryArea()
->SetOrientation( Orient_Vertical )
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient( 0.1f )
->SetHideTabWell( true )
->AddTab( GetToolbarTabId(), ETabState::OpenedTab )
)
->Split
(
FTabManager::NewSplitter()
->SetOrientation( Orient_Horizontal )
->SetSizeCoefficient( 0.9f )
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient( 0.35f )
->SetHideTabWell( true )
->AddTab( FSkillTreeEditorTabs::skillTreeViewportID, ETabState::OpenedTab )
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient( 0.15f )
->SetHideTabWell( true )
->AddTab( FSkillTreeEditorTabs::skillTreeDetailViewportID, ETabState::OpenedTab )
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient( 0.35f )
->SetHideTabWell( true )
->AddTab( FSkillTreeEditorTabs::skillViewportID, ETabState::OpenedTab )
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient( 0.15f )
->SetHideTabWell( true )
->AddTab( FSkillTreeEditorTabs::skillDetailViewportID, ETabState::OpenedTab )
)
)
);
// Initialize the asset editor
InitAssetEditor( a_mode, a_toolkitHost, skillTreeEditorAppName, defaultLayout, true, true, a_skillTree );
m_skillTreeViewport->ActivateEditMode();
m_skillViewport->ActivateEditMode();
// Extend things
RegenerateMenusAndToolbars();
}
void FSkillTreeEditorViewport::UpdateSkills()
{
if ( m_skillTreeBeingEdited->skills != m_tmpSkills )
{
for ( int i = 0; i < m_tmpSkills.Num(); i++ )
{
if ( m_tmpSkills[i] != NULL && !m_skillTreeBeingEdited->skills.Contains( m_tmpSkills[i] ) )
{
USkillObject* tmpSkill = (USkillObject*)*m_tmpSkills[i];//m_tmpSkills[i]->GetDefaultObject<USkillObject>();
if ( tmpSkill != NULL ) tmpSkill->skillTree = NULL;
}
}
for ( int i = 0; i < m_skillTreeBeingEdited->skills.Num(); i++ )
{
if ( m_skillTreeBeingEdited->skills[i] != NULL && !m_tmpSkills.Contains( m_skillTreeBeingEdited->skills[i] ) )
{
USkillObject* tmpSkill = (USkillObject*)*m_skillTreeBeingEdited->skills[i]; //m_skillTreeBeingEdited->skills[i]->GetDefaultObject<USkillObject>();
if ( tmpSkill != NULL ) tmpSkill->skillTree = m_skillTreeBeingEdited;
}
}
m_tmpSkills = m_skillTreeBeingEdited->skills;
}
}
void FSkillTreeEditorViewport::SaveAsset_Execute()
{
TArray< UPackage* > PackagesToSave;
PackagesToSave.Add( m_skillTreeBeingEdited->GetOutermost() );
PackagesToSave.Add( m_skillBeingEdited->GetOutermost() );
FEditorFileUtils::PromptForCheckoutAndSave( PackagesToSave, bCheckDirtyOnAssetSave, /*bPromptToSave=*/ false );
}
#undef LOCTEXT_NAMESPACE