// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. /*============================================================================= TextureEditorToolkit.cpp: Implements the FTextureEditorToolkit class. =============================================================================*/ #include "TextureEditorPrivatePCH.h" #include "Factories.h" #define LOCTEXT_NAMESPACE "FTextureEditorToolkit" DEFINE_LOG_CATEGORY_STATIC(LogTextureEditor, Log, All); #define MIPLEVEL_MIN 0 #define MIPLEVEL_MAX 15 #define EXPOSURE_MIN -10 #define EXPOSURE_MAX 10 const FName FTextureEditorToolkit::ViewportTabId(TEXT("TextureEditor_Viewport")); const FName FTextureEditorToolkit::PropertiesTabId(TEXT("TextureEditor_Properties")); /* FTextureEditorToolkit structors *****************************************************************************/ FTextureEditorToolkit::~FTextureEditorToolkit( ) { FReimportManager::Instance()->OnPreReimport().RemoveAll(this); FReimportManager::Instance()->OnPostReimport().RemoveAll(this); GEditor->UnregisterForUndo(this); } /* FAssetEditorToolkit interface *****************************************************************************/ void FTextureEditorToolkit::RegisterTabSpawners( const TSharedRef& TabManager ) { FAssetEditorToolkit::RegisterTabSpawners(TabManager); const IWorkspaceMenuStructure& MenuStructure = WorkspaceMenu::GetMenuStructure(); TabManager->RegisterTabSpawner( ViewportTabId, FOnSpawnTab::CreateSP(this, &FTextureEditorToolkit::SpawnTab_Viewport) ) .SetDisplayName( LOCTEXT("ViewportTab", "Viewport") ) .SetGroup( MenuStructure.GetAssetEditorCategory() ); TabManager->RegisterTabSpawner( PropertiesTabId, FOnSpawnTab::CreateSP(this, &FTextureEditorToolkit::SpawnTab_Properties) ) .SetDisplayName( LOCTEXT("PropertiesTab", "Details") ) .SetGroup( MenuStructure.GetAssetEditorCategory() ); } void FTextureEditorToolkit::UnregisterTabSpawners( const TSharedRef& TabManager ) { FAssetEditorToolkit::UnregisterTabSpawners(TabManager); TabManager->UnregisterTabSpawner( ViewportTabId ); TabManager->UnregisterTabSpawner( PropertiesTabId ); } void FTextureEditorToolkit::InitTextureEditor( const EToolkitMode::Type Mode, const TSharedPtr< class IToolkitHost >& InitToolkitHost, UObject* ObjectToEdit ) { FReimportManager::Instance()->OnPreReimport().AddRaw(this, &FTextureEditorToolkit::OnPreReimport); FReimportManager::Instance()->OnPostReimport().AddRaw(this, &FTextureEditorToolkit::OnPostReimport); Texture = CastChecked(ObjectToEdit); // Support undo/redo Texture->SetFlags(RF_Transactional); GEditor->RegisterForUndo(this); // initialize view options bIsRedChannel = true; bIsGreenChannel = true; bIsBlueChannel = true; bIsAlphaChannel = false; bIsSaturation = false; PreviewEffectiveTextureWidth = 0; PreviewEffectiveTextureHeight = 0; SpecifiedMipLevel = 0; bUseSpecifiedMipLevel = false; SavedCompressionSetting = false; Zoom = 1.0f; // Register our commands. This will only register them if not previously registered FTextureEditorCommands::Register(); BindCommands(); CreateInternalWidgets(); const TSharedRef StandaloneDefaultLayout = FTabManager::NewLayout("Standalone_TextureEditor_Layout_v3") ->AddArea ( FTabManager::NewPrimaryArea() ->SetOrientation(Orient_Horizontal) ->Split ( FTabManager::NewSplitter() ->SetOrientation(Orient_Vertical) ->SetSizeCoefficient(0.66f) ->Split ( FTabManager::NewStack() ->AddTab(GetToolbarTabId(), ETabState::OpenedTab) ->SetHideTabWell(true) ->SetSizeCoefficient(0.1f) ) ->Split ( FTabManager::NewStack() ->AddTab(ViewportTabId, ETabState::OpenedTab) ->SetHideTabWell(true) ->SetSizeCoefficient(0.9f) ) ) ->Split ( FTabManager::NewStack() ->AddTab(PropertiesTabId, ETabState::OpenedTab) ->SetSizeCoefficient(0.33f) ) ); const bool bCreateDefaultStandaloneMenu = true; const bool bCreateDefaultToolbar = true; FAssetEditorToolkit::InitAssetEditor(Mode, InitToolkitHost, TextureEditorAppIdentifier, StandaloneDefaultLayout, bCreateDefaultStandaloneMenu, bCreateDefaultToolbar, ObjectToEdit); ITextureEditorModule* TextureEditorModule = &FModuleManager::LoadModuleChecked("TextureEditor"); AddMenuExtender(TextureEditorModule->GetMenuExtensibilityManager()->GetAllExtenders(GetToolkitCommands(), GetEditingObjects())); ExtendToolBar(); RegenerateMenusAndToolbars(); // @todo toolkit world centric editing /*if(IsWorldCentricAssetEditor()) { SpawnToolkitTab(GetToolbarTabId(), FString(), EToolkitTabSpot::ToolBar); SpawnToolkitTab(ViewportTabId, FString(), EToolkitTabSpot::Viewport); SpawnToolkitTab(PropertiesTabId, FString(), EToolkitTabSpot::Details); }*/ } bool FTextureEditorToolkit::IsCubeTexture( ) const { return (Texture->IsA(UTextureCube::StaticClass()) || Texture->IsA(UTextureRenderTargetCube::StaticClass())); } /* ITextureEditorToolkit interface *****************************************************************************/ void FTextureEditorToolkit::CalculateTextureDimensions( uint32& Width, uint32& Height ) const { uint32 ImportedWidth = Texture->Source.GetSizeX(); uint32 ImportedHeight = Texture->Source.GetSizeY(); // if Original Width and Height are 0, use the saved current width and height if ((ImportedWidth == 0) && (ImportedHeight == 0)) { ImportedWidth = Texture->GetSurfaceWidth(); ImportedHeight = Texture->GetSurfaceHeight(); } Width = ImportedWidth; Height = ImportedHeight; // catch if the Width and Height are still zero for some reason if ((Width == 0) || (Height == 0)) { Width = 0; Height= 0; return; } // See if we need to uniformly scale it to fit in viewport // Cap the size to effective dimensions uint32 ViewportW = TextureViewport->GetViewport()->GetSizeXY().X; uint32 ViewportH = TextureViewport->GetViewport()->GetSizeXY().Y; uint32 MaxWidth; uint32 MaxHeight; const bool bFitToViewport = GetFitToViewport(); if (bFitToViewport) { // Subtract off the viewport space devoted to padding (2 * PreviewPadding) // so that the texture is padded on all sides MaxWidth = ViewportW; MaxHeight = ViewportH; if (IsCubeTexture()) { // Cubes are displayed 2:1. 2x width if the source exists and is not an unwrapped image. const bool bMultipleSourceImages = Texture->Source.GetNumSlices() > 1; const bool bNoSourceImage = Texture->Source.GetNumSlices() == 0; Width *= (bNoSourceImage || bMultipleSourceImages) ? 2 : 1; } // First, scale up based on the size of the viewport if (MaxWidth > MaxHeight) { Height = Height * MaxWidth / Width; Width = MaxWidth; } else { Width = Width * MaxHeight / Height; Height = MaxHeight; } // then, scale again if our width and height is impacted by the scaling if (Width > MaxWidth) { Height = Height * MaxWidth / Width; Width = MaxWidth; } if (Height > MaxHeight) { Width = Width * MaxHeight / Height; Height = MaxHeight; } } else { Width = PreviewEffectiveTextureWidth * Zoom; Height = PreviewEffectiveTextureHeight * Zoom; } } ESimpleElementBlendMode FTextureEditorToolkit::GetColourChannelBlendMode( ) const { if (Texture && (Texture->CompressionSettings == TC_Grayscale || Texture->CompressionSettings == TC_Alpha)) { return SE_BLEND_Opaque; } // Add the red, green, blue, alpha and desaturation flags to the enum to identify the chosen filters uint32 Result = (uint32)SE_BLEND_RGBA_MASK_START; Result += bIsRedChannel ? (1 << 0) : 0; Result += bIsGreenChannel ? (1 << 1) : 0; Result += bIsBlueChannel ? (1 << 2) : 0; Result += bIsAlphaChannel ? (1 << 3) : 0; // If we only have one color channel active, enable color desaturation by default const int32 NumColorChannelsActive = (bIsRedChannel ? 1 : 0) + (bIsGreenChannel ? 1 : 0) + (bIsBlueChannel ? 1 : 0); const bool bIsSaturationLocal = bIsSaturation ? true : (NumColorChannelsActive==1); Result += bIsSaturationLocal ? (1 << 4) : 0; return (ESimpleElementBlendMode)Result; } void FTextureEditorToolkit::PopulateQuickInfo( ) { UTexture2D* Texture2D = Cast(Texture); UTextureRenderTarget2D* Texture2DRT = Cast(Texture); UTextureRenderTargetCube* TextureCubeRT = Cast(Texture); UTextureCube* TextureCube = Cast(Texture); uint32 ImportedWidth = Texture->Source.GetSizeX(); uint32 ImportedHeight = Texture->Source.GetSizeY(); // If Original Width and Height are 0, use the saved current width and height if (ImportedWidth == 0 && ImportedHeight == 0) { ImportedWidth = Texture->GetSurfaceWidth(); ImportedHeight = Texture->GetSurfaceHeight(); } // In game max bias and dimensions uint32 MaxInGameWidth, MaxInGameHeight; int32 MipLevel = GSystemSettings.TextureLODSettings.CalculateLODBias(Texture); CalculateEffectiveTextureDimensions(MipLevel, MaxInGameWidth, MaxInGameHeight); // Editor bias and dimensions (takes user specified mip setting into account) Texture->UpdateCachedLODBias(!GetUseSpecifiedMip()); MipLevel = FMath::Max(GetMipLevel(), Texture->GetCachedLODBias()); CalculateEffectiveTextureDimensions(MipLevel, PreviewEffectiveTextureWidth, PreviewEffectiveTextureHeight); // Cubes are previewed as unwrapped 2D textures. // These have 2x the width of a cube face. PreviewEffectiveTextureWidth *= IsCubeTexture() ? 2 : 1; FNumberFormattingOptions Options; Options.UseGrouping = false; ImportedText->SetText( FText::Format( NSLOCTEXT("TextureEditor", "QuickInfo_Imported", "Imported: {0}x{1}"), FText::AsNumber( ImportedWidth, &Options ), FText::AsNumber( ImportedHeight, &Options ) ) ); CurrentText->SetText( FText::Format( NSLOCTEXT("TextureEditor", "QuickInfo_Displayed", "Displayed: {0}x{1}"), FText::AsNumber( FMath::Max((uint32)1, ImportedWidth >> MipLevel), &Options ), FText::AsNumber( FMath::Max((uint32)1, ImportedHeight >> MipLevel), &Options) ) ); MaxInGameText->SetText(FText::Format( NSLOCTEXT("TextureEditor", "QuickInfo_MaxInGame", "Max In-Game: {0}x{1}"), FText::AsNumber( MaxInGameWidth, &Options ), FText::AsNumber( MaxInGameHeight, &Options ))); MethodText->SetText( FText::Format( NSLOCTEXT("TextureEditor", "QuickInfo_Method", "Method: {0}"), Texture->NeverStream ? NSLOCTEXT("TextureEditor", "QuickInfo_MethodNotStreamed", "Not Streamed") : NSLOCTEXT("TextureEditor", "QuickInfo_MethodStreamed", "Streamed"))); LODBiasText->SetText(FText::Format(NSLOCTEXT("TextureEditor", "QuickInfo_LODBias", "Combined LOD Bias: {0}"), FText::AsNumber(Texture->GetCachedLODBias()))); int32 TextureFormatIndex = PF_MAX; if (Texture2D) { TextureFormatIndex = Texture2D->GetPixelFormat(); } else if (TextureCube) { TextureFormatIndex = TextureCube->GetPixelFormat(); } else if (Texture2DRT) { TextureFormatIndex = Texture2DRT->GetFormat(); } if (TextureFormatIndex != PF_MAX) { FormatText->SetText(FText::Format( NSLOCTEXT("TextureEditor", "QuickInfo_Format", "Format: {0}"), FText::FromString( GPixelFormats[TextureFormatIndex].Name ))); } } /* IToolkit interface *****************************************************************************/ FText FTextureEditorToolkit::GetBaseToolkitName() const { return LOCTEXT("AppLabel", "Texture Editor"); } FString FTextureEditorToolkit::GetWorldCentricTabPrefix() const { return LOCTEXT("WorldCentricTabPrefix", "Texture ").ToString(); } TSharedRef FTextureEditorToolkit::SpawnTab_Viewport(const FSpawnTabArgs& Args) { check( Args.GetTabId() == ViewportTabId ); return SNew(SDockTab) .Label(LOCTEXT("TextureViewportTitle", "Viewport")) [ TextureViewport.ToSharedRef() ]; } TSharedRef FTextureEditorToolkit::SpawnTab_Properties(const FSpawnTabArgs& Args) { check( Args.GetTabId() == PropertiesTabId ); TSharedRef SpawnedTab = SNew(SDockTab) .Icon(FEditorStyle::GetBrush("TextureEditor.Tabs.Properties")) .Label(LOCTEXT("TexturePropertiesTitle", "Details")) [ TextureProperties.ToSharedRef() ]; PopulateQuickInfo(); return SpawnedTab; } /* FGCObject interface *****************************************************************************/ void FTextureEditorToolkit::AddReferencedObjects( FReferenceCollector& Collector ) { Collector.AddReferencedObject(Texture); TextureViewport->AddReferencedObjects(Collector); } /* FTextureEditorToolkit static functions *****************************************************************************/ void FTextureEditorToolkit::CreateInternalWidgets() { TextureViewport = SNew(STextureEditorViewport, SharedThis(this)); TextureProperties = SNew(SVerticalBox) + SVerticalBox::Slot() .AutoHeight() .Padding(2.0f) [ SNew(SBorder) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .FillWidth(0.5f) [ SNew(SVerticalBox) + SVerticalBox::Slot() .AutoHeight() .VAlign(VAlign_Center) .Padding(4.0f) [ SAssignNew(ImportedText, STextBlock) ] + SVerticalBox::Slot() .AutoHeight() .VAlign(VAlign_Center) .Padding(4.0f) [ SAssignNew(CurrentText, STextBlock) ] + SVerticalBox::Slot() .AutoHeight() .VAlign(VAlign_Center) .Padding(4.0f) [ SAssignNew(MaxInGameText, STextBlock) ] ] + SHorizontalBox::Slot() .FillWidth(0.5f) [ SNew(SVerticalBox) + SVerticalBox::Slot() .AutoHeight() .VAlign(VAlign_Center) .Padding(4.0f) [ SAssignNew(MethodText, STextBlock) ] + SVerticalBox::Slot() .AutoHeight() .VAlign(VAlign_Center) .Padding(4.0f) [ SAssignNew(FormatText, STextBlock) ] + SVerticalBox::Slot() .AutoHeight() .VAlign(VAlign_Center) .Padding(4.0f) [ SAssignNew(LODBiasText, STextBlock) ] ] ] ] + SVerticalBox::Slot() .FillHeight(1.0f) .Padding(2.0f) [ SNew(SBorder) .Padding(4.0f) [ BuildTexturePropertiesWidget() ] ]; } TSharedRef FTextureEditorToolkit::BuildTexturePropertiesWidget() { FDetailsViewArgs Args; Args.bHideSelectionTip = true; FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked("PropertyEditor"); TexturePropertiesWidget = PropertyModule.CreateDetailView(Args); TexturePropertiesWidget->SetObject( Texture ); return TexturePropertiesWidget.ToSharedRef(); } BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void FTextureEditorToolkit::ExtendToolBar() { struct Local { static void FillToolbar(FToolBarBuilder& ToolbarBuilder, const TSharedRef< FUICommandList > ToolkitCommands, TSharedRef LODControl) { ToolbarBuilder.BeginSection("TextureMisc"); { ToolbarBuilder.AddToolBarButton(FTextureEditorCommands::Get().CompressNow); ToolbarBuilder.AddToolBarButton(FTextureEditorCommands::Get().Reimport); } ToolbarBuilder.EndSection(); ToolbarBuilder.BeginSection("TextureMipAndExposure"); { ToolbarBuilder.AddWidget(LODControl); } ToolbarBuilder.EndSection(); } }; TSharedRef LODControl = SNew(SBox) .WidthOverride(240.0f) [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .FillWidth(1.0f) .MaxWidth(240.0f) .Padding(0.0f,0.0f,0.0f,0.0f) .VAlign(VAlign_Center) [ // Mip and exposure controls SNew(SHorizontalBox) +SHorizontalBox::Slot() .Padding(4.0f,0.0f,4.0f,0.0f) .AutoWidth() [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .VAlign(VAlign_Center) .AutoWidth() [ SNew( SCheckBox ) .IsChecked( this, &FTextureEditorToolkit::OnGetUseSpecifiedMip ) .IsEnabled( this, &FTextureEditorToolkit::OnGetUseSpecifiedMipEnabled ) .OnCheckStateChanged( this, &FTextureEditorToolkit::OnUseSpecifiedMipChanged ) ] ] +SHorizontalBox::Slot() .Padding(4.0f,0.0f,4.0f,0.0f) .FillWidth(1) [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .Padding(0.0f,0.0,4.0,0.0) .AutoWidth() .VAlign(VAlign_Center) [ SNew(STextBlock) .Text(NSLOCTEXT("TextureEditor", "MipLevel", "Mip Level: ")) ] +SHorizontalBox::Slot() .VAlign(VAlign_Center) .FillWidth(1.0f) [ SNew(SNumericEntryBox) .AllowSpin(true) .MinSliderValue(MIPLEVEL_MIN) .MaxSliderValue(this, &FTextureEditorToolkit::GetMaxMipLevel) .Value(this, &FTextureEditorToolkit::GetWidgetMipLevel) .OnValueChanged(this, &FTextureEditorToolkit::OnMipLevelChanged) .IsEnabled(this, &FTextureEditorToolkit::GetUseSpecifiedMip) ] +SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) .Padding(2.0f) [ SNew(SButton) .Text(NSLOCTEXT("TextureEditor", "MipMinus", "-")) .OnClicked(this, &FTextureEditorToolkit::OnMipLevelDown) .IsEnabled(this, &FTextureEditorToolkit::GetUseSpecifiedMip) ] +SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) .Padding(2.0f) [ SNew(SButton) .Text(NSLOCTEXT("TextureEditor", "MipPlus", "+")) .OnClicked(this, &FTextureEditorToolkit::OnMipLevelUp) .IsEnabled(this, &FTextureEditorToolkit::GetUseSpecifiedMip) ] ] ] ]; TSharedPtr ToolbarExtender = MakeShareable(new FExtender); ToolbarExtender->AddToolBarExtension( "Asset", EExtensionHook::After, GetToolkitCommands(), FToolBarExtensionDelegate::CreateStatic( &Local::FillToolbar, GetToolkitCommands(), LODControl ) ); AddToolbarExtender(ToolbarExtender); ITextureEditorModule* TextureEditorModule = &FModuleManager::LoadModuleChecked( "TextureEditor" ); AddToolbarExtender(TextureEditorModule->GetToolBarExtensibilityManager()->GetAllExtenders(GetToolkitCommands(), GetEditingObjects())); } END_SLATE_FUNCTION_BUILD_OPTIMIZATION void FTextureEditorToolkit::BindCommands() { const FTextureEditorCommands& Commands = FTextureEditorCommands::Get(); ToolkitCommands->MapAction( Commands.RedChannel, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnRedChannel), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::IsRedChannelChecked)); ToolkitCommands->MapAction( Commands.GreenChannel, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnGreenChannel), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::IsGreenChannelChecked)); ToolkitCommands->MapAction( Commands.BlueChannel, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnBlueChannel), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::IsBlueChannelChecked)); ToolkitCommands->MapAction( Commands.AlphaChannel, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnAlphaChannel), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::IsAlphaChannelChecked)); ToolkitCommands->MapAction( Commands.Saturation, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnSaturation), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::IsSaturationChecked)); ToolkitCommands->MapAction( Commands.FitToViewport, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnFitToViewport), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::IsFitToViewportChecked)); ToolkitCommands->MapAction( Commands.CheckeredBackground, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::HandleBackgroundActionExecute, TextureEditorBackground_Checkered), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::HandleBackgroundActionIsChecked, TextureEditorBackground_Checkered)); ToolkitCommands->MapAction( Commands.CheckeredBackgroundFill, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::HandleBackgroundActionExecute, TextureEditorBackground_CheckeredFill), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::HandleBackgroundActionIsChecked, TextureEditorBackground_CheckeredFill)); ToolkitCommands->MapAction( Commands.SolidBackground, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::HandleBackgroundActionExecute, TextureEditorBackground_SolidColor), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::HandleBackgroundActionIsChecked, TextureEditorBackground_SolidColor)); ToolkitCommands->MapAction( Commands.TextureBorder, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnShowBorder), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FTextureEditorToolkit::IsShowBorderChecked)); ToolkitCommands->MapAction( Commands.CompressNow, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnCompressNow), FCanExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnCompressNowEnabled)); ToolkitCommands->MapAction( Commands.Reimport, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnReimport), FCanExecuteAction::CreateSP(this, &FTextureEditorToolkit::OnReimportEnabled)); ToolkitCommands->MapAction( Commands.Settings, FExecuteAction::CreateSP(this, &FTextureEditorToolkit::HandleSettingsActionExecute)); } void FTextureEditorToolkit::CalculateEffectiveTextureDimensions(int32 LODBias, uint32& EffectiveTextureWidth, uint32& EffectiveTextureHeight) { //Calculate in-game max resolution and store in EffectiveTextureWidth, EffectiveTextureHeight GSystemSettings.TextureLODSettings.ComputeInGameMaxResolution(LODBias, *Texture, (uint32 &)EffectiveTextureWidth, (uint32 &)EffectiveTextureHeight); } void FTextureEditorToolkit::OnRedChannel() { bIsRedChannel = !bIsRedChannel; } bool FTextureEditorToolkit::IsRedChannelChecked() const { return bIsRedChannel; } void FTextureEditorToolkit::OnGreenChannel() { bIsGreenChannel = !bIsGreenChannel; } bool FTextureEditorToolkit::IsGreenChannelChecked() const { return bIsGreenChannel; } void FTextureEditorToolkit::OnBlueChannel() { bIsBlueChannel = !bIsBlueChannel; } bool FTextureEditorToolkit::IsBlueChannelChecked() const { return bIsBlueChannel; } void FTextureEditorToolkit::OnAlphaChannel() { bIsAlphaChannel = !bIsAlphaChannel; } bool FTextureEditorToolkit::OnAlphaChannelCanExecute() const { const UTexture2D* Texture2D = Cast(Texture); if (Texture2D == NULL) { return false; } return Texture2D->HasAlphaChannel(); } bool FTextureEditorToolkit::IsAlphaChannelChecked() const { return bIsAlphaChannel; } void FTextureEditorToolkit::OnSaturation() { bIsSaturation = !bIsSaturation; } bool FTextureEditorToolkit::IsSaturationChecked() const { return bIsSaturation; } void FTextureEditorToolkit::OnFitToViewport() { ToggleFitToViewport(); } bool FTextureEditorToolkit::IsFitToViewportChecked() const { return GetFitToViewport(); } void FTextureEditorToolkit::HandleBackgroundActionExecute( ETextureEditorBackgrounds Background ) { UTextureEditorSettings& Settings = *GetMutableDefault(); Settings.Background = Background; Settings.PostEditChange(); } bool FTextureEditorToolkit::HandleBackgroundActionIsChecked( ETextureEditorBackgrounds Background ) { const UTextureEditorSettings& Settings = *GetDefault(); return (Background == Settings.Background); } void FTextureEditorToolkit::OnShowBorder() { UTextureEditorSettings& Settings = *GetMutableDefault(); Settings.TextureBorderEnabled = !Settings.TextureBorderEnabled; Settings.PostEditChange(); } bool FTextureEditorToolkit::IsShowBorderChecked() const { const UTextureEditorSettings& Settings = *GetDefault(); return Settings.TextureBorderEnabled; } void FTextureEditorToolkit::OnPreReimport(UObject* InObject) { // Ignore if this is regarding a different object if (InObject != Texture) { return; } // Prevent the texture from being compressed immediately, so the user can see the results SavedCompressionSetting = Texture->DeferCompression; Texture->DeferCompression = true; // Reduce the year to make sure the texture will always be reloaded even if it hasn't changed on disk FDateTime TimeStamp; if (FDateTime::Parse(Texture->SourceFileTimestamp, TimeStamp)) { TimeStamp -= FTimespan(365, 0, 0, 0); } else { TimeStamp = FDateTime::MinValue(); } Texture->SourceFileTimestamp = TimeStamp.ToString(); // Disable viewport rendering until the texture has finished re-importing TextureViewport->DisableRendering(); } void FTextureEditorToolkit::OnPostReimport(UObject* InObject, bool bSuccess) { // Ignore if this is regarding a different object if (InObject != Texture) { return; } if (!bSuccess) { // Failed, restore the compression flag Texture->DeferCompression = SavedCompressionSetting; } // Re-enable viewport rendering now that the texture should be in a known state again TextureViewport->EnableRendering(); } void FTextureEditorToolkit::OnCompressNow() { GWarn->BeginSlowTask( NSLOCTEXT("TextureEditor", "CompressNow", "Compressing 1 Textures that have Defer Compression set"), true); if (Texture->DeferCompression) { // Turn off defer compression and compress the texture Texture->DeferCompression = false; Texture->Source.Compress(); Texture->PostEditChange(); PopulateQuickInfo(); } GWarn->EndSlowTask(); } bool FTextureEditorToolkit::OnCompressNowEnabled() const { return Texture->DeferCompression != 0; } void FTextureEditorToolkit::OnReimport() { FReimportManager::Instance()->Reimport(Texture, /*bAskForNewFileIfMissing=*/true); } bool FTextureEditorToolkit::OnReimportEnabled() const { if ( Texture->IsA() || Texture->IsA() ) { return false; } return true; } void FTextureEditorToolkit::HandleSettingsActionExecute() { FModuleManager::LoadModuleChecked("Settings").ShowViewer("Editor", "ContentEditors", "TextureEditor"); } TOptional FTextureEditorToolkit::GetWidgetMipLevel() const { return SpecifiedMipLevel; } void FTextureEditorToolkit::OnMipLevelChanged(int32 NewMipLevel) { SpecifiedMipLevel = FMath::Clamp( NewMipLevel, MIPLEVEL_MIN, GetMaxMipLevel().Get(MIPLEVEL_MAX) ); } FReply FTextureEditorToolkit::OnMipLevelDown() { if (SpecifiedMipLevel > MIPLEVEL_MIN) { --SpecifiedMipLevel; } return FReply::Handled(); } FReply FTextureEditorToolkit::OnMipLevelUp() { if (SpecifiedMipLevel < GetMaxMipLevel().Get(MIPLEVEL_MAX)) { ++SpecifiedMipLevel; } return FReply::Handled(); } TOptional FTextureEditorToolkit::GetMaxMipLevel()const { const UTexture2D* Texture2D = Cast(Texture); const UTextureCube* TextureCube = Cast(Texture); const UTextureRenderTargetCube* RTTextureCube = Cast(Texture); const UTextureRenderTarget2D* RTTexture2D = Cast(Texture); if (Texture2D) { return Texture2D->GetNumMips() - 1; } if (TextureCube) { return TextureCube->GetNumMips() - 1; } if (RTTextureCube) { return RTTextureCube->GetNumMips() - 1; } if (RTTexture2D) { return RTTexture2D->GetNumMips() - 1; } return MIPLEVEL_MAX; } bool FTextureEditorToolkit::GetUseSpecifiedMip() const { if( GetMaxMipLevel().Get(MIPLEVEL_MAX) > 0 ) { if( OnGetUseSpecifiedMipEnabled() ) { return bUseSpecifiedMipLevel; } // by default this is on return true; } // disable the widgets if we have no mips return false; } double FTextureEditorToolkit::GetZoom() const { return Zoom; } void FTextureEditorToolkit::SetZoom( double ZoomValue ) { Zoom = FMath::Clamp(ZoomValue, MinZoom, MaxZoom); SetFitToViewport(false); } void FTextureEditorToolkit::ZoomIn() { SetZoom(Zoom + ZoomStep); } void FTextureEditorToolkit::ZoomOut() { SetZoom(Zoom - ZoomStep); } bool FTextureEditorToolkit::GetFitToViewport() const { const UTextureEditorSettings& Settings = *GetDefault(); return Settings.FitToViewport; } void FTextureEditorToolkit::SetFitToViewport(const bool bFitToViewport) { UTextureEditorSettings& Settings = *GetMutableDefault(); Settings.FitToViewport = bFitToViewport; Settings.PostEditChange(); } ESlateCheckBoxState::Type FTextureEditorToolkit::OnGetUseSpecifiedMip() const { return GetUseSpecifiedMip() ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked; } bool FTextureEditorToolkit::OnGetUseSpecifiedMipEnabled() const { UTextureCube* TextureCube = Cast(Texture); if( GetMaxMipLevel().Get(MIPLEVEL_MAX) <= 0 || TextureCube ) { return false; } return true; } void FTextureEditorToolkit::OnUseSpecifiedMipChanged(ESlateCheckBoxState::Type InNewState) { bUseSpecifiedMipLevel = InNewState == ESlateCheckBoxState::Checked; } #undef LOCTEXT_NAMESPACE