// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. #include "DetailCustomizationsPrivatePCH.h" #include "DirectoryPathStructCustomization.h" #include "DesktopPlatformModule.h" #include "ContentBrowserDelegates.h" #define LOCTEXT_NAMESPACE "DirectoryPathStructCustomization" TSharedRef FDirectoryPathStructCustomization::MakeInstance() { return MakeShareable(new FDirectoryPathStructCustomization()); } void FDirectoryPathStructCustomization::CustomizeHeader( TSharedRef StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils ) { TSharedPtr PathProperty = StructPropertyHandle->GetChildHandle("Path"); const bool bRelativeToGameContentDir = StructPropertyHandle->HasMetaData( TEXT("RelativeToGameContentDir") ); const bool bUseRelativePath = StructPropertyHandle->HasMetaData( TEXT("RelativePath") ); AbsoluteGameContentDir = FPaths::ConvertRelativePathToFull(FPaths::GameContentDir()); if(PathProperty.IsValid()) { HeaderRow.ValueContent() .MinDesiredWidth(125.0f) .MaxDesiredWidth(600.0f) [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .FillWidth(1.0f) .VAlign(VAlign_Center) [ PathProperty->CreatePropertyValueWidget() ] +SHorizontalBox::Slot() .AutoWidth() .Padding(FMargin(4.0f, 0.0f, 0.0f, 0.0f)) .VAlign(VAlign_Center) [ SAssignNew(BrowseButton, SButton) .ButtonStyle( FEditorStyle::Get(), "HoverHintOnly" ) .ToolTipText( LOCTEXT( "FolderButtonToolTipText", "Choose a directory from this computer") ) .OnClicked( FOnClicked::CreateSP(this, &FDirectoryPathStructCustomization::OnPickDirectory, PathProperty.ToSharedRef(), bRelativeToGameContentDir, bUseRelativePath) ) .ContentPadding( 2.0f ) .ForegroundColor( FSlateColor::UseForeground() ) .IsFocusable( false ) [ SNew( SImage ) .Image( FEditorStyle::GetBrush("PropertyWindow.Button_Ellipsis") ) .ColorAndOpacity( FSlateColor::UseForeground() ) ] ] ] .NameContent() [ StructPropertyHandle->CreatePropertyNameWidget() ]; } } void FDirectoryPathStructCustomization::CustomizeChildren( TSharedRef StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils ) { } FReply FDirectoryPathStructCustomization::OnPickDirectory(TSharedRef PropertyHandle, const bool bRelativeToGameContentDir, const bool bUseRelativePath) const { FString Directory; IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); if ( DesktopPlatform ) { TSharedPtr ParentWindow = FSlateApplication::Get().FindWidgetWindow(BrowseButton.ToSharedRef()); void* ParentWindowHandle = (ParentWindow.IsValid() && ParentWindow->GetNativeWindow().IsValid()) ? ParentWindow->GetNativeWindow()->GetOSWindowHandle() : nullptr; FString StartDirectory = FEditorDirectories::Get().GetLastDirectory(ELastDirectory::GENERIC_IMPORT); if(bRelativeToGameContentDir && !IsValidPath(StartDirectory, bRelativeToGameContentDir)) { StartDirectory = AbsoluteGameContentDir; } // Loop until; a) the user cancels (OpenDirectoryDialog returns false), or, b) the chosen path is valid (IsValidPath returns true) for(;;) { if( DesktopPlatform->OpenDirectoryDialog(ParentWindowHandle, LOCTEXT("FolderDialogTitle", "Choose a directory").ToString(), StartDirectory, Directory) ) { FText FailureReason; if( IsValidPath(Directory, bRelativeToGameContentDir, &FailureReason) ) { FEditorDirectories::Get().SetLastDirectory(ELastDirectory::GENERIC_IMPORT, Directory); if( bRelativeToGameContentDir ) { Directory = Directory.RightChop(AbsoluteGameContentDir.Len()); } if( bUseRelativePath ) { Directory = IFileManager::Get().ConvertToRelativePath(*Directory); } PropertyHandle->SetValue(Directory); } else { StartDirectory = Directory; FMessageDialog::Open(EAppMsgType::Ok, FailureReason); continue; } } break; } } return FReply::Handled(); } bool FDirectoryPathStructCustomization::IsValidPath(const FString& AbsolutePath, const bool bRelativeToGameContentDir, FText* const OutReason) const { if(bRelativeToGameContentDir) { if(!AbsolutePath.StartsWith(AbsoluteGameContentDir)) { if(OutReason) { *OutReason = FText::Format(LOCTEXT("Error_InvalidRootPath", "The chosen directory must be within {0}"), FText::FromString(AbsoluteGameContentDir)); } return false; } } return true; } #undef LOCTEXT_NAMESPACE