Files
UnrealEngineUWP/Engine/Source/Editor/Levels/Private/SLevelsViewRow.h
Andrew Rodham ba3528c9d4 Made it possible for asset editors to maintain their own FEditorModeTools lists
Breaking changes include:
    * Rename of GEditorModeTools -> GLevelEditorModeTools to signify that it applies only to the level editor modes
    * Addition of FEditorModeRegistry, responsible for managing and creating new editor modes. Modes are no longer registered with an instance of the mode, instead with a mode factory that is able to create a new mode of that type.
    * Editor modes now operate on FEditorViewportClients rather than FLevelEditorViewportClients
    * Added ability to specify an FEditorModeTools when creating an FEditorViewport

Moved component vizualiser manager handling outside of individual editor modes, and into FLevelEditorViewportClient. This should make it easier to transplant in future.

This work addresses TTP#334640 - EDITOR: Investigate making editor modes a per-'editor' concept

Reviewed by Michael Noland, Matt Kuhlenschmidt

[CL 2109245 by Andrew Rodham in Main branch]
2014-06-18 10:16:16 -04:00

1031 lines
30 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Editor/UnrealEd/Public/DragAndDrop/ActorDragDropGraphEdOp.h"
#include "AssetToolsModule.h"
#include "ISourceControlModule.h"
#include "SVectorInputBox.h"
#include "LevelUtils.h"
#define LOCTEXT_NAMESPACE "LevelsView"
namespace LevelsView
{
/** IDs for list columns */
static const FName ColumnID_LevelLabel( "Level" );
static const FName ColumnID_Visibility( "Visibility" );
static const FName ColumnID_Lock( "Lock" );
static const FName ColumnID_SCCStatus( "SCC_Status" );
static const FName ColumnID_Save( "Save" );
static const FName ColumnID_Kismet( "Kismet" );
static const FName ColumnID_Color( "Color" );
static const FName ColumnID_ActorCount( "ActorCount" );
static const FName ColumnID_LightmassSize( "LightmassSize" );
static const FName ColumnID_FileSize( "FileSize" );
static const FName ColumnID_EditorOffset( "EditorOffset" );
}
/**
* The widget that represents a row in the LevelsView's list view control. Generates widgets for each column on demand.
*/
class SLevelsViewRow : public SMultiColumnTableRow< TSharedPtr< FLevelViewModel > >
{
public:
SLATE_BEGIN_ARGS( SLevelsViewRow ){}
SLATE_ATTRIBUTE( FText, HighlightText )
SLATE_END_ARGS()
/**
* Construct this widget. Called by the SNew() Slate macro.
*
* @param InArgs Declaration used by the SNew() macro to construct this widget
* @param InViewModel The Level the row widget is supposed to represent
* @param InOwnerTableView The owner of the row widget
*/
void Construct( const FArguments& InArgs, TSharedRef< FLevelViewModel > InViewModel, TSharedRef< STableViewBase > InOwnerTableView )
{
ViewModel = InViewModel;
// Check we have the streaming level
ULevelStreaming* LevelStreaming = ViewModel->GetLevelStreaming().Get();
if(LevelStreaming)
{
// Cache Transform, so we can update spin box without rotating level till commit
LevelTransform = LevelStreaming->LevelTransform;
}
bSliderMovement = false;
HighlightText = InArgs._HighlightText;
SMultiColumnTableRow< TSharedPtr< FLevelViewModel > >::Construct( FSuperRowType::FArguments(), InOwnerTableView );
ForegroundColor = TAttribute<FSlateColor>( this, &SLevelsViewRow::GetForegroundBasedOnSelection );
}
FSlateColor GetForegroundBasedOnSelection() const
{
return FEditorStyle::GetSlateColor("DefaultForeground");
}
protected:
/** @return the visibility for the Actor Count column */
EVisibility IsActorColumnVisible() const
{
return (GetDefault<ULevelBrowserSettings>()->bDisplayActorCount)?
EVisibility::Visible : EVisibility::Collapsed;
}
/** @return the visibility for the Lightmass Size column */
EVisibility IsLightmassSizeColumnVisible() const
{
return (GetDefault<ULevelBrowserSettings>()->bDisplayLightmassSize)?
EVisibility::Visible : EVisibility::Collapsed;
}
/** @return the visibility for the File Size column */
EVisibility IsFileSizeColumnVisible() const
{
return (GetDefault<ULevelBrowserSettings>()->bDisplayFileSize)?
EVisibility::Visible : EVisibility::Collapsed;
}
/** @return the visibility for the Editor Offset column */
EVisibility IsEditorOffsetColumnVisible() const
{
return (ViewModel->IsPersistent() || !ViewModel->IsLevel()) ? EVisibility::Hidden : EVisibility::Visible;
}
/**
* Constructs the widget that represents the specified ColumnID for this Row
*
* @param ColumnName A unique ID for a column in this TableView; see SHeaderRow::FColumn for more info.
*
* @return a widget to represent the contents of a cell in this row of a TableView.
*/
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
virtual TSharedRef< SWidget > GenerateWidgetForColumn( const FName & ColumnID ) override
{
TSharedPtr< SWidget > TableRowContent;
if( ColumnID == LevelsView::ColumnID_LevelLabel )
{
TableRowContent =
SNew( SHorizontalBox )
+SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.AutoWidth()
[
SNew( STextBlock )
.Font( this, &SLevelsViewRow::GetFont )
.Text( ViewModel.Get(), &FLevelViewModel::GetDisplayName )
.ColorAndOpacity( this, &SLevelsViewRow::GetColorAndOpacity )
.HighlightText( HighlightText )
.ToolTipText( LOCTEXT("DoubleClickToolTip", "Double-Click to make this the current Level") )
.ShadowOffset( FVector2D(1.0f, 1.0f) )
]
;
}
else if( ColumnID == LevelsView::ColumnID_ActorCount )
{
TableRowContent =
SNew( SHorizontalBox )
.Visibility(this, &SLevelsViewRow::IsActorColumnVisible )
+SHorizontalBox::Slot()
.HAlign(HAlign_Right)
.VAlign(VAlign_Center)
[
SNew( STextBlock )
.Font( this, &SLevelsViewRow::GetFont )
.Text( ViewModel.Get(), &FLevelViewModel::GetActorCountString )
.ColorAndOpacity( this, &SLevelsViewRow::GetColorAndOpacity )
.HighlightText( HighlightText )
.ToolTipText( LOCTEXT("ActorCountToolTip", "The number of Actors in this level") )
.ShadowOffset( FVector2D(1.0f, 1.0f) )
]
;
}
else if( ColumnID == LevelsView::ColumnID_LightmassSize )
{
TableRowContent =
SNew( SHorizontalBox )
.Visibility(this, &SLevelsViewRow::IsLightmassSizeColumnVisible )
+SHorizontalBox::Slot()
.FillWidth(1.0f)
.HAlign(HAlign_Right)
.VAlign(VAlign_Center)
[
SNew( STextBlock )
.Font( this, &SLevelsViewRow::GetFont )
.Text( ViewModel.Get(), &FLevelViewModel::GetLightmassSizeString )
.ColorAndOpacity( this, &SLevelsViewRow::GetColorAndOpacity )
.HighlightText( HighlightText )
.ToolTipText( LOCTEXT("LightmassSizeToolTip", "The size of the lightmap data for this level") )
.ShadowOffset( FVector2D(1.0f, 1.0f) )
]
;
}
else if( ColumnID == LevelsView::ColumnID_FileSize )
{
TableRowContent =
SNew( SHorizontalBox )
.Visibility(this, &SLevelsViewRow::IsFileSizeColumnVisible )
+SHorizontalBox::Slot()
.HAlign(HAlign_Right)
.VAlign(VAlign_Center)
[
SNew( STextBlock )
.Font( this, &SLevelsViewRow::GetFont )
.Text( ViewModel.Get(), &FLevelViewModel::GetFileSizeString )
.ColorAndOpacity( this, &SLevelsViewRow::GetColorAndOpacity )
.HighlightText( HighlightText )
.ToolTipText( LOCTEXT("FileSizeToolTip", "The size of the file for this level") )
.ShadowOffset( FVector2D(1.0f, 1.0f) )
]
;
}
else if( ColumnID == LevelsView::ColumnID_Visibility )
{
TableRowContent =
SAssignNew( VisibilityButton, SButton )
.ContentPadding( 0 )
.ButtonStyle( FEditorStyle::Get(), "ToggleButton" )
.OnClicked( this, &SLevelsViewRow::OnToggleVisibility )
.ToolTipText( LOCTEXT("VisibilityButtonToolTip", "Toggle Level Visibility") )
.ForegroundColor( FSlateColor::UseForeground() )
.HAlign( HAlign_Center )
.VAlign( VAlign_Center )
.Content()
[
SNew( SImage )
.Image( this, &SLevelsViewRow::GetVisibilityBrushForLevel )
.ColorAndOpacity( this, &SLevelsViewRow::GetForegroundColorForVisibilityButton )
]
;
}
else if( ColumnID == LevelsView::ColumnID_Lock )
{
TableRowContent =
SAssignNew( LockButton, SButton )
.ContentPadding( 0 )
.ButtonStyle( FEditorStyle::Get(), "ToggleButton" )
.OnClicked( this, &SLevelsViewRow::OnToggleLock )
.ToolTipText( this, &SLevelsViewRow::GetLockToolTipForLevel )
.ForegroundColor( FSlateColor::UseForeground() )
.HAlign( HAlign_Center )
.VAlign( VAlign_Center )
.Content()
[
SNew( SImage )
.Image( this, &SLevelsViewRow::GetLockBrushForLevel )
.ColorAndOpacity( this, &SLevelsViewRow::GetForegroundColorForLockButton )
]
;
}
else if( ColumnID == LevelsView::ColumnID_Color)
{
TableRowContent =
SAssignNew( ColorButton, SButton )
.ContentPadding( 0 )
.ButtonStyle( FEditorStyle::Get(), "ToggleButton" )
.OnClicked( this, &SLevelsViewRow::OnChangeColor )
.ToolTipText( LOCTEXT("ColorButtonToolTip", "Change Level Color") )
.ForegroundColor( FSlateColor::UseForeground() )
.HAlign( HAlign_Center )
.VAlign( VAlign_Center )
.Content()
[
SNew( SImage )
.Image( this, &SLevelsViewRow::GetColorBrushForLevel )
.ColorAndOpacity( TAttribute< FSlateColor >::Create( TAttribute< FSlateColor >::FGetter::CreateSP( this, &SLevelsViewRow::GetLevelColorAndOpacity ) ) )
]
;
}
else if( ColumnID == LevelsView::ColumnID_SCCStatus )
{
TableRowContent =
SNew(SVerticalBox)
+SVerticalBox::Slot()
.FillHeight(1.0f)
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.FillWidth(1.0f)
.VAlign(VAlign_Center)
[
SNew( SImage )
.Image( this, &SLevelsViewRow::GetSCCStateImage )
.ToolTipText(this, &SLevelsViewRow::GetSCCStateTooltip)
]
]
;
}
else if( ColumnID == LevelsView::ColumnID_Save )
{
TableRowContent =
SAssignNew( SaveButton, SButton )
.ContentPadding( 0 )
.ButtonStyle( FEditorStyle::Get(), "ToggleButton" )
.OnClicked( this, &SLevelsViewRow::OnSave )
.ToolTipText( LOCTEXT("SaveButtonToolTip", "Save Level") )
.ForegroundColor( FSlateColor::UseForeground() )
.HAlign( HAlign_Center )
.VAlign( VAlign_Center )
.Content()
[
SNew( SImage )
.Image( this, &SLevelsViewRow::GetSaveBrushForLevel )
.ColorAndOpacity( TAttribute< FSlateColor >::Create( TAttribute< FSlateColor >::FGetter::CreateSP( this, &SLevelsViewRow::GetSaveButtonColorAndOpacity ) ) )
]
;
}
else if( ColumnID == LevelsView::ColumnID_Kismet )
{
TableRowContent =
SAssignNew( KismetButton, SButton )
.ContentPadding( 0 )
.ButtonStyle( FEditorStyle::Get(), "ToggleButton" )
.OnClicked( this, &SLevelsViewRow::OnOpenKismet )
.ToolTipText( LOCTEXT("KismetButtonToolTip", "Open Level Blueprint") )
.ForegroundColor( FSlateColor::UseForeground() )
.HAlign( HAlign_Center )
.VAlign( VAlign_Center )
.Content()
[
SNew( SImage )
.Image( this, &SLevelsViewRow::GetKismetBrushForLevel )
.ColorAndOpacity( this, &SLevelsViewRow::GetForegroundColorForKismetButton )
]
;
}
else if( ColumnID == LevelsView::ColumnID_EditorOffset )
{
TableRowContent =
SNew( SHorizontalBox )
.Visibility(this, &SLevelsViewRow::IsEditorOffsetColumnVisible )
+SHorizontalBox::Slot()
.Padding(FMargin(10,0,0,0))
.HAlign(HAlign_Fill)
.VAlign(VAlign_Center)
.FillWidth(0.25f)
[
SNew( SButton )
.Text( LOCTEXT("EditLevelTransform", "Viewport Edit") )
.ToolTipText( LOCTEXT("EditLevelToolTip", "Edit level transform in viewport.") )
.OnClicked( FOnClicked::CreateSP( this, &SLevelsViewRow::OnEditLevelClicked ) )
.IsEnabled( this, &SLevelsViewRow::LevelTransformAllowed )
]
+SHorizontalBox::Slot()
.Padding(FMargin(10,0,0,0))
.HAlign(HAlign_Fill)
.VAlign(VAlign_Center)
.FillWidth(0.55f)
[
SNew( SVectorInputBox )
.X( this, &SLevelsViewRow::GetLevelOffset, 0 )
.Y( this, &SLevelsViewRow::GetLevelOffset, 1 )
.Z( this, &SLevelsViewRow::GetLevelOffset, 2 )
.bColorAxisLabels( true )
.OnXCommitted( this, &SLevelsViewRow::OnSetLevelOffset, 0 )
.OnYCommitted( this, &SLevelsViewRow::OnSetLevelOffset, 1 )
.OnZCommitted( this, &SLevelsViewRow::OnSetLevelOffset, 2 )
.Font( FEditorStyle::GetFontStyle( TEXT("PropertyWindow.NormalFont") ) ) // Look the same as transform editing in the details panel
.IsEnabled( this, &SLevelsViewRow::LevelEditTextTransformAllowed )
]
+SHorizontalBox::Slot()
.Padding(FMargin(10,0,0,0))
.HAlign(HAlign_Fill)
.VAlign(VAlign_Center)
.FillWidth(0.2f)
[
SNew( SNumericEntryBox<float> )
.IsEnabled( this, &SLevelsViewRow::LevelEditTextTransformAllowed )
.Font( FEditorStyle::GetFontStyle( TEXT("PropertyWindow.NormalFont") ) )
.Delta(90.0f)
.AllowSpin( true )
.MinValue(0.0f)
.MaxValue(270.0f)
.MinSliderValue(0.0f)
.MaxSliderValue(270.0f)
.Value( this, &SLevelsViewRow::GetLevelRotation )
.OnValueChanged( this, &SLevelsViewRow::OnSetLevelRotation )
.OnValueCommitted( this, &SLevelsViewRow::OnCommitLevelRotation )
.OnBeginSliderMovement( this, &SLevelsViewRow::OnBeginLevelRotatonSlider )
.OnEndSliderMovement( this, &SLevelsViewRow::OnEndLevelRotatonSlider )
.LabelPadding(0)
.Label()
[
SNumericEntryBox<float>::BuildLabel( LOCTEXT("LevelRotation_Label", "Yaw"), FLinearColor::White, SNumericEntryBox<float>::BlueLabelBackgroundColor )
]
]
;
}
else
{
checkf(false, TEXT("Unknown ColumnID provided to SLevelsView") );
}
return TableRowContent.ToSharedRef();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
/**
* Called during drag and drop when the drag leaves a widget.
*
* @param DragDropEvent The drag and drop event.
*/
virtual void OnDragLeave( const FDragDropEvent& DragDropEvent ) override
{
TSharedPtr< FActorDragDropGraphEdOp > DragActorOp = DragDropEvent.GetOperationAs< FActorDragDropGraphEdOp >();
if (DragActorOp.IsValid())
{
DragActorOp->ResetToDefaultToolTip();
}
}
/**
* Called during drag and drop when the the mouse is being dragged over a widget.
*
* @param MyGeometry The geometry of the widget receiving the event.
* @param DragDropEvent The drag and drop event.
*
* @return A reply that indicated whether this event was handled.
*/
virtual FReply OnDragOver( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) override
{
TSharedPtr< FActorDragDropGraphEdOp > DragActorOp = DragDropEvent.GetOperationAs< FActorDragDropGraphEdOp >();
if (!DragActorOp.IsValid())
{
return FReply::Unhandled();
}
bool bCanAssign = false;
FText Message;
if( DragActorOp->Actors.Num() > 1 )
{
bCanAssign = ViewModel->CanAssignActors( DragActorOp->Actors, OUT Message );
}
else
{
bCanAssign = ViewModel->CanAssignActor( DragActorOp->Actors[ 0 ], OUT Message );
}
if ( bCanAssign )
{
DragActorOp->SetToolTip( FActorDragDropGraphEdOp::ToolTip_CompatibleGeneric, Message );
}
else
{
DragActorOp->SetToolTip( FActorDragDropGraphEdOp::ToolTip_IncompatibleGeneric, Message );
}
return FReply::Handled();
}
/**
* Called when the user is dropping something onto a widget; terminates drag and drop.
*
* @param MyGeometry The geometry of the widget receiving the event.
* @param DragDropEvent The drag and drop event.
*
* @return A reply that indicated whether this event was handled.
*/
virtual FReply OnDrop( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) override
{
TSharedPtr< FActorDragDropGraphEdOp > DragActorOp = DragDropEvent.GetOperationAs< FActorDragDropGraphEdOp >();
if (!DragActorOp.IsValid())
{
return FReply::Unhandled();
}
ViewModel->AddActors( DragActorOp->Actors );
return FReply::Handled();
}
private:
/** @return the FSlateFontInfo for the Level label; bold if current or level invalid */
FSlateFontInfo GetFont() const
{
if ( ViewModel->IsCurrent() ||
(!ViewModel->IsLevel() && ViewModel->IsLevelStreaming()) )
{
return FEditorStyle::GetFontStyle("LevelBrowser.LabelFontBold");
}
else
{
return FEditorStyle::GetFontStyle("LevelBrowser.LabelFont");
}
}
/**
* Gets the appropriate SlateColor for each button depending on the button's current state
*
* @return The ForegroundColor
*/
FSlateColor GetForegroundColorForVisibilityButton() const
{
return FSlateColor::UseForeground();
}
FSlateColor GetForegroundColorForLockButton() const
{
return FSlateColor::UseForeground();
}
FSlateColor GetForegroundColorForKismetButton() const
{
return FSlateColor::UseForeground();
}
/**
* Returns the Color and Opacity for displaying the bound Level's Name.
* The Color and Opacity changes depending on whether a drag/drop operation is occurring
*
* @return The SlateColor to render the Level's name in
*/
FSlateColor GetColorAndOpacity() const
{
if ( ViewModel->IsCurrent() )
{
return FLinearColor( 0.12f, 0.56f, 1.0f );
}
// Force the text to display red if level is missing
if (!ViewModel->IsLevel() && ViewModel->IsLevelStreaming())
{
return FLinearColor( 1.0f, 0.0f, 0.0f);
}
if ( !FSlateApplication::Get().IsDragDropping() )
{
return FSlateColor::UseForeground();
}
bool bCanAcceptDrop = false;
TSharedPtr<FDragDropOperation> DragDropOp = FSlateApplication::Get().GetDragDroppingContent();
if (DragDropOp.IsValid() && DragDropOp->IsOfType<FActorDragDropGraphEdOp>())
{
TSharedPtr<FActorDragDropGraphEdOp> DragDropActorOp = StaticCastSharedPtr<FActorDragDropGraphEdOp>(DragDropOp);
FText Message;
bCanAcceptDrop = ViewModel->CanAssignActors( DragDropActorOp->Actors, OUT Message );
}
return ( bCanAcceptDrop ) ? FSlateColor::UseForeground() : FLinearColor( 0.30f, 0.30f, 0.30f );
}
/**
* Returns the Color and Opacity for displaying the bound Level's Name.
* The Color and Opacity changes depending on whether a drag/drop operation is occurring
*
* @return The SlateColor to render the Level's name in
*/
FSlateColor GetLockButtonColorAndOpacity() const
{
if ( !ViewModel->GetLevel().IsValid() )
{
return FSlateColor::UseForeground();
}
return ( ViewModel->IsPersistent() ) ? FSlateColor::UseForeground() : FLinearColor( 0.0f, 0.0f, 0.0f, 0.0f );
}
/**
* Returns the Color and Opacity for displaying the Level's Save Button.
*
* @return The SlateColor to render the Level's Saves icon
*/
FSlateColor GetSaveButtonColorAndOpacity() const
{
if ( ViewModel->IsDirty() )
{
return FLinearColor::White;
}
else
{
return FSlateColor::UseForeground();
}
}
/**
* Returns the Color and Opacity for displaying the Level's color.
*
* @return The SlateColor to render the Level's color icon
*/
FSlateColor GetLevelColorAndOpacity() const
{
return ViewModel->GetColor();
}
/**
* Called when the user clicks on the visibility icon for a Level's row widget
*
* @return A reply that indicated whether this event was handled.
*/
FReply OnToggleVisibility()
{
ViewModel->ToggleVisibility();
return FReply::Handled();
}
/**
* Called when the user clicks on the lock icon for a Level's row widget
*
* @return A reply that indicated whether this event was handled.
*/
FReply OnToggleLock()
{
// If were locking a level, lets make sure to close the level transform mode if its the same level currently selected for edit
FEdModeLevel* LevelMode = static_cast<FEdModeLevel*>(GLevelEditorModeTools().GetActiveMode( FBuiltinEditorModes::EM_Level ));
if( LevelMode )
{
ULevelStreaming* LevelStreaming = ViewModel->GetLevelStreaming().Get();
if( LevelMode->IsEditing( LevelStreaming ) )
{
GLevelEditorModeTools().DeactivateMode( FBuiltinEditorModes::EM_Level );
}
}
const FScopedTransaction Transaction( LOCTEXT("ToggleLevelLock", "Toggle Level Lock") );
ViewModel->ToggleLock();
return FReply::Handled();
}
/**
* Called when the user clicks on the save icon for a Level's row widget
*
* @return A reply that indicated whether this event was handled.
*/
FReply OnSave()
{
ViewModel->Save();
return FReply::Handled();
}
/**
* Called when the user clicks on the kismet icon for a Level's row widget
*
* @return A reply that indicated whether this event was handled.
*/
FReply OnOpenKismet()
{
ViewModel->OpenKismet();
return FReply::Handled();
}
/**
* Called when the user clicks on the color icon for a Level's row widget
*
* @return A reply that indicated whether this event was handled.
*/
FReply OnChangeColor()
{
ViewModel->ChangeColor(AsShared());
return FReply::Handled();
}
/**
* Called to get the Slate Image Brush representing the visibility state of
* the Level this row widget represents
*
* @return The SlateBrush representing the Level's visibility state
*/
const FSlateBrush* GetVisibilityBrushForLevel() const
{
if ( ViewModel->IsLevel() )
{
if ( ViewModel->IsVisible() )
{
return VisibilityButton->IsHovered() ? FEditorStyle::GetBrush( "Level.VisibleHighlightIcon16x" ) :
FEditorStyle::GetBrush( "Level.VisibleIcon16x" );
}
else
{
return VisibilityButton->IsHovered() ? FEditorStyle::GetBrush( "Level.NotVisibleHighlightIcon16x" ) :
FEditorStyle::GetBrush( "Level.NotVisibleIcon16x" );
}
}
else
{
return FEditorStyle::GetBrush( "Level.EmptyIcon16x" );
}
}
/**
* Called to get the Slate Image Brush representing the lock state of
* the Level this row widget represents
*
* @return The SlateBrush representing the Level's lock state
*/
const FSlateBrush* GetLockBrushForLevel() const
{
if ( !ViewModel->IsLevel() || ViewModel->IsPersistent() )
{
//Locking the persistent level is not allowed; stub in a different brush
return FEditorStyle::GetBrush( "Level.EmptyIcon16x" );
}
else
{
//Non-Persistent
if ( GEngine && GEngine->bLockReadOnlyLevels )
{
if(ViewModel->IsReadOnly())
{
return LockButton->IsHovered() ? FEditorStyle::GetBrush( "Level.ReadOnlyLockedHighlightIcon16x" ) :
FEditorStyle::GetBrush( "Level.ReadOnlyLockedIcon16x" );
}
}
if ( ViewModel->IsLocked() )
{
return LockButton->IsHovered() ? FEditorStyle::GetBrush( "Level.LockedHighlightIcon16x" ) :
FEditorStyle::GetBrush( "Level.LockedIcon16x" );
}
else
{
return LockButton->IsHovered() ? FEditorStyle::GetBrush( "Level.UnlockedHighlightIcon16x" ) :
FEditorStyle::GetBrush( "Level.UnlockedIcon16x" );
}
}
}
/**
* Called to get the tooltip string representing the lock state of
* the Level this row widget represents
*
* @return The tooltip representing the Level's lock state
*/
FString GetLockToolTipForLevel() const
{
//Non-Persistent
if ( GEngine && GEngine->bLockReadOnlyLevels )
{
if(ViewModel->IsReadOnly())
{
return LOCTEXT("ReadOnly_LockButtonToolTip", "Read-Only levels are locked!").ToString();
}
}
return LOCTEXT("LockButtonToolTip", "Toggle Level Lock").ToString();
}
FString GetSCCStateTooltip() const
{
ULevel* Level = ViewModel->GetLevel().Get();
if (Level != NULL)
{
FSourceControlStatePtr SourceControlState = ISourceControlModule::Get().GetProvider().GetState(Level->GetOutermost(), EStateCacheUsage::Use);
if(SourceControlState.IsValid())
{
return SourceControlState->GetDisplayTooltip().ToString();
}
}
return FString();
}
const FSlateBrush* GetSCCStateImage() const
{
ULevel* Level = ViewModel->GetLevel().Get();
if (Level != NULL)
{
FSourceControlStatePtr SourceControlState = ISourceControlModule::Get().GetProvider().GetState(Level->GetOutermost(), EStateCacheUsage::Use);
if(SourceControlState.IsValid())
{
return FEditorStyle::GetBrush(SourceControlState->GetSmallIconName());
}
}
return NULL;
}
/**
* Called to get the Slate Image Brush representing the save state of
* the Level this row widget represents
*
* @return The SlateBrush representing the Level's save state
*/
const FSlateBrush* GetSaveBrushForLevel() const
{
if ( ViewModel->IsLevel() )
{
if ( ViewModel->IsLocked() )
{
return FEditorStyle::GetBrush( "Level.SaveDisabledIcon16x" );
}
else
{
if ( ViewModel->IsDirty() )
{
return SaveButton->IsHovered() ? FEditorStyle::GetBrush( "Level.SaveModifiedHighlightIcon16x" ) :
FEditorStyle::GetBrush( "Level.SaveModifiedIcon16x" );
}
else
{
return SaveButton->IsHovered() ? FEditorStyle::GetBrush( "Level.SaveHighlightIcon16x" ) :
FEditorStyle::GetBrush( "Level.SaveIcon16x" );
}
}
}
else
{
return FEditorStyle::GetBrush( "Level.EmptyIcon16x" );
}
}
/**
* Called to get the Slate Image Brush representing the kismet state of
* the Level this row widget represents
*
* @return The SlateBrush representing the Level's kismet state
*/
const FSlateBrush* GetKismetBrushForLevel() const
{
if ( ViewModel->IsLevel() )
{
if ( ViewModel->HasKismet() )
{
return KismetButton->IsHovered() ? FEditorStyle::GetBrush( "Level.ScriptHighlightIcon16x" ) :
FEditorStyle::GetBrush( "Level.ScriptIcon16x" );
}
else
{
return FEditorStyle::GetBrush( "Level.EmptyIcon16x" );
}
}
else
{
return FEditorStyle::GetBrush( "Level.EmptyIcon16x" );
}
}
/**
* Called to get the Slate Image Brush representing the color of
* the Level this row widget represents
*
* @return The SlateBrush representing the Level's color
*/
const FSlateBrush* GetColorBrushForLevel() const
{
if ( !ViewModel->IsLevel() || ViewModel->IsPersistent() )
{
//stub in a different brush for the persistent level, since the color cannot be changed
return FEditorStyle::GetBrush( "Level.EmptyIcon16x" );
}
else
{
return FEditorStyle::GetBrush( "Level.ColorIcon40x" );
}
}
/**
* Called by the Editor Level Transform column, to set the new values.
*
* @param NewValue The new value entered.
* @param CommitInfo The way in which the value was committed, currently ignored, we always use the new value.
* @param Axis The axis being edited.
*/
void OnSetLevelOffset( float NewValue, ETextCommit::Type CommitInfo, int32 Axis )
{
// Check we have the streaming level
ULevelStreaming* LevelStreaming = ViewModel->GetLevelStreaming().Get();
if(!LevelStreaming)
{
return;
}
// Setup a new transform
FVector Translation = LevelTransform.GetTranslation();
Translation[Axis] = NewValue;
LevelTransform.SetTranslation(Translation);
FLevelUtils::SetEditorTransform(LevelStreaming, LevelTransform);
}
/**
* Called by the Editor Level Transform column, to get the current values.
*
* @param Axis The axis to return the value for.
*
* @return The current value of the translation for given axis.
*/
TOptional<float> GetLevelOffset( int32 Axis ) const
{
ULevelStreaming* LevelStreaming = ViewModel->GetLevelStreaming().Get();
if(!LevelStreaming)
{
FVector Translation = LevelTransform.GetTranslation();
return Translation[Axis];
}
FVector Translation = LevelStreaming->LevelTransform.GetTranslation();
return Translation[Axis];
}
/**
* Called by the Editor Level Rotation column, to commit the new values.
*
* @param NewValue The new value entered.
* @param CommitInfo The way in which the value was committed, currently ignored, we always use the new value.
*/
void OnCommitLevelRotation( float NewValue, ETextCommit::Type CommitInfo )
{
// Check we have the streaming level
ULevelStreaming* LevelStreaming = ViewModel->GetLevelStreaming().Get();
if(!LevelStreaming)
{
return;
}
// Use LevelTransform set by OnSetLeveRotation as OnCommitLevelRotation NewValue seems to ignore min delta of a spin box
FLevelUtils::SetEditorTransform(LevelStreaming, LevelTransform);
}
/**
* Called by the Editor Level Rotation column, to set the new values.
*
* @param NewValue The new value entered.
*/
void OnSetLevelRotation( float NewValue )
{
FRotator Rotation = LevelTransform.GetRotation().Rotator();
Rotation.Yaw = NewValue;
LevelTransform.SetRotation(Rotation.Quaternion());
}
/**
* Called by the Editor Level Rotation column, to set weve started spinning the value.
*/
void OnBeginLevelRotatonSlider()
{
bSliderMovement = true;
}
/**
* Called by the Editor Level Rotation column, to set weve stopped spinning the value.
*
* @param NewValue The new value entered.
*/
void OnEndLevelRotatonSlider( float NewValue )
{
bSliderMovement = false;
}
/**
* Called by the Editor Level Transform column, to get the current values.
*
* @return The current value of the Level Yaw.
*/
TOptional<float> GetLevelRotation() const
{
// If were not using the spin box use the actual transform instead of cached as it may have changed with the view port widget
if( !bSliderMovement )
{
ULevelStreaming* LevelStreaming = ViewModel->GetLevelStreaming().Get();
if(LevelStreaming)
{
return LevelStreaming->LevelTransform.GetRotation().Rotator().Yaw;
}
}
return LevelTransform.GetRotation().Rotator().Yaw;
}
/**
* Called by the Editor Level Edit Viewport button.
*/
FReply OnEditLevelClicked()
{
ULevelStreaming* LevelStreaming = ViewModel->GetLevelStreaming().Get();
if(!LevelStreaming)
{
return FReply::Handled();
}
if( !GLevelEditorModeTools().IsModeActive(FBuiltinEditorModes::EM_Level))
{
// Activate Level Mode if it was not active
GLevelEditorModeTools().ActivateMode( FBuiltinEditorModes::EM_Level );
}
FEdModeLevel* ActiveMode = static_cast<FEdModeLevel*>(GLevelEditorModeTools().GetActiveMode( FBuiltinEditorModes::EM_Level ));
check(ActiveMode != NULL);
if( ActiveMode->IsEditing(LevelStreaming) == true )
{
// Toggle this mode off if already editing this level
GLevelEditorModeTools().DeactivateMode(FBuiltinEditorModes::EM_Level);
// Cache Transform, as it might of changed by doing a view port edit
LevelTransform = LevelStreaming->LevelTransform;
}
else
{
// Set the level we now want to edit
ActiveMode->SetLevel(LevelStreaming);
}
return FReply::Handled();
}
bool LevelTransformAllowed() const
{
ULevelStreaming* LevelStreaming = ViewModel->GetLevelStreaming().Get();
if(LevelStreaming)
{
if( LevelStreaming->GetLoadedLevel()->bIsVisible && !LevelStreaming->bLocked )
{
return true;
}
}
return false;
}
bool LevelEditTextTransformAllowed() const
{
ULevelStreaming* LevelStreaming = ViewModel->GetLevelStreaming().Get();
FEdModeLevel* ActiveMode = static_cast<FEdModeLevel*>(GLevelEditorModeTools().GetActiveMode( FBuiltinEditorModes::EM_Level ));
if( ActiveMode && ActiveMode->IsEditing(LevelStreaming) == true )
{
return false;
}
return LevelTransformAllowed();
}
private:
/** The Level associated with this row of data */
TSharedPtr< FLevelViewModel > ViewModel;
/** The visibility button for the Level */
TSharedPtr< SButton > VisibilityButton;
/** The lock button for the Level */
TSharedPtr< SButton > LockButton;
/** The save button for the Level */
TSharedPtr< SButton > SaveButton;
/** The kismet button for the Level */
TSharedPtr< SButton > KismetButton;
/** The color button for the Level */
TSharedPtr< SButton > ColorButton;
/** The string to highlight on any text contained in the row widget */
TAttribute< FText > HighlightText;
/** Cached Level Transform, so we don't have to edit the original before we commit change*/
FTransform LevelTransform;
/** Set When the user is using the rotation spin box so we can update the value with the cached Transform */
bool bSliderMovement;
};
#undef LOCTEXT_NAMESPACE