// Copyright Epic Games, Inc. All Rights Reserved. #include "LevelInstanceActorDetails.h" #include "LevelInstance/LevelInstanceSettings.h" #include "LevelInstance/LevelInstanceSubsystem.h" #include "DetailLayoutBuilder.h" #include "DetailCategoryBuilder.h" #include "DetailWidgetRow.h" #include "UObject/WeakInterfacePtr.h" #include "Widgets/Input/SButton.h" #include "Widgets/Text/STextBlock.h" #include "ScopedTransaction.h" #include "Engine/World.h" #include "LevelInstance/LevelInstanceInterface.h" #define LOCTEXT_NAMESPACE "FLevelInstanceActorDetails" struct FLevelInstanceActorDetailsHelper { static void ResetPropertyOverrides(ILevelInstanceInterface* LevelInstance) { check(LevelInstance); LevelInstance->GetLevelInstanceSubsystem()->ResetPropertyOverrides(LevelInstance); } }; namespace LevelInstanceActorDetailsCallbacks { static bool IsEditButtonEnabled(TWeakInterfacePtr LevelInstancePtr) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { return LevelInstance->CanEnterEdit(); } return false; } static FText GetEditButtonTooltip(TWeakInterfacePtr LevelInstancePtr) { FText Reason; if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { if (!LevelInstance->IsEditing()) { if (!LevelInstance->CanEnterEdit(&Reason)) { return Reason; } return LOCTEXT("EditButtonToolTip", "Edit level instance source level"); } } return FText::GetEmpty(); } static EVisibility GetEditButtonVisibility(TWeakInterfacePtr LevelInstancePtr) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { return (!LevelInstance->IsEditing() && !LevelInstance->IsEditingPropertyOverrides()) ? EVisibility::Visible : EVisibility::Collapsed; } return EVisibility::Collapsed; } static FReply OnEditButtonClicked(TWeakInterfacePtr LevelInstancePtr) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { if (LevelInstance->CanEnterEdit()) { LevelInstance->EnterEdit(); } } return FReply::Handled(); } static bool IsOverrideButtonEnabled(TWeakInterfacePtr LevelInstancePtr) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { return LevelInstance->CanEnterEditPropertyOverrides(); } return false; } static EVisibility GetOverrideButtonVisibility(TWeakInterfacePtr LevelInstancePtr) { if (ULevelInstanceSettings::Get()->IsPropertyOverrideEnabled()) { return GetEditButtonVisibility(LevelInstancePtr); } return EVisibility::Collapsed; } static FText GetOverrideButtonTooltip(TWeakInterfacePtr LevelInstancePtr) { FText Reason; if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { if (!LevelInstance->IsEditingPropertyOverrides()) { if (!LevelInstance->CanEnterEditPropertyOverrides(&Reason)) { return Reason; } return LOCTEXT("OverrideButtonToolTip", "Override properties on level instance actors"); } } return FText::GetEmpty(); } static FReply OnOverrideButtonClicked(TWeakInterfacePtr LevelInstancePtr) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { if (LevelInstance->CanEnterEditPropertyOverrides()) { LevelInstance->EnterEditPropertyOverrides(); } } return FReply::Handled(); } static bool IsResetOverridesButtonEnabled(TWeakInterfacePtr LevelInstancePtr) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { return LevelInstance->GetPropertyOverrideAsset() != nullptr; } return false; } static FText GetResetOverridesButtonTooltip(TWeakInterfacePtr LevelInstancePtr) { return LOCTEXT("ResetOverrideButtonToolTip", "Reset property overrides on level instance actor"); } static FReply OnResetOverridesButtonClicked(TWeakInterfacePtr LevelInstancePtr) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { FLevelInstanceActorDetailsHelper::ResetPropertyOverrides(LevelInstance); } return FReply::Handled(); } static EVisibility GetResetOverridesButtonVisibility(TWeakInterfacePtr LevelInstancePtr) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { AActor* Actor = CastChecked(LevelInstance); return ULevelInstanceSettings::Get()->IsPropertyOverrideEnabled() && !LevelInstance->IsEditing() && !LevelInstance->IsEditingPropertyOverrides() && (!Actor->IsInLevelInstance() || Actor->IsInEditLevelInstance()) ? EVisibility::Visible : EVisibility::Collapsed; } return EVisibility::Collapsed; } static EVisibility GetSaveCancelButtonVisibility(TWeakInterfacePtr LevelInstancePtr) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { return (LevelInstance->IsEditing() || LevelInstance->IsEditingPropertyOverrides()) ? EVisibility::Visible : EVisibility::Collapsed; } return EVisibility::Collapsed; } static bool IsSaveCancelButtonEnabled(TWeakInterfacePtr LevelInstancePtr, bool bDiscard) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { if (LevelInstance->IsEditing()) { return LevelInstance->CanExitEdit(bDiscard); } else if (LevelInstance->IsEditingPropertyOverrides()) { return LevelInstance->CanExitEditPropertyOverrides(bDiscard); } } return false; } static FText GetSaveCancelButtonTooltip(TWeakInterfacePtr LevelInstancePtr, bool bDiscard) { FText Reason; if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { if (LevelInstance->IsEditing()) { if (!LevelInstance->CanExitEdit(bDiscard, &Reason)) { return Reason; } return bDiscard ? LOCTEXT("CancelButtonToolTip", "Cancel edits and exit") : LOCTEXT("SaveButtonToolTip", "Save edits and exit"); } else if (LevelInstance->IsEditingPropertyOverrides()) { if (!LevelInstance->CanExitEditPropertyOverrides(bDiscard, &Reason)) { return Reason; } return bDiscard ? LOCTEXT("CancelOverrideButtonToolTip", "Cancel overrides and exit") : LOCTEXT("SaveOverrideButtonToolTip", "Save overrides and exit"); } } return FText::GetEmpty(); } static FReply OnSaveCancelButtonClicked(TWeakInterfacePtr LevelInstancePtr, bool bDiscard) { if (ILevelInstanceInterface* LevelInstance = LevelInstancePtr.Get()) { if (LevelInstance->IsEditing()) { LevelInstance->ExitEdit(bDiscard); } else if (LevelInstance->IsEditingPropertyOverrides()) { LevelInstance->ExitEditPropertyOverrides(bDiscard); } } return FReply::Handled(); } } FLevelInstanceActorDetails::FLevelInstanceActorDetails() { } TSharedRef FLevelInstanceActorDetails::MakeInstance() { return MakeShareable(new FLevelInstanceActorDetails); } void FLevelInstanceActorDetails::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) { TArray> EditingObjects; DetailBuilder.GetObjectsBeingCustomized(EditingObjects); if (EditingObjects.Num() > 1) { return; } TWeakInterfacePtr LevelInstance = Cast(EditingObjects[0].Get()); UWorld* World = LevelInstance.GetObject()->GetWorld(); if (!World) { return; } if (ULevelInstancePropertyOverrideAsset* PropertyOverride = LevelInstance->GetPropertyOverrideAsset()) { DetailBuilder.HideProperty("WorldAsset"); } IDetailCategoryBuilder& LevelInstanceEditingCategory = DetailBuilder.EditCategory("LevelInstanceEdit", LOCTEXT("LevelInstanceEditCategory", "Level Instance"), ECategoryPriority::Transform); LevelInstanceEditingCategory.AddCustomRow(FText::GetEmpty()).ValueContent() [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() .Padding(4.0f, 8.0f, 4.0f, 8.0f) .VAlign(VAlign_Center) [ SNew(SButton) .IsEnabled_Static(&LevelInstanceActorDetailsCallbacks::IsEditButtonEnabled, LevelInstance) .ToolTipText_Static(&LevelInstanceActorDetailsCallbacks::GetEditButtonTooltip, LevelInstance) .Visibility_Static(&LevelInstanceActorDetailsCallbacks::GetEditButtonVisibility, LevelInstance) .HAlign(HAlign_Center) .VAlign(VAlign_Center) .OnClicked_Static(&LevelInstanceActorDetailsCallbacks::OnEditButtonClicked, LevelInstance) [ SNew(STextBlock) .Font(IDetailLayoutBuilder::GetDetailFont()) .Text(LOCTEXT("EditText", "Edit")) ] ] + SHorizontalBox::Slot() .AutoWidth() .Padding(4.0f, 8.0f, 4.0f, 8.0f) .VAlign(VAlign_Center) [ SNew(SButton) .IsEnabled_Static(&LevelInstanceActorDetailsCallbacks::IsOverrideButtonEnabled, LevelInstance) .ToolTipText_Static(&LevelInstanceActorDetailsCallbacks::GetOverrideButtonTooltip, LevelInstance) .Visibility_Static(&LevelInstanceActorDetailsCallbacks::GetOverrideButtonVisibility, LevelInstance) .HAlign(HAlign_Center) .VAlign(VAlign_Center) .OnClicked_Static(&LevelInstanceActorDetailsCallbacks::OnOverrideButtonClicked, LevelInstance) [ SNew(STextBlock) .Font(IDetailLayoutBuilder::GetDetailFont()) .Text(LOCTEXT("OverrideText", "Override")) ] ] + SHorizontalBox::Slot() .AutoWidth() .Padding(4.0f, 8.0f, 8.0f, 8.0f) .VAlign(VAlign_Center) [ SNew(SButton) .IsEnabled_Static(&LevelInstanceActorDetailsCallbacks::IsResetOverridesButtonEnabled, LevelInstance) .ToolTipText_Static(&LevelInstanceActorDetailsCallbacks::GetResetOverridesButtonTooltip, LevelInstance) .Visibility_Static(&LevelInstanceActorDetailsCallbacks::GetResetOverridesButtonVisibility, LevelInstance) .HAlign(HAlign_Center) .VAlign(VAlign_Center) .OnClicked_Static(&LevelInstanceActorDetailsCallbacks::OnResetOverridesButtonClicked, LevelInstance) [ SNew(STextBlock) .Font(IDetailLayoutBuilder::GetDetailFont()) .Text(LOCTEXT("ResetOverrideText", "Reset Overrides")) ] ] + SHorizontalBox::Slot() .AutoWidth() .Padding(4.0f, 8.0f, 4.0f, 8.0f) .VAlign(VAlign_Center) [ SNew(SButton) .ButtonStyle(FAppStyle::Get(), "PrimaryButton") .IsEnabled_Static(&LevelInstanceActorDetailsCallbacks::IsSaveCancelButtonEnabled, LevelInstance, false) .ToolTipText_Static(&LevelInstanceActorDetailsCallbacks::GetSaveCancelButtonTooltip, LevelInstance, false) .Visibility_Static(&LevelInstanceActorDetailsCallbacks::GetSaveCancelButtonVisibility, LevelInstance) .HAlign(HAlign_Center) .VAlign(VAlign_Center) .OnClicked_Static(&LevelInstanceActorDetailsCallbacks::OnSaveCancelButtonClicked, LevelInstance, false) [ SNew(STextBlock) .Font(IDetailLayoutBuilder::GetDetailFont()) .Text(LOCTEXT("SaveText", "Save")) ] ] + SHorizontalBox::Slot() .AutoWidth() .Padding(4.0f, 8.0f, 4.0f, 8.0f) .VAlign(VAlign_Center) [ SNew(SButton) .IsEnabled_Static(&LevelInstanceActorDetailsCallbacks::IsSaveCancelButtonEnabled, LevelInstance, true) .ToolTipText_Static(&LevelInstanceActorDetailsCallbacks::GetSaveCancelButtonTooltip, LevelInstance, true) .Visibility_Static(&LevelInstanceActorDetailsCallbacks::GetSaveCancelButtonVisibility, LevelInstance) .Text(LOCTEXT("DiscardText", "Discard")) .HAlign(HAlign_Center) .VAlign(VAlign_Center) .OnClicked_Static(&LevelInstanceActorDetailsCallbacks::OnSaveCancelButtonClicked, LevelInstance, true) [ SNew(STextBlock) .Font(IDetailLayoutBuilder::GetDetailFont()) .Text(LOCTEXT("CancelText", "Cancel")) ] ] ]; } #undef LOCTEXT_NAMESPACE