You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
TTP# 279062 - ROCKET: TASK: PUNTABLE: Viewports: "Drag to Attach" feature Moved FEdModePicker out of the Private section of the PropertyEditor module, and into its own module so that it can be shared between the PropertyEditor and LevelEditor modules. Also renamed it to FEdModeActorPicker. Added a way to filter FEdModeActorPicker by checking the actor directly (this complements the class type check it already had). Added an actor picker button next to the scene outliner in the "Attach To" menu on actors. This is also mapped to the Alt+A command. Built and tested in unity and non-unity. ReviewedBy Thomas.Sarkanen, Max.Preussner [CL 2060928 by Jamie Dale in Main branch]
488 lines
15 KiB
C++
488 lines
15 KiB
C++
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "PropertyEditorPrivatePCH.h"
|
|
#include "AssetSelection.h"
|
|
#include "SPropertyTreeViewImpl.h"
|
|
#include "Slate.h"
|
|
#include "PropertyNode.h"
|
|
#include "ItemPropertyNode.h"
|
|
#include "CategoryPropertyNode.h"
|
|
#include "ObjectPropertyNode.h"
|
|
#include "PropertyNode.h"
|
|
#include "SDetailsView.h"
|
|
#include "SSingleProperty.h"
|
|
#include "Editor/MainFrame/Public/MainFrame.h"
|
|
#include "PropertyChangeListener.h"
|
|
#include "PropertyEditorToolkit.h"
|
|
|
|
#include "PropertyTable.h"
|
|
#include "SPropertyTable.h"
|
|
#include "TextPropertyTableCellPresenter.h"
|
|
|
|
#include "PropertyTableConstants.h"
|
|
|
|
IMPLEMENT_MODULE( FPropertyEditorModule, PropertyEditor );
|
|
|
|
void FPropertyEditorModule::StartupModule()
|
|
{
|
|
}
|
|
|
|
void FPropertyEditorModule::ShutdownModule()
|
|
{
|
|
// NOTE: It's vital that we clean up everything created by this DLL here! We need to make sure there
|
|
// are no outstanding references to objects as the compiled code for this module's class will
|
|
// literally be unloaded from memory after this function exits. This even includes instantiated
|
|
// templates, such as delegate wrapper objects that are allocated by the module!
|
|
DestroyColorPicker();
|
|
|
|
AllDetailViews.Empty();
|
|
AllSinglePropertyViews.Empty();
|
|
}
|
|
|
|
void FPropertyEditorModule::NotifyCustomizationModuleChanged()
|
|
{
|
|
// The module was changed (loaded or unloaded), force a refresh. Note it is assumed the module unregisters all customization delegates before this
|
|
for( int32 ViewIndex = 0; ViewIndex < AllDetailViews.Num(); ++ViewIndex )
|
|
{
|
|
if( AllDetailViews[ ViewIndex ].IsValid() )
|
|
{
|
|
TSharedPtr<SDetailsView> DetailViewPin = AllDetailViews[ ViewIndex ].Pin();
|
|
|
|
DetailViewPin->ForceRefresh();
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool ShouldShowProperty(UProperty const * const Property, bool bHaveTemplate)
|
|
{
|
|
if ((Property != NULL) && bHaveTemplate)
|
|
{
|
|
const UClass* PropertyOwnerClass = Cast<const UClass>(Property->GetOuter());
|
|
const bool bDisableEditOnTemplate = PropertyOwnerClass
|
|
&& PropertyOwnerClass->HasAllFlags(RF_Native)
|
|
&& Property->HasAnyPropertyFlags(CPF_DisableEditOnTemplate);
|
|
if(bDisableEditOnTemplate)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
TSharedRef<SWindow> FPropertyEditorModule::CreateFloatingDetailsView( const TArray< UObject* >& InObjects, bool bIsLockable )
|
|
{
|
|
|
|
TSharedRef<SWindow> NewSlateWindow = SNew(SWindow)
|
|
.Title( NSLOCTEXT("PropertyEditor", "WindowTitle", "Property Editor") )
|
|
.ClientSize( FVector2D(400, 550) );
|
|
|
|
// If the main frame exists parent the window to it
|
|
TSharedPtr< SWindow > ParentWindow;
|
|
if( FModuleManager::Get().IsModuleLoaded( "MainFrame" ) )
|
|
{
|
|
IMainFrameModule& MainFrame = FModuleManager::GetModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
ParentWindow = MainFrame.GetParentWindow();
|
|
}
|
|
|
|
if( ParentWindow.IsValid() )
|
|
{
|
|
// Parent the window to the main frame
|
|
FSlateApplication::Get().AddWindowAsNativeChild( NewSlateWindow, ParentWindow.ToSharedRef() );
|
|
}
|
|
else
|
|
{
|
|
FSlateApplication::Get().AddWindow( NewSlateWindow );
|
|
}
|
|
|
|
FDetailsViewArgs Args;
|
|
Args.bHideSelectionTip = true;
|
|
Args.bLockable = bIsLockable;
|
|
|
|
FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
|
|
TSharedRef<IDetailsView> DetailView = PropertyEditorModule.CreateDetailView( Args );
|
|
|
|
bool bHaveTemplate = false;
|
|
for(int32 i=0; i<InObjects.Num(); i++)
|
|
{
|
|
if(InObjects[i] != NULL && InObjects[i]->IsTemplate())
|
|
{
|
|
bHaveTemplate = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
DetailView->SetIsPropertyVisibleDelegate( FIsPropertyVisible::CreateStatic(&ShouldShowProperty, bHaveTemplate) );
|
|
|
|
DetailView->SetObjects( InObjects );
|
|
|
|
NewSlateWindow->SetContent(
|
|
SNew(SBorder)
|
|
.BorderImage( FEditorStyle::GetBrush(TEXT("PropertyWindow.WindowBorder")) )
|
|
[
|
|
DetailView
|
|
]
|
|
);
|
|
|
|
return NewSlateWindow;
|
|
}
|
|
|
|
TSharedRef<SPropertyTreeViewImpl> FPropertyEditorModule::CreatePropertyView(
|
|
UObject* InObject,
|
|
bool bAllowFavorites,
|
|
bool bIsLockable,
|
|
bool bHiddenPropertyVisibility,
|
|
bool bAllowSearch,
|
|
bool ShowTopLevelNodes,
|
|
FNotifyHook* InNotifyHook,
|
|
float InNameColumnWidth,
|
|
FOnPropertySelectionChanged OnPropertySelectionChanged,
|
|
FOnPropertyClicked OnPropertyMiddleClicked,
|
|
FConstructExternalColumnHeaders ConstructExternalColumnHeaders,
|
|
FConstructExternalColumnCell ConstructExternalColumnCell)
|
|
{
|
|
TSharedRef<SPropertyTreeViewImpl> PropertyView =
|
|
SNew( SPropertyTreeViewImpl )
|
|
.IsLockable( bIsLockable )
|
|
.AllowFavorites( bAllowFavorites )
|
|
.HiddenPropertyVis( bHiddenPropertyVisibility )
|
|
.NotifyHook( InNotifyHook )
|
|
.AllowSearch( bAllowSearch )
|
|
.ShowTopLevelNodes( ShowTopLevelNodes )
|
|
.NameColumnWidth( InNameColumnWidth )
|
|
.OnPropertySelectionChanged( OnPropertySelectionChanged )
|
|
.OnPropertyMiddleClicked( OnPropertyMiddleClicked )
|
|
.ConstructExternalColumnHeaders( ConstructExternalColumnHeaders )
|
|
.ConstructExternalColumnCell( ConstructExternalColumnCell );
|
|
|
|
if( InObject )
|
|
{
|
|
TArray< TWeakObjectPtr< UObject > > Objects;
|
|
Objects.Add( InObject );
|
|
PropertyView->SetObjectArray( Objects );
|
|
}
|
|
|
|
return PropertyView;
|
|
}
|
|
|
|
TSharedRef<IDetailsView> FPropertyEditorModule::CreateDetailView( const FDetailsViewArgs& DetailsViewArgs )
|
|
{
|
|
// Compact the list of detail view instances
|
|
for( int32 ViewIndex = 0; ViewIndex < AllDetailViews.Num(); ++ViewIndex )
|
|
{
|
|
if ( !AllDetailViews[ViewIndex].IsValid() )
|
|
{
|
|
AllDetailViews.RemoveAtSwap( ViewIndex );
|
|
--ViewIndex;
|
|
}
|
|
}
|
|
|
|
TSharedRef<SDetailsView> DetailView =
|
|
SNew( SDetailsView )
|
|
.DetailsViewArgs( DetailsViewArgs );
|
|
|
|
AllDetailViews.Add( DetailView );
|
|
return DetailView;
|
|
}
|
|
|
|
TSharedPtr<IDetailsView> FPropertyEditorModule::FindDetailView( const FName ViewIdentifier ) const
|
|
{
|
|
if(ViewIdentifier.IsNone())
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
for(auto It = AllDetailViews.CreateConstIterator(); It; ++It)
|
|
{
|
|
TSharedPtr<SDetailsView> DetailsView = It->Pin();
|
|
if(DetailsView.IsValid() && DetailsView->GetIdentifier() == ViewIdentifier)
|
|
{
|
|
return DetailsView;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
TSharedPtr<ISinglePropertyView> FPropertyEditorModule::CreateSingleProperty( UObject* InObject, FName InPropertyName, const FSinglePropertyParams& InitParams )
|
|
{
|
|
// Compact the list of detail view instances
|
|
for( int32 ViewIndex = 0; ViewIndex < AllSinglePropertyViews.Num(); ++ViewIndex )
|
|
{
|
|
if ( !AllSinglePropertyViews[ViewIndex].IsValid() )
|
|
{
|
|
AllSinglePropertyViews.RemoveAtSwap( ViewIndex );
|
|
--ViewIndex;
|
|
}
|
|
}
|
|
|
|
TSharedRef<SSingleProperty> Property =
|
|
SNew( SSingleProperty )
|
|
.Object( InObject )
|
|
.PropertyName( InPropertyName )
|
|
.NamePlacement( InitParams.NamePlacement )
|
|
.NameOverride( InitParams.NameOverride )
|
|
.NotifyHook( InitParams.NotifyHook )
|
|
.PropertyFont( InitParams.Font );
|
|
|
|
if( Property->HasValidProperty() )
|
|
{
|
|
AllSinglePropertyViews.Add( Property );
|
|
|
|
return Property;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
TSharedRef< IPropertyTable > FPropertyEditorModule::CreatePropertyTable()
|
|
{
|
|
return MakeShareable( new FPropertyTable() );
|
|
}
|
|
|
|
TSharedRef< SWidget > FPropertyEditorModule::CreatePropertyTableWidget( const TSharedRef< class IPropertyTable >& PropertyTable )
|
|
{
|
|
return SNew( SPropertyTable, PropertyTable );
|
|
}
|
|
|
|
TSharedRef< SWidget > FPropertyEditorModule::CreatePropertyTableWidget( const TSharedRef< IPropertyTable >& PropertyTable, const TArray< TSharedRef< class IPropertyTableCustomColumn > >& Customizations )
|
|
{
|
|
return SNew( SPropertyTable, PropertyTable )
|
|
.ColumnCustomizations( Customizations );
|
|
}
|
|
|
|
TSharedRef< IPropertyTableWidgetHandle > FPropertyEditorModule::CreatePropertyTableWidgetHandle( const TSharedRef< IPropertyTable >& PropertyTable )
|
|
{
|
|
TSharedRef< FPropertyTableWidgetHandle > FWidgetHandle = MakeShareable( new FPropertyTableWidgetHandle( SNew( SPropertyTable, PropertyTable ) ) );
|
|
|
|
TSharedRef< IPropertyTableWidgetHandle > IWidgetHandle = StaticCastSharedRef<IPropertyTableWidgetHandle>(FWidgetHandle);
|
|
|
|
return IWidgetHandle;
|
|
}
|
|
|
|
TSharedRef< IPropertyTableWidgetHandle > FPropertyEditorModule::CreatePropertyTableWidgetHandle( const TSharedRef< IPropertyTable >& PropertyTable, const TArray< TSharedRef< class IPropertyTableCustomColumn > >& Customizations )
|
|
{
|
|
TSharedRef< FPropertyTableWidgetHandle > FWidgetHandle = MakeShareable( new FPropertyTableWidgetHandle( SNew( SPropertyTable, PropertyTable )
|
|
.ColumnCustomizations( Customizations )));
|
|
|
|
TSharedRef< IPropertyTableWidgetHandle > IWidgetHandle = StaticCastSharedRef<IPropertyTableWidgetHandle>(FWidgetHandle);
|
|
|
|
return IWidgetHandle;
|
|
}
|
|
|
|
TSharedRef< IPropertyTableCellPresenter > FPropertyEditorModule::CreateTextPropertyCellPresenter(const TSharedRef< class FPropertyNode >& InPropertyNode, const TSharedRef< class IPropertyTableUtilities >& InPropertyUtilities,
|
|
const FSlateFontInfo* InFontPtr /* = NULL */)
|
|
{
|
|
FSlateFontInfo InFont;
|
|
|
|
if (InFontPtr == NULL)
|
|
{
|
|
// Encapsulating reference to Private file PropertyTableConstants.h
|
|
InFont = FEditorStyle::GetFontStyle( PropertyTableConstants::NormalFontStyle );
|
|
}
|
|
else
|
|
{
|
|
InFont = *InFontPtr;
|
|
}
|
|
|
|
TSharedRef< FPropertyEditor > PropertyEditor = FPropertyEditor::Create( InPropertyNode, InPropertyUtilities );
|
|
return MakeShareable( new FTextPropertyTableCellPresenter( PropertyEditor, InPropertyUtilities, InFont) );
|
|
}
|
|
|
|
TSharedRef< FAssetEditorToolkit > FPropertyEditorModule::CreatePropertyEditorToolkit( const EToolkitMode::Type Mode, const TSharedPtr< class IToolkitHost >& InitToolkitHost, UObject* ObjectToEdit )
|
|
{
|
|
return FPropertyEditorToolkit::CreateEditor( Mode, InitToolkitHost, ObjectToEdit );
|
|
}
|
|
|
|
|
|
TSharedRef< FAssetEditorToolkit > FPropertyEditorModule::CreatePropertyEditorToolkit( const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, const TArray< UObject* >& ObjectsToEdit )
|
|
{
|
|
return FPropertyEditorToolkit::CreateEditor( Mode, InitToolkitHost, ObjectsToEdit );
|
|
}
|
|
|
|
TSharedRef< FAssetEditorToolkit > FPropertyEditorModule::CreatePropertyEditorToolkit( const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, const TArray< TWeakObjectPtr< UObject > >& ObjectsToEdit )
|
|
{
|
|
TArray< UObject* > RawObjectsToEdit;
|
|
for( auto ObjectIter = ObjectsToEdit.CreateConstIterator(); ObjectIter; ++ObjectIter )
|
|
{
|
|
RawObjectsToEdit.Add( ObjectIter->Get() );
|
|
}
|
|
|
|
return FPropertyEditorToolkit::CreateEditor( Mode, InitToolkitHost, RawObjectsToEdit );
|
|
}
|
|
|
|
TSharedRef<IPropertyChangeListener> FPropertyEditorModule::CreatePropertyChangeListener()
|
|
{
|
|
return MakeShareable( new FPropertyChangeListener );
|
|
}
|
|
|
|
|
|
void FPropertyEditorModule::RegisterCustomPropertyLayout( FName ClassName, FOnGetDetailCustomizationInstance DetailLayoutDelegate )
|
|
{
|
|
if( ClassName != NAME_None )
|
|
{
|
|
FDetailLayoutCallback Callback;
|
|
Callback.DetailLayoutDelegate = DetailLayoutDelegate;
|
|
// @todo: DetailsView: Fix me: this specifies the order in which detail layouts should be queried
|
|
Callback.Order = ClassNameToDetailLayoutNameMap.Num();
|
|
|
|
ClassNameToDetailLayoutNameMap.Add( ClassName, Callback );
|
|
}
|
|
}
|
|
|
|
void FPropertyEditorModule::RegisterStructPropertyLayout( FName StructTypeName, FOnGetStructCustomizationInstance StructLayoutDelegate )
|
|
{
|
|
if( StructTypeName != NAME_None )
|
|
{
|
|
StructTypeToLayoutMap.Add( StructTypeName, StructLayoutDelegate );
|
|
}
|
|
}
|
|
|
|
void FPropertyEditorModule::UnregisterCustomPropertyLayout( FName ClassName )
|
|
{
|
|
if( ClassName != NAME_None )
|
|
{
|
|
ClassNameToDetailLayoutNameMap.Remove( ClassName );
|
|
}
|
|
}
|
|
|
|
void FPropertyEditorModule::UnregisterStructPropertyLayout( FName StructTypeName )
|
|
{
|
|
if( StructTypeName != NAME_None )
|
|
{
|
|
StructTypeToLayoutMap.Remove( StructTypeName );
|
|
}
|
|
}
|
|
|
|
bool FPropertyEditorModule::HasUnlockedDetailViews() const
|
|
{
|
|
uint32 NumUnlockedViews = 0;
|
|
for( int32 ViewIndex = 0; ViewIndex < AllDetailViews.Num(); ++ViewIndex )
|
|
{
|
|
const TWeakPtr<SDetailsView>& DetailView = AllDetailViews[ ViewIndex ];
|
|
if( DetailView.IsValid() )
|
|
{
|
|
TSharedPtr<SDetailsView> DetailViewPin = DetailView.Pin();
|
|
if( DetailViewPin->IsUpdatable() && !DetailViewPin->IsLocked() )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Refreshes property windows with a new list of objects to view
|
|
*
|
|
* @param NewObjectList The list of objects each property window should view
|
|
*/
|
|
void FPropertyEditorModule::UpdatePropertyViews( const TArray<UObject*>& NewObjectList )
|
|
{
|
|
DestroyColorPicker();
|
|
|
|
TSet<AActor*> ValidObjects;
|
|
|
|
for( int32 ViewIndex = 0; ViewIndex < AllDetailViews.Num(); ++ViewIndex )
|
|
{
|
|
if( AllDetailViews[ ViewIndex ].IsValid() )
|
|
{
|
|
TSharedPtr<SDetailsView> DetailViewPin = AllDetailViews[ ViewIndex ].Pin();
|
|
if( DetailViewPin->IsUpdatable() )
|
|
{
|
|
if( !DetailViewPin->IsLocked() )
|
|
{
|
|
DetailViewPin->SetObjects( NewObjectList, true );
|
|
}
|
|
else
|
|
{
|
|
if( ValidObjects.Num() == 0 )
|
|
{
|
|
// Populate the valid objects list only once
|
|
UWorld* IteratorWorld = GWorld;
|
|
for( FActorIterator It(IteratorWorld); It; ++It )
|
|
{
|
|
ValidObjects.Add( *It );
|
|
}
|
|
}
|
|
|
|
// If the property window is locked make sure all the actors still exist
|
|
DetailViewPin->RemoveInvalidActors( ValidObjects );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FPropertyEditorModule::ReplaceViewedObjects( const TMap<UObject*, UObject*>& OldToNewObjectMap )
|
|
{
|
|
DestroyColorPicker();
|
|
|
|
// Replace objects from detail views
|
|
for( int32 ViewIndex = 0; ViewIndex < AllDetailViews.Num(); ++ViewIndex )
|
|
{
|
|
if( AllDetailViews[ ViewIndex ].IsValid() )
|
|
{
|
|
TSharedPtr<SDetailsView> DetailViewPin = AllDetailViews[ ViewIndex ].Pin();
|
|
|
|
DetailViewPin->ReplaceObjects( OldToNewObjectMap );
|
|
}
|
|
}
|
|
|
|
// Replace objects from single views
|
|
for( int32 ViewIndex = 0; ViewIndex < AllSinglePropertyViews.Num(); ++ViewIndex )
|
|
{
|
|
if( AllSinglePropertyViews[ ViewIndex ].IsValid() )
|
|
{
|
|
TSharedPtr<SSingleProperty> SinglePropPin = AllSinglePropertyViews[ ViewIndex ].Pin();
|
|
|
|
SinglePropPin->ReplaceObjects( OldToNewObjectMap );
|
|
}
|
|
}
|
|
}
|
|
|
|
void FPropertyEditorModule::RemoveDeletedObjects( TArray<UObject*>& DeletedObjects )
|
|
{
|
|
DestroyColorPicker();
|
|
|
|
// remove deleted objects from detail views
|
|
for( int32 ViewIndex = 0; ViewIndex < AllDetailViews.Num(); ++ViewIndex )
|
|
{
|
|
if( AllDetailViews[ ViewIndex ].IsValid() )
|
|
{
|
|
TSharedPtr<SDetailsView> DetailViewPin = AllDetailViews[ ViewIndex ].Pin();
|
|
|
|
DetailViewPin->RemoveDeletedObjects( DeletedObjects );
|
|
}
|
|
}
|
|
|
|
// remove deleted object from single property views
|
|
for( int32 ViewIndex = 0; ViewIndex < AllSinglePropertyViews.Num(); ++ViewIndex )
|
|
{
|
|
if( AllSinglePropertyViews[ ViewIndex ].IsValid() )
|
|
{
|
|
TSharedPtr<SSingleProperty> SinglePropPin = AllSinglePropertyViews[ ViewIndex ].Pin();
|
|
|
|
SinglePropPin->RemoveDeletedObjects( DeletedObjects );
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FPropertyEditorModule::IsCustomizedStruct(const UStruct* Struct) const
|
|
{
|
|
if (Struct && !Struct->IsA<UUserDefinedStruct>())
|
|
{
|
|
return StructTypeToLayoutMap.Contains(Struct->GetFName());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
FOnGetStructCustomizationInstance FPropertyEditorModule::GetStructCustomizaton(const UStruct* Struct)
|
|
{
|
|
if (Struct && !Struct->IsA<UUserDefinedStruct>())
|
|
{
|
|
return StructTypeToLayoutMap.FindRef(Struct->GetFName());
|
|
}
|
|
return FOnGetStructCustomizationInstance();
|
|
} |