Files
UnrealEngineUWP/Engine/Source/Editor/WorldBrowser/Private/StreamingLevels/StreamingLevelCustomization.cpp
Wes Hunt 31e2bb00ac Removed a bunch of stuff from Slate standard include, created SlateBasics.h
* Moved Slate.h into SlateBasics.h and began shifting less commonly used headers into SlateExtras.h.
* Slate.h now simply includes SlateBasics.h and SlateExtras.h.
* Slate.h includes a deprecated warning now to indicate that SlateBasics.h + specific includes should be used instead.
* Moved dozens of inlined functions using Slate widgets into .cpp files to avoid header dependencies.
* All code samples now include SlateBasics.h and SlateExtras.h so future shifts will not break most those projects, but not trigger the deprecation warning of including Slate.h.
#BUN

[CL 2329610 by Wes Hunt in Main branch]
2014-10-14 22:50:06 -04:00

292 lines
9.5 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "WorldBrowserPrivatePCH.h"
#include "Editor/PropertyEditor/Public/IDetailsView.h"
#include "Editor/PropertyEditor/Public/PropertyEditing.h"
#include "Editor/PropertyEditor/Public/PropertyEditorModule.h"
#include "SVectorInputBox.h"
#include "SRotatorInputBox.h"
#include "SWorldDetails.h"
#include "StreamingLevelCollectionModel.h"
#include "StreamingLevelCustomization.h"
#include "StreamingLevelEdMode.h"
#include "SNumericEntryBox.h"
#define LOCTEXT_NAMESPACE "WorldBrowser"
/////////////////////////////////////////////////////
// FWorldTileDetails
FStreamingLevelCustomization::FStreamingLevelCustomization()
: bSliderMovement(false)
{
}
TSharedRef<IDetailCustomization> FStreamingLevelCustomization::MakeInstance(TSharedRef<FStreamingLevelCollectionModel> InWorldModel)
{
TSharedRef<FStreamingLevelCustomization> Instance = MakeShareable(new FStreamingLevelCustomization());
Instance->WorldModel = InWorldModel;
return Instance;
}
void FStreamingLevelCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailLayoutBuilder)
{
IDetailCategoryBuilder& LevelStreamingCategory = DetailLayoutBuilder.EditCategory("LevelStreaming");
// Hide level transform
TSharedPtr<IPropertyHandle> LevelTransformProperty = DetailLayoutBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(ULevelStreaming, LevelTransform));
DetailLayoutBuilder.HideProperty(LevelTransformProperty);
LevelPositionProperty = LevelTransformProperty->GetChildHandle("Translation");
LevelRotationProperty = LevelTransformProperty->GetChildHandle("Rotation");
// Add Position property
LevelStreamingCategory.AddCustomRow(LOCTEXT("Position", "Position").ToString())
.NameContent()
[
SNew(STextBlock)
.Text(LOCTEXT("Position", "Position"))
.Font(IDetailLayoutBuilder::GetDetailFont())
]
.ValueContent()
.MinDesiredWidth(500)
[
SNew(SVectorInputBox)
.IsEnabled(this, &FStreamingLevelCustomization::LevelEditTextTransformAllowed)
.Font(FEditorStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
.bColorAxisLabels(true)
.X(this, &FStreamingLevelCustomization::OnGetLevelPosition, 0)
.Y(this, &FStreamingLevelCustomization::OnGetLevelPosition, 1)
.Z(this, &FStreamingLevelCustomization::OnGetLevelPosition, 2)
.OnXCommitted(this, &FStreamingLevelCustomization::OnSetLevelPosition, 0)
.OnYCommitted(this, &FStreamingLevelCustomization::OnSetLevelPosition, 1)
.OnZCommitted(this, &FStreamingLevelCustomization::OnSetLevelPosition, 2)
];
// Add Yaw Rotation property
LevelStreamingCategory.AddCustomRow(LOCTEXT("Rotation", "Rotation").ToString())
.NameContent()
[
SNew(STextBlock)
.Text(LOCTEXT("Rotation", "Rotation"))
.Font(IDetailLayoutBuilder::GetDetailFont())
]
.ValueContent()
.MinDesiredWidth(500)
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.FillWidth(1.f)
.Padding(0,2,0,2)
[
SNew(SNumericEntryBox<int32>)
.IsEnabled(this, &FStreamingLevelCustomization::LevelEditTextTransformAllowed)
.Font(FEditorStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
.UndeterminedString(LOCTEXT("MultipleValues", "Multiple Values"))
//.Delta(90)
.AllowSpin(true)
.MinValue(0)
.MaxValue(360 - 1)
.MinSliderValue(0)
.MaxSliderValue(360 - 1)
.Value(this, &FStreamingLevelCustomization::GetLevelRotation)
.OnValueChanged(this, &FStreamingLevelCustomization::OnSetLevelRotation)
.OnBeginSliderMovement(this, &FStreamingLevelCustomization::OnBeginLevelRotatonSlider)
.OnEndSliderMovement(this, &FStreamingLevelCustomization::OnEndLevelRotatonSlider)
.LabelPadding(0)
.Label()
[
SNumericEntryBox<float>::BuildLabel(LOCTEXT("LevelRotation_Label", "Yaw"), FLinearColor::White, SNumericEntryBox<int32>::BlueLabelBackgroundColor)
]
]
+SHorizontalBox::Slot()
.AutoWidth()
[
SNew( SButton )
.Text(LOCTEXT("EditLevelTransform", "Viewport Edit"))
.ToolTipText(LOCTEXT("EditLevelToolTip", "Edit level transform in viewport."))
.OnClicked(this, &FStreamingLevelCustomization::OnEditLevelClicked)
.IsEnabled(this, &FStreamingLevelCustomization::LevelViewportTransformAllowed)
.ContentPadding(1)
]
];
}
void FStreamingLevelCustomization::OnSetLevelPosition( float NewValue, ETextCommit::Type CommitInfo, int32 Axis )
{
TSharedPtr<FStreamingLevelCollectionModel> CollectionModel = WorldModel.Pin();
if (CollectionModel.IsValid())
{
FLevelModelList SelectedLevels = CollectionModel->GetSelectedLevels();
for (auto It = SelectedLevels.CreateIterator(); It; ++It)
{
TSharedPtr<FStreamingLevelModel> LevelModel = StaticCastSharedPtr<FStreamingLevelModel>(*It);
if (LevelModel->IsEditable() && LevelModel->GetLevelStreaming().IsValid())
{
ULevelStreaming* LevelStreaming = LevelModel->GetLevelStreaming().Get();
// Create transform with new translation
FTransform LevelTransform = LevelStreaming->LevelTransform;
FVector LevelTraslation = LevelTransform.GetTranslation();
LevelTraslation[Axis] = NewValue;
LevelTransform.SetTranslation(LevelTraslation);
// Transform level
FLevelUtils::SetEditorTransform(LevelStreaming, LevelTransform);
}
}
}
}
TOptional<float> FStreamingLevelCustomization::OnGetLevelPosition( int32 Axis ) const
{
float AxisVal = 0.f;
if (LevelPositionProperty->GetChildHandle(Axis)->GetValue(AxisVal) == FPropertyAccess::Success)
{
return AxisVal;
}
return TOptional<float>();
}
void FStreamingLevelCustomization::OnSetLevelRotation( int32 NewValue )
{
CachedYawValue = NewValue;
if (bSliderMovement)
{
return;
}
// Apply rotation when user stops slider drag
TSharedPtr<FStreamingLevelCollectionModel> CollectionModel = WorldModel.Pin();
if (CollectionModel.IsValid())
{
FQuat NewRotaion = FRotator(0.f, (float)CachedYawValue.GetValue(), 0.f).Quaternion();
FLevelModelList SelectedLevels = CollectionModel->GetSelectedLevels();
for (auto It = SelectedLevels.CreateIterator(); It; ++It)
{
TSharedPtr<FStreamingLevelModel> LevelModel = StaticCastSharedPtr<FStreamingLevelModel>(*It);
if (LevelModel->IsEditable() && LevelModel->GetLevelStreaming().IsValid())
{
ULevelStreaming* LevelStreaming = LevelModel->GetLevelStreaming().Get();
FTransform LevelTransform = LevelStreaming->LevelTransform;
if (LevelTransform.GetRotation() != NewRotaion)
{
LevelTransform.SetRotation(NewRotaion);
FLevelUtils::SetEditorTransform(LevelStreaming, LevelTransform);
}
}
}
}
}
void FStreamingLevelCustomization::OnBeginLevelRotatonSlider()
{
CachedYawValue = GetLevelRotation();
bSliderMovement = true;
}
void FStreamingLevelCustomization::OnEndLevelRotatonSlider( int32 NewValue )
{
bSliderMovement = false;
OnSetLevelRotation(NewValue);
}
TOptional<int32> FStreamingLevelCustomization::GetLevelRotation() const
{
if (bSliderMovement)
{
return CachedYawValue;
}
// If were not using the spin box use the actual transform instead of cached as it may have changed with the view port widget
FQuat RotQ;
if (LevelRotationProperty->GetValue(RotQ) == FPropertyAccess::Success)
{
int32 YawValue = FMath::RoundToInt(RotQ.Rotator().Yaw);
return YawValue < 0 ? (YawValue + 360) : YawValue;
}
return TOptional<int32>();
}
bool FStreamingLevelCustomization::LevelViewportTransformAllowed() const
{
TSharedPtr<FStreamingLevelCollectionModel> CollectionModel = WorldModel.Pin();
if (CollectionModel.IsValid() && CollectionModel->IsOneLevelSelected())
{
auto SelectedLevel = CollectionModel->GetSelectedLevels()[0];
return SelectedLevel->IsEditable() && SelectedLevel->IsVisible();
}
return false;
}
bool FStreamingLevelCustomization::LevelEditTextTransformAllowed() const
{
TSharedPtr<FStreamingLevelCollectionModel> CollectionModel = WorldModel.Pin();
if (!CollectionModel.IsValid() || !CollectionModel->AreAnySelectedLevelsEditable())
{
return false;
}
auto LevelModel = StaticCastSharedPtr<FStreamingLevelModel>(CollectionModel->GetSelectedLevels()[0]);
ULevelStreaming* LevelStreaming = LevelModel->GetLevelStreaming().Get();
auto* ActiveMode = static_cast<FStreamingLevelEdMode*>(
GLevelEditorModeTools().GetActiveMode(FBuiltinEditorModes::EM_StreamingLevel)
);
if (ActiveMode && ActiveMode->IsEditing(LevelStreaming) == true)
{
return false;
}
return CollectionModel->AreAnySelectedLevelsEditable();
}
FReply FStreamingLevelCustomization::OnEditLevelClicked()
{
TSharedPtr<FStreamingLevelCollectionModel> CollectionModel = WorldModel.Pin();
if (!CollectionModel.IsValid() || !CollectionModel->AreAnySelectedLevelsEditable())
{
return FReply::Handled();
}
auto LevelModel = StaticCastSharedPtr<FStreamingLevelModel>(CollectionModel->GetSelectedLevels()[0]);
ULevelStreaming* LevelStreaming = LevelModel->GetLevelStreaming().Get();
if (!LevelStreaming)
{
return FReply::Handled();
}
if (!GLevelEditorModeTools().IsModeActive(FBuiltinEditorModes::EM_StreamingLevel))
{
// Activate Level Mode if it was not active
GLevelEditorModeTools().ActivateMode(FBuiltinEditorModes::EM_StreamingLevel);
}
auto* ActiveMode = GLevelEditorModeTools().GetActiveModeTyped<FStreamingLevelEdMode>(FBuiltinEditorModes::EM_StreamingLevel);
check(ActiveMode != NULL);
if (ActiveMode->IsEditing(LevelStreaming) == true)
{
// Toggle this mode off if already editing this level
GLevelEditorModeTools().DeactivateMode(FBuiltinEditorModes::EM_StreamingLevel);
// ActiveMode is now invalid
}
else
{
// Set the level we now want to edit
ActiveMode->SetLevel(LevelStreaming);
}
return FReply::Handled();
}
#undef LOCTEXT_NAMESPACE