October3d55/M/LGUI/Source/LGUIComponentVisualizer/Private/ComponentVisualizer/UIItemComponentVisualizer.cpp

363 lines
14 KiB
C++

// Copyright 2019-Present LexLiu. All Rights Reserved.
#include "UIItemComponentVisualizer.h"
#include "Core/ActorComponent/UIItem.h"
#include "LGUIComponentVisualizerModule.h"
#include "LGUI.h"
#include "LGUIEditorUtils.h"
#include "Utils/LGUIUtils.h"
#include "Interfaces/IPluginManager.h"
#include "Core/LGUISettings.h"
#include "Layout/UIPanelLayoutBase.h"
#include "PrefabSystem/LGUIPrefabManager.h"
#if LGUI_CAN_DISABLE_OPTIMIZATION
UE_DISABLE_OPTIMIZATION
#endif
#define LOCTEXT_NAMESPACE "UIItemComponentVisualizer"
FUIItemComponentVisualizer::FUIItemComponentVisualizer()
: FComponentVisualizer()
{
}
void FUIItemComponentVisualizer::DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI)
{
auto UIItem = Cast<UUIItem>(Component);
if (!UIItem)return;
TargetComp = (UUIItem*)UIItem;
if (TargetComp->GetWorld() != View->Family->Scene->GetWorld())return;
auto Center = TargetComp->GetLocalSpaceCenter();
auto Left = TargetComp->GetLocalSpaceLeft();
auto Right = TargetComp->GetLocalSpaceRight();
auto Bottom = TargetComp->GetLocalSpaceBottom();
auto Top = TargetComp->GetLocalSpaceTop();
auto LeftPoint = TargetComp->GetComponentTransform().TransformPosition(FVector(0, Left, Center.Y));
auto RightPoint = TargetComp->GetComponentTransform().TransformPosition(FVector(0, Right, Center.Y));
auto BottomPoint = TargetComp->GetComponentTransform().TransformPosition(FVector(0, Center.X, Bottom));
auto TopPoint = TargetComp->GetComponentTransform().TransformPosition(FVector(0, Center.X, Top));
auto LeftBottomPoint = TargetComp->GetComponentTransform().TransformPosition(FVector(0, Left, Bottom));
auto LeftTopPoint = TargetComp->GetComponentTransform().TransformPosition(FVector(0, Left, Top));
auto RightBottomPoint = TargetComp->GetComponentTransform().TransformPosition(FVector(0, Right, Bottom));
auto RightTopPoint = TargetComp->GetComponentTransform().TransformPosition(FVector(0, Right, Top));
auto Area = TargetComp->GetWidth() * TargetComp->GetHeight();
Area = FMath::Sqrt(Area);
auto DrawHitProxy = [=, this](FVector Position, EUIItemVisualizerSelectorType Type, UTexture2D* IconTexture, float AreaMultiply = 1.0f) {
float DistScale = View->WorldToScreen(Position).W * (4.0f / View->UnscaledViewRect.Width() / View->ViewMatrices.GetProjectionMatrix().M[0][0]);
float Scale = DistScale * 0.25f;
float AreaScale = 100 - DistScale / (Area * 0.001f) * AreaMultiply;
AreaScale = FMath::Clamp(AreaScale, 0.0f, 1.0f);
if (AreaScale > 0.01f)
{
auto Color = FLinearColor(1, 1, 1, AreaScale);
PDI->SetHitProxy(new HUIItemAnchorVisProxy(TargetComp.Get(), Type));
PDI->DrawSprite(Position, IconTexture->GetSizeX() * Scale, IconTexture->GetSizeY() * Scale, IconTexture->GetResource(), Color, SDPG_Foreground, 0.0f, 0.0f, 0.0f, 0.0f, SE_BLEND_AlphaBlend);
PDI->SetHitProxy(NULL);
}
};
static FString LGUIBasePath = IPluginManager::Get().FindPlugin(TEXT("LGUI"))->GetBaseDir();
//draw panel layout button
bool bHaveDrawPanelLayout = false;
if (auto Parent = TargetComp->GetParentUIItem())
{
if (auto PanelLayout = Parent->GetOwner()->FindComponentByClass<UUIPanelLayoutBase>())
{
if (auto Slot = PanelLayout->GetChildSlot(TargetComp.Get()))
{
if (!Slot->GetIgnoreLayout())
{
const float AreaScale = 3.0f;
static auto PanelLayoutReorderButton_Left_Texture = LGUIEditorUtils::LoadTexture(LGUIBasePath + TEXT("/Resources/Icons/PanelLayoutReorderButton_Left.png"));
static auto PanelLayoutReorderButton_Right_Texture = LGUIEditorUtils::LoadTexture(LGUIBasePath + TEXT("/Resources/Icons/PanelLayoutReorderButton_Right.png"));
static auto PanelLayoutReorderButton_Top_Texture = LGUIEditorUtils::LoadTexture(LGUIBasePath + TEXT("/Resources/Icons/PanelLayoutReorderButton_Top.png"));
static auto PanelLayoutReorderButton_Bottom_Texture = LGUIEditorUtils::LoadTexture(LGUIBasePath + TEXT("/Resources/Icons/PanelLayoutReorderButton_Bottom.png"));
if (PanelLayout->CanMoveChildToCell(TargetComp.Get(), UUIPanelLayoutBase::EMoveChildDirectionType::Left))
{
DrawHitProxy(LeftPoint, EUIItemVisualizerSelectorType::PanelLayout_Left, PanelLayoutReorderButton_Left_Texture, AreaScale);
}
if (PanelLayout->CanMoveChildToCell(TargetComp.Get(), UUIPanelLayoutBase::EMoveChildDirectionType::Right))
{
DrawHitProxy(RightPoint, EUIItemVisualizerSelectorType::PanelLayout_Right, PanelLayoutReorderButton_Right_Texture, AreaScale);
}
if (PanelLayout->CanMoveChildToCell(TargetComp.Get(), UUIPanelLayoutBase::EMoveChildDirectionType::Top))
{
DrawHitProxy(TopPoint, EUIItemVisualizerSelectorType::PanelLayout_Top, PanelLayoutReorderButton_Top_Texture, AreaScale);
}
if (PanelLayout->CanMoveChildToCell(TargetComp.Get(), UUIPanelLayoutBase::EMoveChildDirectionType::Bottom))
{
DrawHitProxy(BottomPoint, EUIItemVisualizerSelectorType::PanelLayout_Bottom, PanelLayoutReorderButton_Bottom_Texture, AreaScale);
}
bHaveDrawPanelLayout = true;
}
}
}
}
//draw anchor tool
if (GetDefault<ULGUIEditorSettings>()->bShowAnchorTool)
{
if (!bHaveDrawPanelLayout)//anchor is controlled by panel layout, so no need to draw it
{
static auto AnchorVisTexture = LGUIEditorUtils::LoadTexture(LGUIBasePath + TEXT("/Resources/Icons/AnchorVisSelector.png"));
DrawHitProxy(LeftPoint, EUIItemVisualizerSelectorType::Left, AnchorVisTexture);
DrawHitProxy(RightPoint, EUIItemVisualizerSelectorType::Right, AnchorVisTexture);
DrawHitProxy(TopPoint, EUIItemVisualizerSelectorType::Top, AnchorVisTexture);
DrawHitProxy(BottomPoint, EUIItemVisualizerSelectorType::Bottom, AnchorVisTexture);
DrawHitProxy(LeftBottomPoint, EUIItemVisualizerSelectorType::LeftBottom, AnchorVisTexture);
DrawHitProxy(RightBottomPoint, EUIItemVisualizerSelectorType::RightBottom, AnchorVisTexture);
DrawHitProxy(LeftTopPoint, EUIItemVisualizerSelectorType::LeftTop, AnchorVisTexture);
DrawHitProxy(RightTopPoint, EUIItemVisualizerSelectorType::RightTop, AnchorVisTexture);
}
static auto PivotVisTexture = LGUIEditorUtils::LoadTexture(LGUIBasePath + TEXT("/Resources/Icons/PivotVisSelector.png"));
DrawHitProxy(TargetComp->GetComponentLocation(), EUIItemVisualizerSelectorType::Pivot, PivotVisTexture);
}
}
bool FUIItemComponentVisualizer::VisProxyHandleClick(FEditorViewportClient* InViewportClient, HComponentVisProxy* VisProxy, const FViewportClick& Click)
{
if (!TargetComp.IsValid())return false;
if (VisProxy->IsA(HUIItemAnchorVisProxy::StaticGetType()))
{
const HUIItemAnchorVisProxy* Proxy = (HUIItemAnchorVisProxy*)VisProxy;
switch (Proxy->Type)
{
case EUIItemVisualizerSelectorType::Left:
case EUIItemVisualizerSelectorType::Right:
case EUIItemVisualizerSelectorType::Top:
case EUIItemVisualizerSelectorType::Bottom:
case EUIItemVisualizerSelectorType::LeftTop:
case EUIItemVisualizerSelectorType::RightTop:
case EUIItemVisualizerSelectorType::LeftBottom:
case EUIItemVisualizerSelectorType::RightBottom:
case EUIItemVisualizerSelectorType::Pivot:
{
SelectorType = Proxy->Type;
}
break;
case EUIItemVisualizerSelectorType::PanelLayout_Left:
case EUIItemVisualizerSelectorType::PanelLayout_Right:
case EUIItemVisualizerSelectorType::PanelLayout_Top:
case EUIItemVisualizerSelectorType::PanelLayout_Bottom:
{
if (auto Parent = TargetComp->GetParentUIItem())
{
if (auto PanelLayout = Parent->GetOwner()->FindComponentByClass<UUIPanelLayoutBase>())
{
GEditor->BeginTransaction(LOCTEXT("ChangeLayoutOrder", "Change Layout Order"));
TargetComp->Modify();
PanelLayout->GetChildSlot(TargetComp.Get())->Modify();
auto Direction = (int)Proxy->Type - (int)EUIItemVisualizerSelectorType::PanelLayout_Left;
PanelLayout->MoveChildToCell(TargetComp.Get(), (UUIPanelLayoutBase::EMoveChildDirectionType)Direction);
GEditor->EndTransaction();
ULGUIPrefabManagerObject::AddOneShotTickFunction([] {
GEditor->RedrawAllViewports();
}, 1);
}
}
}
break;
}
return true;
}
return false;
}
bool FUIItemComponentVisualizer::HandleInputKey(FEditorViewportClient* ViewportClient, FViewport* Viewport, FKey Key, EInputEvent Event)
{
return false;
}
bool FUIItemComponentVisualizer::HandleInputDelta(FEditorViewportClient* ViewportClient, FViewport* Viewport, FVector& DeltaTranslate, FRotator& DeltalRotate, FVector& DeltaScale)
{
if (!GetDefault<ULGUIEditorSettings>()->bShowAnchorTool)return false;
if (!TargetComp.IsValid())return false;
if (DeltaTranslate.IsZero())return false;
TargetComp->Modify();
bool bAnchorChanged = false;
auto LocalSpaceDeltaTranslate = TargetComp->GetComponentTransform().InverseTransformVector(DeltaTranslate);
bool bLeft = false, bRight = false, bBottom = false, bTop = false;
switch (SelectorType)
{
case EUIItemVisualizerSelectorType::Left:
bLeft = true;
break;
case EUIItemVisualizerSelectorType::Right:
bRight = true;
break;
case EUIItemVisualizerSelectorType::Bottom:
bBottom = true;
break;
case EUIItemVisualizerSelectorType::Top:
bTop = true;
break;
case EUIItemVisualizerSelectorType::LeftTop:
bLeft = true; bTop = true;
break;
case EUIItemVisualizerSelectorType::LeftBottom:
bLeft = true; bBottom = true;
break;
case EUIItemVisualizerSelectorType::RightTop:
bRight = true; bTop = true;
break;
case EUIItemVisualizerSelectorType::RightBottom:
bRight = true; bBottom = true;
break;
case EUIItemVisualizerSelectorType::Pivot:
{
if (LocalSpaceDeltaTranslate.Y != 0 || LocalSpaceDeltaTranslate.Z != 0)
{
auto DeltaTranslatePivot = FVector2D(LocalSpaceDeltaTranslate.Y / TargetComp->GetWidth(), LocalSpaceDeltaTranslate.Z / TargetComp->GetHeight());
FMargin PrevAnchorAsMargin(TargetComp->GetAnchorLeft(), TargetComp->GetAnchorTop(), TargetComp->GetAnchorRight(), TargetComp->GetAnchorBottom());
TargetComp->SetPivot(TargetComp->GetPivot() + DeltaTranslatePivot);
TargetComp->SetAnchorLeft(PrevAnchorAsMargin.Left);
TargetComp->SetAnchorRight(PrevAnchorAsMargin.Right);
TargetComp->SetAnchorBottom(PrevAnchorAsMargin.Bottom);
TargetComp->SetAnchorTop(PrevAnchorAsMargin.Top);
bAnchorChanged = true;
}
}
break;
}
if (bLeft)
{
if (LocalSpaceDeltaTranslate.Y != 0)
{
TargetComp->SetAnchorLeft(TargetComp->GetAnchorLeft() + LocalSpaceDeltaTranslate.Y);
if (IsAltDown(Viewport))
{
TargetComp->SetAnchorRight(TargetComp->GetAnchorRight() + LocalSpaceDeltaTranslate.Y);
}
bAnchorChanged = true;
}
}
if (bRight)
{
if (LocalSpaceDeltaTranslate.Y != 0)
{
TargetComp->SetAnchorRight(TargetComp->GetAnchorRight() - LocalSpaceDeltaTranslate.Y);
if (IsAltDown(Viewport))
{
TargetComp->SetAnchorLeft(TargetComp->GetAnchorLeft() - LocalSpaceDeltaTranslate.Y);
}
bAnchorChanged = true;
}
}
if (bBottom)
{
if (LocalSpaceDeltaTranslate.Z != 0)
{
TargetComp->SetAnchorBottom(TargetComp->GetAnchorBottom() + LocalSpaceDeltaTranslate.Z);
if (IsAltDown(Viewport))
{
TargetComp->SetAnchorTop(TargetComp->GetAnchorTop() + LocalSpaceDeltaTranslate.Z);
}
bAnchorChanged = true;
}
}
if (bTop)
{
if (LocalSpaceDeltaTranslate.Z != 0)
{
TargetComp->SetAnchorTop(TargetComp->GetAnchorTop() - LocalSpaceDeltaTranslate.Z);
if (IsAltDown(Viewport))
{
TargetComp->SetAnchorBottom(TargetComp->GetAnchorBottom() - LocalSpaceDeltaTranslate.Z);
}
bAnchorChanged = true;
}
}
if (bAnchorChanged)
{
LGUIUtils::NotifyPropertyChanged(TargetComp.Get(), UUIItem::GetAnchorDataPropertyName());
}
return true;
}
bool FUIItemComponentVisualizer::GetWidgetLocation(const FEditorViewportClient* ViewportClient, FVector& OutLocation) const
{
if (!TargetComp.IsValid())return false;
auto Center = TargetComp->GetLocalSpaceCenter();
auto Left = TargetComp->GetLocalSpaceLeft();
auto Right = TargetComp->GetLocalSpaceRight();
auto Bottom = TargetComp->GetLocalSpaceBottom();
auto Top = TargetComp->GetLocalSpaceTop();
FVector LocalPosition;
switch (SelectorType)
{
case EUIItemVisualizerSelectorType::Left:
{
LocalPosition = FVector(0, TargetComp->GetLocalSpaceLeft(), Center.Y);
}
break;
case EUIItemVisualizerSelectorType::Right:
{
LocalPosition = FVector(0, TargetComp->GetLocalSpaceRight(), Center.Y);
}
break;
case EUIItemVisualizerSelectorType::Top:
{
LocalPosition = FVector(0, Center.X, TargetComp->GetLocalSpaceTop());
}
break;
case EUIItemVisualizerSelectorType::Bottom:
{
LocalPosition = FVector(0, Center.X, TargetComp->GetLocalSpaceBottom());
}
break;
case EUIItemVisualizerSelectorType::LeftBottom:
{
LocalPosition = FVector(0, Left, Bottom);
}
break;
case EUIItemVisualizerSelectorType::RightBottom:
{
LocalPosition = FVector(0, Right, Bottom);
}
break;
case EUIItemVisualizerSelectorType::LeftTop:
{
LocalPosition = FVector(0, Left, Top);
}
break;
case EUIItemVisualizerSelectorType::RightTop:
{
LocalPosition = FVector(0, Right, Top);
}
break;
case EUIItemVisualizerSelectorType::Pivot:
{
LocalPosition = FVector::ZeroVector;
}
break;
}
OutLocation = TargetComp->GetComponentTransform().TransformPosition(LocalPosition);
return true;
}
bool FUIItemComponentVisualizer::GetCustomInputCoordinateSystem(const FEditorViewportClient* ViewportClient, FMatrix& OutMatrix) const
{
if (!TargetComp.IsValid())return false;
OutMatrix = FRotationMatrix(TargetComp->GetComponentTransform().Rotator());
return true;
}
IMPLEMENT_HIT_PROXY(HUIItemAnchorVisProxy, HComponentVisProxy);
HUIItemAnchorVisProxy::HUIItemAnchorVisProxy(const UUIItem* InComponent, EUIItemVisualizerSelectorType InType)
: HComponentVisProxy(InComponent, HPP_Foreground)
{
Type = InType;
}
#undef LOCTEXT_NAMESPACE
#if LGUI_CAN_DISABLE_OPTIMIZATION
UE_ENABLE_OPTIMIZATION
#endif