2021-09-28 13:33:17 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "SStateTreeViewRow.h"
|
|
|
|
|
#include "SStateTreeView.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "EditorFontGlyphs.h"
|
2023-06-20 13:49:25 -04:00
|
|
|
#include "StateTreeEditor.h"
|
2023-06-15 11:38:28 -04:00
|
|
|
#include "StateTreeEditorData.h"
|
2021-09-28 13:33:17 -04:00
|
|
|
#include "StateTreeEditorStyle.h"
|
|
|
|
|
|
|
|
|
|
#include "Widgets/Text/SInlineEditableTextBlock.h"
|
|
|
|
|
#include "Widgets/Layout/SScrollBox.h"
|
2023-06-15 11:38:28 -04:00
|
|
|
#include "Widgets/Layout/SSpacer.h"
|
2021-09-28 13:33:17 -04:00
|
|
|
|
2023-12-05 17:55:30 -05:00
|
|
|
#include "StateTree.h"
|
2021-09-28 13:33:17 -04:00
|
|
|
#include "StateTreeState.h"
|
2022-02-03 09:13:49 -05:00
|
|
|
#include "StateTreeTaskBase.h"
|
2021-09-28 13:33:17 -04:00
|
|
|
#include "StateTreeViewModel.h"
|
2023-01-19 00:48:07 -05:00
|
|
|
#include "Widgets/Views/SListView.h"
|
2021-09-28 13:33:17 -04:00
|
|
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "StateTreeEditor"
|
|
|
|
|
|
2023-09-26 11:50:26 -04:00
|
|
|
namespace UE::StateTree::Editor
|
|
|
|
|
{
|
|
|
|
|
FLinearColor LerpColorSRGB(const FLinearColor ColorA, FLinearColor ColorB, float T)
|
|
|
|
|
{
|
|
|
|
|
const FColor A = ColorA.ToFColorSRGB();
|
|
|
|
|
const FColor B = ColorB.ToFColorSRGB();
|
|
|
|
|
return FLinearColor(FColor(
|
|
|
|
|
static_cast<uint8>(FMath::RoundToInt(static_cast<float>(A.R) * (1.f - T) + static_cast<float>(B.R) * T)),
|
|
|
|
|
static_cast<uint8>(FMath::RoundToInt(static_cast<float>(A.G) * (1.f - T) + static_cast<float>(B.G) * T)),
|
|
|
|
|
static_cast<uint8>(FMath::RoundToInt(static_cast<float>(A.B) * (1.f - T) + static_cast<float>(B.B) * T)),
|
|
|
|
|
static_cast<uint8>(FMath::RoundToInt(static_cast<float>(A.A) * (1.f - T) + static_cast<float>(B.A) * T))));
|
|
|
|
|
}
|
|
|
|
|
} // UE:StateTree::Editor
|
|
|
|
|
|
2022-09-30 11:31:57 -04:00
|
|
|
void SStateTreeViewRow::Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwnerTableView, TWeakObjectPtr<UStateTreeState> InState, const TSharedPtr<SScrollBox>& ViewBox, TSharedRef<FStateTreeViewModel> InStateTreeViewModel)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
StateTreeViewModel = InStateTreeViewModel;
|
|
|
|
|
WeakState = InState;
|
2023-06-15 11:38:28 -04:00
|
|
|
const UStateTreeState* State = InState.Get();
|
|
|
|
|
WeakTreeData = State != nullptr ? State->GetTypedOuter<UStateTreeEditorData>() : nullptr;
|
2021-09-28 13:33:17 -04:00
|
|
|
|
2023-06-05 13:12:19 -04:00
|
|
|
ConstructInternal(STableRow::FArguments()
|
2023-03-14 13:35:46 -04:00
|
|
|
.Padding(5.0f)
|
|
|
|
|
.OnDragDetected(this, &SStateTreeViewRow::HandleDragDetected)
|
|
|
|
|
.OnCanAcceptDrop(this, &SStateTreeViewRow::HandleCanAcceptDrop)
|
|
|
|
|
.OnAcceptDrop(this, &SStateTreeViewRow::HandleAcceptDrop)
|
|
|
|
|
.Style(&FStateTreeEditorStyle::Get().GetWidgetStyle<FTableRowStyle>("StateTree.Selection"))
|
|
|
|
|
, InOwnerTableView);
|
2021-09-28 13:33:17 -04:00
|
|
|
|
2022-04-05 03:20:57 -04:00
|
|
|
static const FLinearColor LinkBackground = FLinearColor(FColor(84, 84, 84));
|
2023-06-05 13:12:19 -04:00
|
|
|
static constexpr FLinearColor IconTint = FLinearColor(1, 1, 1, 0.5f);
|
2022-06-30 03:06:38 -04:00
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
this->ChildSlot
|
2022-10-31 15:13:40 -04:00
|
|
|
.HAlign(HAlign_Fill)
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
2023-05-08 13:32:14 -04:00
|
|
|
.MinDesiredWidth_Lambda([WeakOwnerViewBox = ViewBox.ToWeakPtr()]()
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-05-08 13:32:14 -04:00
|
|
|
// Captured as weak ptr so we don't prevent our parent widget from being destroyed (circular pointer reference).
|
|
|
|
|
if (const TSharedPtr<SScrollBox> OwnerViewBox = WeakOwnerViewBox.Pin())
|
|
|
|
|
{
|
|
|
|
|
// Make the row at least as wide as the view.
|
|
|
|
|
// The -1 is needed or we'll see a scrollbar.
|
|
|
|
|
return OwnerViewBox->GetTickSpaceGeometry().GetLocalSize().X - 1;
|
|
|
|
|
}
|
|
|
|
|
return 0.f;
|
2023-03-14 13:35:46 -04:00
|
|
|
})
|
2022-06-30 03:06:38 -04:00
|
|
|
[
|
2022-10-31 15:13:40 -04:00
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Fill)
|
|
|
|
|
.HAlign(HAlign_Left)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SExpanderArrow, SharedThis(this))
|
|
|
|
|
.ShouldDrawWires(true)
|
|
|
|
|
.IndentAmount(32)
|
|
|
|
|
.BaseIndentLevel(0)
|
|
|
|
|
]
|
2021-09-28 13:33:17 -04:00
|
|
|
|
2022-10-31 15:13:40 -04:00
|
|
|
+ SHorizontalBox::Slot()
|
2023-03-14 13:35:46 -04:00
|
|
|
.VAlign(VAlign_Fill)
|
|
|
|
|
.HAlign(HAlign_Left)
|
2022-10-31 15:13:40 -04:00
|
|
|
.Padding(FMargin(0.0f, 4.0f))
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
|
|
|
|
.HeightOverride(28.0f)
|
|
|
|
|
.VAlign(VAlign_Fill)
|
|
|
|
|
[
|
|
|
|
|
SNew(SBorder)
|
2023-06-05 13:12:19 -04:00
|
|
|
.BorderImage(FStateTreeEditorStyle::Get().GetBrush("StateTree.State.Border"))
|
2023-03-14 13:35:46 -04:00
|
|
|
.BorderBackgroundColor(this, &SStateTreeViewRow::GetActiveStateColor)
|
2022-10-31 15:13:40 -04:00
|
|
|
[
|
|
|
|
|
SNew(SHorizontalBox)
|
2023-04-12 07:59:16 -04:00
|
|
|
|
|
|
|
|
// Sub tree marker
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
|
|
|
|
.WidthOverride(4.0f)
|
|
|
|
|
.HeightOverride(28.0f)
|
|
|
|
|
[
|
|
|
|
|
SNew(SBorder)
|
|
|
|
|
.BorderImage(FAppStyle::GetBrush("WhiteBrush"))
|
|
|
|
|
.BorderBackgroundColor(this, &SStateTreeViewRow::GetSubTreeMarkerColor)
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// State Box
|
2022-10-31 15:13:40 -04:00
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
2023-03-14 13:35:46 -04:00
|
|
|
.HeightOverride(28.0f)
|
|
|
|
|
.VAlign(VAlign_Fill)
|
2022-10-31 15:13:40 -04:00
|
|
|
[
|
2023-03-14 13:35:46 -04:00
|
|
|
SNew(SBorder)
|
|
|
|
|
.BorderImage(FAppStyle::GetBrush("WhiteBrush"))
|
|
|
|
|
.BorderBackgroundColor(this, &SStateTreeViewRow::GetTitleColor)
|
2023-04-12 07:59:16 -04:00
|
|
|
.Padding(FMargin(4.0f, 0.0f, 12.0f, 0.0f))
|
2023-06-05 13:12:19 -04:00
|
|
|
.IsEnabled_Lambda([InState]
|
|
|
|
|
{
|
|
|
|
|
const UStateTreeState* State = InState.Get();
|
|
|
|
|
return State != nullptr && State->bEnabled;
|
|
|
|
|
})
|
2023-03-14 13:35:46 -04:00
|
|
|
[
|
2023-06-15 11:38:28 -04:00
|
|
|
SNew(SOverlay)
|
|
|
|
|
+ SOverlay::Slot()
|
2023-03-14 13:35:46 -04:00
|
|
|
[
|
2023-06-15 11:38:28 -04:00
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
// Conditions icon
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
2023-03-14 13:35:46 -04:00
|
|
|
[
|
2023-06-15 11:38:28 -04:00
|
|
|
SNew(SBox)
|
|
|
|
|
.Padding(FMargin(0.0f, 0.0f, 4.0f, 0.0f))
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetConditionVisibility)
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.ColorAndOpacity(IconTint)
|
|
|
|
|
.Image(FStateTreeEditorStyle::Get().GetBrush("StateTreeEditor.Conditions"))
|
|
|
|
|
.ToolTipText(LOCTEXT("StateHasEnterConditions", "State selection is guarded with enter conditions."))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// Selector icon
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
|
|
|
|
.Padding(FMargin(0.0f, 0.0f, 4.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.Image(this, &SStateTreeViewRow::GetSelectorIcon)
|
|
|
|
|
.ColorAndOpacity(IconTint)
|
|
|
|
|
.ToolTipText(this, &SStateTreeViewRow::GetSelectorTooltip)
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// State Name
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SAssignNew(NameTextBlock, SInlineEditableTextBlock)
|
|
|
|
|
.Style(FStateTreeEditorStyle::Get(), "StateTree.State.TitleInlineEditableText")
|
|
|
|
|
.OnVerifyTextChanged_Lambda([](const FText& NewLabel, FText& OutErrorMessage)
|
|
|
|
|
{
|
|
|
|
|
return !NewLabel.IsEmptyOrWhitespace();
|
|
|
|
|
})
|
|
|
|
|
.OnTextCommitted(this, &SStateTreeViewRow::HandleNodeLabelTextCommitted)
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetStateDesc)
|
|
|
|
|
.ToolTipText(this, &SStateTreeViewRow::GetStateTypeTooltip)
|
|
|
|
|
.Clipping(EWidgetClipping::ClipToBounds)
|
|
|
|
|
.IsSelected(this, &SStateTreeViewRow::IsStateSelected)
|
2023-03-14 13:35:46 -04:00
|
|
|
]
|
2023-06-21 10:32:41 -04:00
|
|
|
|
|
|
|
|
// State ID
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Visibility_Lambda([]()
|
|
|
|
|
{
|
|
|
|
|
return UE::StateTree::Editor::GbDisplayItemIds ? EVisibility::Visible : EVisibility::Collapsed;
|
|
|
|
|
})
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetStateIDDesc)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Details")
|
|
|
|
|
]
|
2023-03-14 13:35:46 -04:00
|
|
|
]
|
2023-06-15 11:38:28 -04:00
|
|
|
+ SOverlay::Slot()
|
2023-03-14 13:35:46 -04:00
|
|
|
[
|
2023-06-15 11:38:28 -04:00
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
|
|
|
|
|
// State breakpoint box
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Top)
|
|
|
|
|
.HAlign(HAlign_Left)
|
|
|
|
|
.AutoWidth()
|
2023-03-14 13:35:46 -04:00
|
|
|
[
|
2023-06-15 11:38:28 -04:00
|
|
|
SNew(SBox)
|
|
|
|
|
.Padding(FMargin(-12.0f, -6.0f, 0.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.DesiredSizeOverride(FVector2D(12.f, 12.f))
|
|
|
|
|
.Image(FStateTreeEditorStyle::Get().GetBrush(TEXT("StateTreeEditor.Debugger.Breakpoint.EnabledAndValid")))
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetStateBreakpointVisibility)
|
|
|
|
|
.ToolTipText(this, &SStateTreeViewRow::GetStateBreakpointTooltipText)
|
|
|
|
|
]
|
2023-03-14 13:35:46 -04:00
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
2022-06-30 03:06:38 -04:00
|
|
|
]
|
|
|
|
|
]
|
2023-04-12 07:59:16 -04:00
|
|
|
|
|
|
|
|
// Linked State box
|
2022-06-30 03:06:38 -04:00
|
|
|
+ SHorizontalBox::Slot()
|
2023-04-12 07:59:16 -04:00
|
|
|
.VAlign(VAlign_Fill)
|
2022-06-30 03:06:38 -04:00
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
2023-04-12 07:59:16 -04:00
|
|
|
SNew(SBox)
|
|
|
|
|
.HeightOverride(28.0f)
|
|
|
|
|
.VAlign(VAlign_Fill)
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetLinkedStateVisibility)
|
|
|
|
|
[
|
|
|
|
|
SNew(SBorder)
|
|
|
|
|
.BorderImage(FAppStyle::GetBrush("WhiteBrush"))
|
|
|
|
|
.BorderBackgroundColor(LinkBackground)
|
|
|
|
|
.Padding(FMargin(6.0f, 0.0f, 12.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
// Link icon
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(FMargin(0.0f, 0.0f, 4.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.ColorAndOpacity(IconTint)
|
|
|
|
|
.Image(FStateTreeEditorStyle::Get().GetBrush("StateTreeEditor.StateLinked"))
|
|
|
|
|
]
|
2021-09-28 13:33:17 -04:00
|
|
|
|
2023-04-12 07:59:16 -04:00
|
|
|
// Linked State
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetLinkedStateDesc)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Details")
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
2022-06-30 03:06:38 -04:00
|
|
|
]
|
2023-06-05 13:12:19 -04:00
|
|
|
// Tasks
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Fill)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
|
|
|
|
.VAlign(VAlign_Fill)
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetTasksVisibility)
|
|
|
|
|
[
|
|
|
|
|
CreateTasksWidget()
|
|
|
|
|
]
|
|
|
|
|
]
|
2022-04-05 03:20:57 -04:00
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
2023-03-14 13:35:46 -04:00
|
|
|
|
2022-06-30 03:06:38 -04:00
|
|
|
// Completed transitions
|
2021-09-28 13:33:17 -04:00
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
2022-06-30 03:06:38 -04:00
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(FMargin(8.0f, 0.0f, 0, 0.0f))
|
|
|
|
|
[
|
2023-06-20 13:49:25 -04:00
|
|
|
SNew(SOverlay)
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetCompletedTransitionsIcon)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Icon")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetCompletedTransitionVisibility)
|
|
|
|
|
]
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
// Breakpoint box
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Top)
|
|
|
|
|
.HAlign(HAlign_Left)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
|
|
|
|
.Padding(FMargin(0.0f, -10.0f, 0.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.DesiredSizeOverride(FVector2D(10.f, 10.f))
|
|
|
|
|
.Image(FStateTreeEditorStyle::Get().GetBrush(TEXT("StateTreeEditor.Debugger.Breakpoint.EnabledAndValid")))
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetCompletedTransitionBreakpointVisibility)
|
|
|
|
|
.ToolTipText_Lambda([this]
|
|
|
|
|
{
|
|
|
|
|
return FText::Format(LOCTEXT("TransitionBreakpointTooltip","Break when executing transition: {0}"),
|
|
|
|
|
GetCompletedTransitionWithBreakpointDesc());
|
|
|
|
|
})
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
2022-06-30 03:06:38 -04:00
|
|
|
]
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(FMargin(4.0f, 0, 0, 0))
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetCompletedTransitionsDesc)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Details")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetCompletedTransitionVisibility)
|
|
|
|
|
]
|
2021-09-28 13:33:17 -04:00
|
|
|
]
|
|
|
|
|
|
2022-06-30 03:06:38 -04:00
|
|
|
// Succeeded transitions
|
2021-09-28 13:33:17 -04:00
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
2022-06-30 03:06:38 -04:00
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.Padding(FMargin(8.0f, 0.0f, 0, 0))
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(FEditorFontGlyphs::Check_Circle)
|
2022-10-31 15:13:40 -04:00
|
|
|
.ColorAndOpacity(FLinearColor(FColor(110,143,67)))
|
2022-06-30 03:06:38 -04:00
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Icon")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetSucceededTransitionVisibility)
|
|
|
|
|
]
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.Padding(FMargin(4.0f, 0.0f, 0, 0))
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
2023-06-20 13:49:25 -04:00
|
|
|
SNew(SOverlay)
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetSucceededTransitionIcon)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Icon")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetSucceededTransitionVisibility)
|
|
|
|
|
]
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
// Breakpoint box
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Top)
|
|
|
|
|
.HAlign(HAlign_Left)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
|
|
|
|
.Padding(FMargin(0.0f, -10.0f, 0.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.DesiredSizeOverride(FVector2D(10.f, 10.f))
|
|
|
|
|
.Image(FStateTreeEditorStyle::Get().GetBrush(TEXT("StateTreeEditor.Debugger.Breakpoint.EnabledAndValid")))
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetSucceededTransitionBreakpointVisibility)
|
|
|
|
|
.ToolTipText_Lambda([this]
|
|
|
|
|
{
|
|
|
|
|
return FText::Format(LOCTEXT("TransitionBreakpointTooltip", "Break when executing transition: {0}"),
|
|
|
|
|
GetSucceededTransitionWithBreakpointDesc());
|
|
|
|
|
})
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
2022-06-30 03:06:38 -04:00
|
|
|
]
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(FMargin(4.0f, 0, 0, 0))
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetSucceededTransitionDesc)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Details")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetSucceededTransitionVisibility)
|
|
|
|
|
]
|
2021-09-28 13:33:17 -04:00
|
|
|
]
|
|
|
|
|
|
2022-06-30 03:06:38 -04:00
|
|
|
// Failed transitions
|
2021-09-28 13:33:17 -04:00
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
2022-06-30 03:06:38 -04:00
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.Padding(FMargin(8.0f, 0.0f, 0, 0))
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(FEditorFontGlyphs::Times_Circle)
|
2022-10-31 15:13:40 -04:00
|
|
|
.ColorAndOpacity(FLinearColor(FColor(187,77,42)))
|
2022-06-30 03:06:38 -04:00
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Icon")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetFailedTransitionVisibility)
|
|
|
|
|
]
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.Padding(FMargin(4.0f, 0.0f, 0, 0))
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
2023-06-20 13:49:25 -04:00
|
|
|
SNew(SOverlay)
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetFailedTransitionIcon)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Icon")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetFailedTransitionVisibility)
|
|
|
|
|
]
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
// Breakpoint box
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Top)
|
|
|
|
|
.HAlign(HAlign_Left)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
|
|
|
|
.Padding(FMargin(0.0f, -10.0f, 0.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.DesiredSizeOverride(FVector2D(10.f, 10.f))
|
|
|
|
|
.Image(FStateTreeEditorStyle::Get().GetBrush(TEXT("StateTreeEditor.Debugger.Breakpoint.EnabledAndValid")))
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetFailedTransitionBreakpointVisibility)
|
|
|
|
|
.ToolTipText_Lambda([this]
|
|
|
|
|
{
|
|
|
|
|
return FText::Format(LOCTEXT("TransitionBreakpointTooltip", "Break when executing transition: {0}"),
|
|
|
|
|
GetFailedTransitionWithBreakpointDesc());
|
|
|
|
|
})
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
2022-06-30 03:06:38 -04:00
|
|
|
]
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(FMargin(4.0f, 0, 0, 0))
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetFailedTransitionDesc)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Details")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetFailedTransitionVisibility)
|
|
|
|
|
]
|
2021-09-28 13:33:17 -04:00
|
|
|
]
|
2023-06-20 13:49:25 -04:00
|
|
|
|
2022-06-30 03:06:38 -04:00
|
|
|
// Transitions
|
2021-09-28 13:33:17 -04:00
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
2022-06-30 03:06:38 -04:00
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.Padding(FMargin(8.0f, 0.0f, 0, 0))
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.Image(FAppStyle::Get().GetBrush("Icons.Help"))
|
2022-10-31 15:13:40 -04:00
|
|
|
.ColorAndOpacity(FLinearColor(FColor(31,151,167)))
|
2022-06-30 03:06:38 -04:00
|
|
|
.Visibility(this, &SStateTreeViewRow::GetConditionalTransitionsVisibility)
|
|
|
|
|
]
|
2022-10-31 15:13:40 -04:00
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.Padding(FMargin(4.0f, 0.0f, 0, 0))
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
2023-06-20 13:49:25 -04:00
|
|
|
SNew(SOverlay)
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(FEditorFontGlyphs::Long_Arrow_Right)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Icon")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetConditionalTransitionsVisibility)
|
|
|
|
|
]
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
// Breakpoint box
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Top)
|
|
|
|
|
.HAlign(HAlign_Left)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
|
|
|
|
.Padding(FMargin(0.0f, -10.0f, 0.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.DesiredSizeOverride(FVector2D(10.f, 10.f))
|
|
|
|
|
.Image(FStateTreeEditorStyle::Get().GetBrush(TEXT("StateTreeEditor.Debugger.Breakpoint.EnabledAndValid")))
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetConditionalTransitionsBreakpointVisibility)
|
|
|
|
|
.ToolTipText_Lambda([this]
|
|
|
|
|
{
|
|
|
|
|
return FText::Format(LOCTEXT("TransitionBreakpointTooltip", "Break when executing transition: {0}"),
|
|
|
|
|
GetConditionalTransitionsWithBreakpointDesc());
|
|
|
|
|
})
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
2022-10-31 15:13:40 -04:00
|
|
|
]
|
|
|
|
|
+ SHorizontalBox::Slot()
|
2022-06-30 03:06:38 -04:00
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(FMargin(4.0f, 0, 0, 0))
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(this, &SStateTreeViewRow::GetConditionalTransitionsDesc)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Details")
|
|
|
|
|
.Visibility(this, &SStateTreeViewRow::GetConditionalTransitionsVisibility)
|
|
|
|
|
]
|
2021-09-28 13:33:17 -04:00
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-05 13:12:19 -04:00
|
|
|
TSharedRef<SHorizontalBox> SStateTreeViewRow::CreateTasksWidget()
|
|
|
|
|
{
|
|
|
|
|
const TSharedRef<SHorizontalBox> TasksBox = SNew(SHorizontalBox);
|
|
|
|
|
|
|
|
|
|
const UStateTreeState* State = WeakState.Get();
|
|
|
|
|
if (State == nullptr || State->Tasks.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
return TasksBox;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-15 11:38:28 -04:00
|
|
|
TWeakObjectPtr<UStateTreeEditorData> WeakEditorData = State->GetTypedOuter<UStateTreeEditorData>();
|
|
|
|
|
|
2023-06-05 13:12:19 -04:00
|
|
|
for (int32 TaskIndex = 0; TaskIndex < State->Tasks.Num(); TaskIndex++)
|
|
|
|
|
{
|
|
|
|
|
if (const FStateTreeTaskBase* Task = State->Tasks[TaskIndex].Node.GetPtr<FStateTreeTaskBase>())
|
|
|
|
|
{
|
2023-06-15 11:38:28 -04:00
|
|
|
FGuid TaskId = State->Tasks[TaskIndex].ID;
|
2023-06-05 13:12:19 -04:00
|
|
|
auto IsTaskEnabledFunc = [WeakState=WeakState, TaskIndex]
|
|
|
|
|
{
|
|
|
|
|
const UStateTreeState* State = WeakState.Get();
|
|
|
|
|
if (State != nullptr && State->Tasks.IsValidIndex(TaskIndex))
|
|
|
|
|
{
|
|
|
|
|
if (const FStateTreeTaskBase* Task = State->Tasks[TaskIndex].Node.GetPtr<FStateTreeTaskBase>())
|
|
|
|
|
{
|
|
|
|
|
return (State->bEnabled && Task->bTaskEnabled);
|
|
|
|
|
}
|
2023-06-15 11:38:28 -04:00
|
|
|
}
|
2023-06-05 13:12:19 -04:00
|
|
|
return true;
|
|
|
|
|
};
|
2023-06-15 11:38:28 -04:00
|
|
|
|
|
|
|
|
auto IsTaskBreakpointEnabledFunc = [WeakEditorData, TaskId]
|
|
|
|
|
{
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
const UStateTreeEditorData* EditorData = WeakEditorData.Get();
|
|
|
|
|
if (EditorData != nullptr && EditorData->HasAnyBreakpoint(TaskId))
|
|
|
|
|
{
|
|
|
|
|
return EVisibility::Visible;
|
|
|
|
|
}
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
|
|
|
|
return EVisibility::Hidden;
|
|
|
|
|
};
|
2023-06-05 13:12:19 -04:00
|
|
|
|
2023-06-15 11:38:28 -04:00
|
|
|
auto GetTaskBreakpointTooltipFunc = [WeakEditorData, TaskId]
|
|
|
|
|
{
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
if (const UStateTreeEditorData* EditorData = WeakEditorData.Get())
|
|
|
|
|
{
|
|
|
|
|
const bool bHasBreakpointOnEnter = EditorData->HasBreakpoint(TaskId, EStateTreeBreakpointType::OnEnter);
|
|
|
|
|
const bool bHasBreakpointOnExit = EditorData->HasBreakpoint(TaskId, EStateTreeBreakpointType::OnExit);
|
|
|
|
|
if (bHasBreakpointOnEnter && bHasBreakpointOnExit)
|
|
|
|
|
{
|
|
|
|
|
return LOCTEXT("StateTreeTaskBreakpointOnEnterAndOnExitTooltip","Break when entering or exiting task");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bHasBreakpointOnEnter)
|
|
|
|
|
{
|
|
|
|
|
return LOCTEXT("StateTreeTaskBreakpointOnEnterTooltip","Break when entering task");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bHasBreakpointOnExit)
|
|
|
|
|
{
|
|
|
|
|
return LOCTEXT("StateTreeTaskBreakpointOnExitTooltip","Break when exiting task");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
};
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
FText TaskName;
|
|
|
|
|
if (UE::StateTree::Editor::GbDisplayItemIds)
|
|
|
|
|
{
|
|
|
|
|
TaskName = FText::FromString(FString::Printf(TEXT("%s (%s)"), *Task->Name.ToString(), *LexToString(TaskId)));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
TaskName = FText::FromName(Task->Name);
|
|
|
|
|
}
|
2023-06-15 11:38:28 -04:00
|
|
|
|
2023-06-05 13:12:19 -04:00
|
|
|
TasksBox->AddSlot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.VAlign(VAlign_Fill)
|
|
|
|
|
[
|
|
|
|
|
SNew(SBorder)
|
|
|
|
|
.VAlign(VAlign_Center)
|
|
|
|
|
.BorderImage(FStateTreeEditorStyle::Get().GetBrush("StateTree.Task.Rect"))
|
2023-09-26 11:50:26 -04:00
|
|
|
.BorderBackgroundColor(this, &SStateTreeViewRow::GetTitleColor)
|
2023-06-15 11:38:28 -04:00
|
|
|
.Padding(0)
|
|
|
|
|
.IsEnabled_Lambda(IsTaskEnabledFunc)
|
2023-06-05 13:12:19 -04:00
|
|
|
[
|
2023-06-15 11:38:28 -04:00
|
|
|
SNew(SOverlay)
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Margin(FMargin(4.f, 0.f))
|
|
|
|
|
.Text(TaskName)
|
|
|
|
|
.TextStyle(FStateTreeEditorStyle::Get(), "StateTree.Task.Title")
|
|
|
|
|
.IsEnabled_Lambda(IsTaskEnabledFunc)
|
|
|
|
|
.ToolTipText(FText::FromName(Task->Name))
|
|
|
|
|
]
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
// Task Breakpoint box
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.VAlign(VAlign_Top)
|
|
|
|
|
.HAlign(HAlign_Left)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBox)
|
|
|
|
|
.Padding(FMargin(0.0f, -10.0f, 0.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.DesiredSizeOverride(FVector2D(10.f, 10.f))
|
|
|
|
|
.Image(FStateTreeEditorStyle::Get().GetBrush(TEXT("StateTreeEditor.Debugger.Breakpoint.EnabledAndValid")))
|
|
|
|
|
.Visibility_Lambda(IsTaskBreakpointEnabledFunc)
|
|
|
|
|
.ToolTipText_Lambda(GetTaskBreakpointTooltipFunc)
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
2023-06-05 13:12:19 -04:00
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TasksBox;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-01 09:06:53 -04:00
|
|
|
void SStateTreeViewRow::RequestRename() const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
if (NameTextBlock)
|
|
|
|
|
{
|
|
|
|
|
NameTextBlock->EnterEditingMode();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FSlateColor SStateTreeViewRow::GetTitleColor() const
|
|
|
|
|
{
|
2023-09-26 11:50:26 -04:00
|
|
|
const UStateTreeState* State = WeakState.Get();
|
|
|
|
|
const UStateTreeEditorData* EditorData = WeakTreeData.Get();
|
|
|
|
|
|
|
|
|
|
if (State != nullptr && EditorData != nullptr)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-09-26 11:50:26 -04:00
|
|
|
if (const FStateTreeEditorColor* FoundColor = EditorData->FindColor(State->ColorRef))
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-09-26 11:50:26 -04:00
|
|
|
if (IsRootState() || State->Type == EStateTreeStateType::Subtree)
|
|
|
|
|
{
|
|
|
|
|
return UE::StateTree::Editor::LerpColorSRGB(FoundColor->Color, FColor::Black, 0.25f);
|
|
|
|
|
}
|
|
|
|
|
return FoundColor->Color;
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FLinearColor(FColor(31, 151, 167));
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-14 13:35:46 -04:00
|
|
|
FSlateColor SStateTreeViewRow::GetActiveStateColor() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
if (StateTreeViewModel && StateTreeViewModel->IsStateActiveInDebugger(*State))
|
|
|
|
|
{
|
|
|
|
|
return FLinearColor::Yellow;
|
|
|
|
|
}
|
2023-04-12 07:59:16 -04:00
|
|
|
if (StateTreeViewModel && StateTreeViewModel->IsSelected(State))
|
|
|
|
|
{
|
|
|
|
|
return FLinearColor(FColor(236, 134, 39));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FLinearColor::Transparent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FSlateColor SStateTreeViewRow::GetSubTreeMarkerColor() const
|
|
|
|
|
{
|
|
|
|
|
// Show color for subtree.
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
if (IsRootState() || State->Type == EStateTreeStateType::Subtree)
|
|
|
|
|
{
|
2023-09-26 11:50:26 -04:00
|
|
|
const FSlateColor TitleColor = GetTitleColor();
|
|
|
|
|
return UE::StateTree::Editor::LerpColorSRGB(TitleColor.GetSpecifiedColor(), FLinearColor::White, 0.2f);
|
2023-04-12 07:59:16 -04:00
|
|
|
}
|
2023-03-14 13:35:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return GetTitleColor();
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
FText SStateTreeViewRow::GetStateDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
return FText::FromName(State->Name);
|
|
|
|
|
}
|
|
|
|
|
return FText::FromName(FName());
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-21 10:32:41 -04:00
|
|
|
FText SStateTreeViewRow::GetStateIDDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
return FText::FromString(*LexToString(State->ID));
|
|
|
|
|
}
|
|
|
|
|
return FText::FromName(FName());
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetConditionVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2021-10-21 04:08:20 -04:00
|
|
|
return State->EnterConditions.Num() > 0 ? EVisibility::Visible : EVisibility::Collapsed;
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-15 11:38:28 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetStateBreakpointVisibility() const
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-06-15 11:38:28 -04:00
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
const UStateTreeState* State = WeakState.Get();
|
|
|
|
|
const UStateTreeEditorData* EditorData = WeakTreeData.Get();
|
|
|
|
|
if (State != nullptr && EditorData != nullptr)
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-06-15 11:38:28 -04:00
|
|
|
return (EditorData != nullptr && EditorData->HasAnyBreakpoint(State->ID)) ? EVisibility::Visible : EVisibility::Hidden;
|
|
|
|
|
}
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
|
|
|
|
return EVisibility::Hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FText SStateTreeViewRow::GetStateBreakpointTooltipText() const
|
|
|
|
|
{
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
const UStateTreeState* State = WeakState.Get();
|
|
|
|
|
const UStateTreeEditorData* EditorData = WeakTreeData.Get();
|
|
|
|
|
if (State != nullptr && EditorData != nullptr)
|
|
|
|
|
{
|
|
|
|
|
const bool bHasBreakpointOnEnter = EditorData->HasBreakpoint(State->ID, EStateTreeBreakpointType::OnEnter);
|
|
|
|
|
const bool bHasBreakpointOnExit = EditorData->HasBreakpoint(State->ID, EStateTreeBreakpointType::OnExit);
|
|
|
|
|
|
|
|
|
|
if (bHasBreakpointOnEnter && bHasBreakpointOnExit)
|
2023-03-14 13:35:46 -04:00
|
|
|
{
|
2023-06-15 11:38:28 -04:00
|
|
|
return LOCTEXT("StateTreeStateBreakpointOnEnterAndOnExitTooltip","Break when entering or exiting state");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bHasBreakpointOnEnter)
|
|
|
|
|
{
|
|
|
|
|
return LOCTEXT("StateTreeStateBreakpointOnEnterTooltip","Break when entering state");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bHasBreakpointOnExit)
|
|
|
|
|
{
|
|
|
|
|
return LOCTEXT("StateTreeStateBreakpointOnExitTooltip","Break when exiting state");
|
2023-03-14 13:35:46 -04:00
|
|
|
}
|
|
|
|
|
}
|
2023-06-15 11:38:28 -04:00
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
|
|
|
|
return FText::GetEmpty();
|
2023-03-14 13:35:46 -04:00
|
|
|
}
|
2022-04-28 03:54:07 -04:00
|
|
|
|
2023-04-12 07:59:16 -04:00
|
|
|
const FSlateBrush* SStateTreeViewRow::GetSelectorIcon() const
|
2022-04-28 03:54:07 -04:00
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2023-04-12 07:59:16 -04:00
|
|
|
if (State->SelectionBehavior == EStateTreeStateSelectionBehavior::None)
|
2022-04-28 03:54:07 -04:00
|
|
|
{
|
2023-04-12 07:59:16 -04:00
|
|
|
return FStateTreeEditorStyle::Get().GetBrush("StateTreeEditor.SelectNone");
|
2022-04-28 03:54:07 -04:00
|
|
|
}
|
2023-04-12 07:59:16 -04:00
|
|
|
else if (State->SelectionBehavior == EStateTreeStateSelectionBehavior::TryEnterState)
|
2022-04-28 03:54:07 -04:00
|
|
|
{
|
2023-04-12 07:59:16 -04:00
|
|
|
return FStateTreeEditorStyle::Get().GetBrush("StateTreeEditor.TryEnterState");
|
2022-04-28 03:54:07 -04:00
|
|
|
}
|
2023-04-12 07:59:16 -04:00
|
|
|
else if (State->SelectionBehavior == EStateTreeStateSelectionBehavior::TrySelectChildrenInOrder)
|
2022-04-28 03:54:07 -04:00
|
|
|
{
|
2023-04-12 07:59:16 -04:00
|
|
|
if (State->Children.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
// Backwards compatible behavior
|
|
|
|
|
return FStateTreeEditorStyle::Get().GetBrush("StateTreeEditor.TryEnterState");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return FStateTreeEditorStyle::Get().GetBrush("StateTreeEditor.TrySelectChildrenInOrder");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (State->SelectionBehavior == EStateTreeStateSelectionBehavior::TryFollowTransitions)
|
|
|
|
|
{
|
|
|
|
|
return FStateTreeEditorStyle::Get().GetBrush("StateTreeEditor.TryFollowTransitions");
|
2022-04-28 03:54:07 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-12 07:59:16 -04:00
|
|
|
return nullptr;
|
2022-04-28 03:54:07 -04:00
|
|
|
}
|
|
|
|
|
|
2023-04-12 07:59:16 -04:00
|
|
|
FText SStateTreeViewRow::GetSelectorTooltip() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
const UEnum* Enum = StaticEnum<EStateTreeStateSelectionBehavior>();
|
|
|
|
|
check(Enum);
|
|
|
|
|
const int32 Index = Enum->GetIndexByValue((int64)State->SelectionBehavior);
|
|
|
|
|
|
|
|
|
|
if (State->SelectionBehavior == EStateTreeStateSelectionBehavior::None)
|
|
|
|
|
{
|
|
|
|
|
return Enum->GetToolTipTextByIndex(Index);
|
|
|
|
|
}
|
|
|
|
|
else if (State->SelectionBehavior == EStateTreeStateSelectionBehavior::TryEnterState)
|
|
|
|
|
{
|
|
|
|
|
return Enum->GetToolTipTextByIndex(Index);
|
|
|
|
|
}
|
|
|
|
|
else if (State->SelectionBehavior == EStateTreeStateSelectionBehavior::TrySelectChildrenInOrder)
|
|
|
|
|
{
|
|
|
|
|
if (State->Children.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
const int32 EnterStateIndex = Enum->GetIndexByValue((int64)EStateTreeStateSelectionBehavior::TryEnterState);
|
|
|
|
|
return FText::Format(LOCTEXT("ConvertedToEnterState", "{0}\nAutomatically converted from '{1}' becase the State has no child States."),
|
|
|
|
|
Enum->GetToolTipTextByIndex(EnterStateIndex), UEnum::GetDisplayValueAsText(State->SelectionBehavior));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return Enum->GetToolTipTextByIndex(Index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (State->SelectionBehavior == EStateTreeStateSelectionBehavior::TryFollowTransitions)
|
|
|
|
|
{
|
|
|
|
|
return Enum->GetToolTipTextByIndex(Index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FText SStateTreeViewRow::GetStateTypeTooltip() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
const UEnum* Enum = StaticEnum<EStateTreeStateType>();
|
|
|
|
|
check(Enum);
|
|
|
|
|
const int32 Index = Enum->GetIndexByValue((int64)State->Type);
|
|
|
|
|
return Enum->GetToolTipTextByIndex(Index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetTasksVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
int32 ValidCount = 0;
|
2021-10-21 04:08:20 -04:00
|
|
|
for (int32 i = 0; i < State->Tasks.Num(); i++)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-03-14 13:35:46 -04:00
|
|
|
if (State->Tasks[i].Node.GetPtr<FStateTreeTaskBase>())
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2021-10-21 04:08:20 -04:00
|
|
|
ValidCount++;
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ValidCount > 0 ? EVisibility::Visible : EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-05 03:20:57 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetLinkedStateVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2023-11-30 07:03:20 -05:00
|
|
|
return (State->Type == EStateTreeStateType::Linked || State->Type == EStateTreeStateType::LinkedAsset) ? EVisibility::Visible : EVisibility::Collapsed;
|
2022-04-05 03:20:57 -04:00
|
|
|
}
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FText SStateTreeViewRow::GetLinkedStateDesc() const
|
|
|
|
|
{
|
|
|
|
|
const UStateTreeState* State = WeakState.Get();
|
|
|
|
|
if (!State)
|
|
|
|
|
{
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (State->Type == EStateTreeStateType::Linked)
|
|
|
|
|
{
|
2022-09-30 11:31:57 -04:00
|
|
|
return FText::FromName(State->LinkedSubtree.Name);
|
2022-04-05 03:20:57 -04:00
|
|
|
}
|
2023-11-30 07:03:20 -05:00
|
|
|
else if (State->Type == EStateTreeStateType::LinkedAsset)
|
|
|
|
|
{
|
2023-12-04 03:46:59 -05:00
|
|
|
return FText::FromString(GetNameSafe(State->LinkedAsset.Get()));
|
2023-11-30 07:03:20 -05:00
|
|
|
}
|
2022-04-05 03:20:57 -04:00
|
|
|
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-01 09:06:53 -04:00
|
|
|
bool SStateTreeViewRow::HasParentTransitionForTrigger(const UStateTreeState& State, const EStateTreeTransitionTrigger Trigger) const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
EStateTreeTransitionTrigger CombinedTrigger = EStateTreeTransitionTrigger::None;
|
2021-09-28 13:33:17 -04:00
|
|
|
for (const UStateTreeState* ParentState = State.Parent; ParentState != nullptr; ParentState = ParentState->Parent)
|
|
|
|
|
{
|
2021-10-21 04:08:20 -04:00
|
|
|
for (const FStateTreeTransition& Transition : ParentState->Transitions)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
CombinedTrigger |= Transition.Trigger;
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-09-01 09:06:53 -04:00
|
|
|
return EnumHasAllFlags(CombinedTrigger, Trigger);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
|
2023-06-14 06:17:56 -04:00
|
|
|
|
|
|
|
|
FText SStateTreeViewRow::GetLinkDescription(const FStateTreeStateLink& Link)
|
|
|
|
|
{
|
|
|
|
|
switch (Link.LinkType)
|
|
|
|
|
{
|
|
|
|
|
case EStateTreeTransitionType::None:
|
|
|
|
|
return LOCTEXT("TransitionNoneStyled", "[None]");
|
|
|
|
|
break;
|
|
|
|
|
case EStateTreeTransitionType::Succeeded:
|
|
|
|
|
return LOCTEXT("TransitionTreeSucceededStyled", "[Succeeded]");
|
|
|
|
|
break;
|
|
|
|
|
case EStateTreeTransitionType::Failed:
|
|
|
|
|
return LOCTEXT("TransitionTreeFailedStyled", "[Failed]");
|
|
|
|
|
break;
|
|
|
|
|
case EStateTreeTransitionType::NextState:
|
|
|
|
|
return LOCTEXT("TransitionNextStateStyled", "[Next]");
|
|
|
|
|
break;
|
2023-10-17 16:15:53 -04:00
|
|
|
case EStateTreeTransitionType::NextSelectableState:
|
|
|
|
|
return LOCTEXT("TransitionNextSelectableStateStyled", "[Next Selectable]");
|
|
|
|
|
break;
|
2023-06-14 06:17:56 -04:00
|
|
|
case EStateTreeTransitionType::GotoState:
|
|
|
|
|
return FText::FromName(Link.Name);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ensureMsgf(false, TEXT("Unhandled transition type."));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
};
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
FText SStateTreeViewRow::GetTransitionsDesc(const UStateTreeState& State, const EStateTreeTransitionTrigger Trigger, const FTransitionDescFilterOptions FilterOptions) const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
TArray<FText> DescItems;
|
2023-06-20 13:49:25 -04:00
|
|
|
const UStateTreeEditorData* TreeEditorData = WeakTreeData.Get();
|
|
|
|
|
|
2021-10-21 04:08:20 -04:00
|
|
|
for (const FStateTreeTransition& Transition : State.Transitions)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-06-20 13:49:25 -04:00
|
|
|
// Apply filter for enabled/disabled transitions
|
|
|
|
|
if ((FilterOptions.Enabled == ETransitionDescRequirement::RequiredTrue && Transition.bTransitionEnabled == false)
|
|
|
|
|
|| (FilterOptions.Enabled == ETransitionDescRequirement::RequiredFalse && Transition.bTransitionEnabled))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
// Apply filter for transitions with/without breakpoint
|
|
|
|
|
const bool bHasBreakpoint = TreeEditorData != nullptr && TreeEditorData->HasBreakpoint(Transition.ID, EStateTreeBreakpointType::OnTransition);
|
|
|
|
|
if ((FilterOptions.WithBreakpoint == ETransitionDescRequirement::RequiredTrue && bHasBreakpoint == false)
|
|
|
|
|
|| (FilterOptions.WithBreakpoint == ETransitionDescRequirement::RequiredFalse && bHasBreakpoint))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
|
|
|
|
|
|
|
|
|
const bool bMatch = FilterOptions.bUseMask ? EnumHasAnyFlags(Transition.Trigger, Trigger) : Transition.Trigger == Trigger;
|
2022-09-01 09:06:53 -04:00
|
|
|
if (bMatch)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-06-14 06:17:56 -04:00
|
|
|
DescItems.Add(GetLinkDescription(Transition.State));
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-14 06:17:56 -04:00
|
|
|
// Find states from transition tasks
|
|
|
|
|
if (EnumHasAnyFlags(Trigger, EStateTreeTransitionTrigger::OnTick | EStateTreeTransitionTrigger::OnEvent))
|
|
|
|
|
{
|
|
|
|
|
auto AddLinksFromStruct = [&DescItems](FStateTreeDataView Struct)
|
|
|
|
|
{
|
|
|
|
|
if (!Struct.IsValid())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (TPropertyValueIterator<FStructProperty> It(Struct.GetStruct(), Struct.GetMemory()); It; ++It)
|
|
|
|
|
{
|
|
|
|
|
const UScriptStruct* StructType = It.Key()->Struct;
|
|
|
|
|
if (StructType == TBaseStructure<FStateTreeStateLink>::Get())
|
|
|
|
|
{
|
|
|
|
|
const FStateTreeStateLink& Link = *static_cast<const FStateTreeStateLink*>(It.Value());
|
|
|
|
|
if (Link.LinkType != EStateTreeTransitionType::None)
|
|
|
|
|
{
|
|
|
|
|
DescItems.Add(GetLinkDescription(Link));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const FStateTreeEditorNode& Task : State.Tasks)
|
|
|
|
|
{
|
|
|
|
|
AddLinksFromStruct(FStateTreeDataView(Task.Node.GetScriptStruct(), const_cast<uint8*>(Task.Node.GetMemory())));
|
|
|
|
|
AddLinksFromStruct(Task.GetInstance());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AddLinksFromStruct(FStateTreeDataView(State.SingleTask.Node.GetScriptStruct(), const_cast<uint8*>(State.SingleTask.Node.GetMemory())));
|
|
|
|
|
AddLinksFromStruct(State.SingleTask.GetInstance());
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
if (State.Children.Num() == 0
|
2022-04-05 03:20:57 -04:00
|
|
|
&& State.Type == EStateTreeStateType::State
|
2021-09-28 13:33:17 -04:00
|
|
|
&& DescItems.Num() == 0
|
2022-09-01 09:06:53 -04:00
|
|
|
&& EnumHasAnyFlags(Trigger, EStateTreeTransitionTrigger::OnStateCompleted))
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
if (HasParentTransitionForTrigger(State, Trigger))
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
DescItems.Add(LOCTEXT("TransitionActionHandleInParentStyled", "[Parent]"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DescItems.Add(LOCTEXT("TransitionActionMissingTransition", "Missing Transition"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FText::Join(FText::FromString(TEXT(", ")), DescItems);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
FText SStateTreeViewRow::GetTransitionsIcon(const UStateTreeState& State, const EStateTreeTransitionTrigger Trigger, const FTransitionDescFilterOptions FilterOptions) const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
enum EIconType
|
|
|
|
|
{
|
|
|
|
|
IconNone = 0,
|
2023-03-14 13:35:46 -04:00
|
|
|
IconRightArrow = 1 << 0,
|
|
|
|
|
IconDownArrow = 1 << 1,
|
|
|
|
|
IconLevelUp = 1 << 2,
|
|
|
|
|
IconWarning = 1 << 3,
|
|
|
|
|
};
|
2021-09-28 13:33:17 -04:00
|
|
|
uint8 IconType = IconNone;
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
const UStateTreeEditorData* TreeEditorData = WeakTreeData.Get();
|
|
|
|
|
|
2021-10-21 04:08:20 -04:00
|
|
|
for (const FStateTreeTransition& Transition : State.Transitions)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-06-20 13:49:25 -04:00
|
|
|
// Apply filter for enabled/disabled transitions
|
|
|
|
|
if ((FilterOptions.Enabled == ETransitionDescRequirement::RequiredTrue && Transition.bTransitionEnabled == false)
|
|
|
|
|
|| (FilterOptions.Enabled == ETransitionDescRequirement::RequiredFalse && Transition.bTransitionEnabled))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
// Apply filter for transitions with/without breakpoint
|
|
|
|
|
const bool bHasBreakpoint = TreeEditorData != nullptr && TreeEditorData->HasBreakpoint(Transition.ID, EStateTreeBreakpointType::OnTransition);
|
|
|
|
|
if ((FilterOptions.WithBreakpoint == ETransitionDescRequirement::RequiredTrue && bHasBreakpoint == false)
|
|
|
|
|
|| (FilterOptions.WithBreakpoint == ETransitionDescRequirement::RequiredFalse && bHasBreakpoint))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
// The icons here depict "transition direction", not the type specifically.
|
2023-06-20 13:49:25 -04:00
|
|
|
const bool bMatch = FilterOptions.bUseMask ? EnumHasAnyFlags(Transition.Trigger, Trigger) : Transition.Trigger == Trigger;
|
2022-09-01 09:06:53 -04:00
|
|
|
if (bMatch)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-01-23 12:48:04 -05:00
|
|
|
switch (Transition.State.LinkType)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-01-23 12:48:04 -05:00
|
|
|
case EStateTreeTransitionType::None:
|
2021-09-28 13:33:17 -04:00
|
|
|
IconType |= IconRightArrow;
|
|
|
|
|
break;
|
|
|
|
|
case EStateTreeTransitionType::Succeeded:
|
|
|
|
|
IconType |= IconRightArrow;
|
|
|
|
|
break;
|
|
|
|
|
case EStateTreeTransitionType::Failed:
|
|
|
|
|
IconType |= IconRightArrow;
|
|
|
|
|
break;
|
|
|
|
|
case EStateTreeTransitionType::NextState:
|
2023-10-17 16:15:53 -04:00
|
|
|
case EStateTreeTransitionType::NextSelectableState:
|
2021-09-28 13:33:17 -04:00
|
|
|
IconType |= IconDownArrow;
|
|
|
|
|
break;
|
|
|
|
|
case EStateTreeTransitionType::GotoState:
|
|
|
|
|
IconType |= IconRightArrow;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ensureMsgf(false, TEXT("Unhandled transition type."));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FMath::CountBits(static_cast<uint64>(IconType)) > 1)
|
|
|
|
|
{
|
|
|
|
|
// Prune down to just one icon.
|
|
|
|
|
IconType = IconRightArrow;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (State.Children.Num() == 0
|
2022-04-05 03:20:57 -04:00
|
|
|
&& State.Type == EStateTreeStateType::State
|
2023-03-14 13:35:46 -04:00
|
|
|
&& IconType == IconNone
|
|
|
|
|
&& EnumHasAnyFlags(Trigger, EStateTreeTransitionTrigger::OnStateCompleted))
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
if (HasParentTransitionForTrigger(State, Trigger))
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
IconType = IconLevelUp;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
IconType = IconWarning;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (IconType)
|
|
|
|
|
{
|
|
|
|
|
case IconRightArrow:
|
|
|
|
|
return FEditorFontGlyphs::Long_Arrow_Right;
|
|
|
|
|
case IconDownArrow:
|
|
|
|
|
return FEditorFontGlyphs::Long_Arrow_Down;
|
|
|
|
|
case IconLevelUp:
|
|
|
|
|
return FEditorFontGlyphs::Level_Up;
|
|
|
|
|
case IconWarning:
|
|
|
|
|
return FEditorFontGlyphs::Exclamation_Triangle;
|
|
|
|
|
default:
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-01 09:06:53 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetTransitionsVisibility(const UStateTreeState& State, const EStateTreeTransitionTrigger Trigger) const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-05-08 13:32:14 -04:00
|
|
|
// Handle completed, succeeded and failed transitions.
|
2022-09-05 09:08:59 -04:00
|
|
|
if (EnumHasAnyFlags(Trigger, EStateTreeTransitionTrigger::OnStateCompleted))
|
2022-09-01 09:06:53 -04:00
|
|
|
{
|
2022-09-05 09:08:59 -04:00
|
|
|
const bool bIsLeafState = (State.Children.Num() == 0);
|
|
|
|
|
EStateTreeTransitionTrigger HandledTriggers = EStateTreeTransitionTrigger::None;
|
|
|
|
|
bool bExactMatch = false;
|
|
|
|
|
|
2022-09-01 09:06:53 -04:00
|
|
|
for (const FStateTreeTransition& Transition : State.Transitions)
|
|
|
|
|
{
|
2023-06-20 13:49:25 -04:00
|
|
|
// Skip disabled transitions
|
|
|
|
|
if (Transition.bTransitionEnabled == false)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 09:08:59 -04:00
|
|
|
HandledTriggers |= Transition.Trigger;
|
|
|
|
|
bExactMatch |= (Transition.Trigger == Trigger);
|
2023-06-20 13:49:25 -04:00
|
|
|
|
|
|
|
|
if (bExactMatch)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-09-01 09:06:53 -04:00
|
|
|
}
|
2021-09-28 13:33:17 -04:00
|
|
|
|
2022-09-05 09:08:59 -04:00
|
|
|
// Assume that leaf states should have completion transitions.
|
|
|
|
|
if (!bExactMatch && bIsLeafState)
|
|
|
|
|
{
|
|
|
|
|
// Find the missing transition type, note: Completed = Succeeded|Failed.
|
|
|
|
|
const EStateTreeTransitionTrigger MissingTriggers = HandledTriggers ^ EStateTreeTransitionTrigger::OnStateCompleted;
|
|
|
|
|
return MissingTriggers == Trigger ? EVisibility::Visible : EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bExactMatch ? EVisibility::Visible : EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-14 06:17:56 -04:00
|
|
|
// Find states from transition tasks
|
|
|
|
|
if (EnumHasAnyFlags(Trigger, EStateTreeTransitionTrigger::OnTick | EStateTreeTransitionTrigger::OnEvent))
|
|
|
|
|
{
|
|
|
|
|
auto HasAnyLinksInStruct = [](FStateTreeDataView Struct) -> bool
|
|
|
|
|
{
|
|
|
|
|
if (!Struct.IsValid())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
for (TPropertyValueIterator<FStructProperty> It(Struct.GetStruct(), Struct.GetMemory()); It; ++It)
|
|
|
|
|
{
|
|
|
|
|
const UScriptStruct* StructType = It.Key()->Struct;
|
|
|
|
|
if (StructType == TBaseStructure<FStateTreeStateLink>::Get())
|
|
|
|
|
{
|
|
|
|
|
const FStateTreeStateLink& Link = *static_cast<const FStateTreeStateLink*>(It.Value());
|
|
|
|
|
if (Link.LinkType != EStateTreeTransitionType::None)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const FStateTreeEditorNode& Task : State.Tasks)
|
|
|
|
|
{
|
|
|
|
|
if (HasAnyLinksInStruct(FStateTreeDataView(Task.Node.GetScriptStruct(), const_cast<uint8*>(Task.Node.GetMemory())))
|
|
|
|
|
|| HasAnyLinksInStruct(Task.GetInstance()))
|
|
|
|
|
{
|
|
|
|
|
return EVisibility::Visible;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HasAnyLinksInStruct(FStateTreeDataView(State.SingleTask.Node.GetScriptStruct(), const_cast<uint8*>(State.SingleTask.Node.GetMemory())))
|
|
|
|
|
|| HasAnyLinksInStruct(State.SingleTask.GetInstance()))
|
|
|
|
|
{
|
|
|
|
|
return EVisibility::Visible;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 09:08:59 -04:00
|
|
|
// Handle the test
|
2021-10-21 04:08:20 -04:00
|
|
|
for (const FStateTreeTransition& Transition : State.Transitions)
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2023-06-20 13:49:25 -04:00
|
|
|
// Skip disabled transitions
|
|
|
|
|
if (Transition.bTransitionEnabled == false)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 09:08:59 -04:00
|
|
|
if (EnumHasAnyFlags(Trigger, Transition.Trigger))
|
|
|
|
|
{
|
|
|
|
|
return EVisibility::Visible;
|
|
|
|
|
}
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
2022-09-05 09:08:59 -04:00
|
|
|
return EVisibility::Collapsed;
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetTransitionsBreakpointVisibility(const UStateTreeState& State, const EStateTreeTransitionTrigger Trigger) const
|
|
|
|
|
{
|
|
|
|
|
#if WITH_STATETREE_DEBUGGER
|
|
|
|
|
if (const UStateTreeEditorData* TreeEditorData = WeakTreeData.Get())
|
|
|
|
|
{
|
|
|
|
|
for (const FStateTreeTransition& Transition : State.Transitions)
|
|
|
|
|
{
|
|
|
|
|
if (Transition.bTransitionEnabled && EnumHasAnyFlags(Trigger, Transition.Trigger))
|
|
|
|
|
{
|
|
|
|
|
if (TreeEditorData->HasBreakpoint(Transition.ID, EStateTreeBreakpointType::OnTransition))
|
|
|
|
|
{
|
|
|
|
|
return GetTransitionsVisibility(State, Trigger);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif // WITH_STATETREE_DEBUGGER
|
|
|
|
|
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetCompletedTransitionVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsVisibility(*State, EStateTreeTransitionTrigger::OnStateCompleted);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return EVisibility::Visible;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetCompletedTransitionBreakpointVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
return GetTransitionsBreakpointVisibility(*State, EStateTreeTransitionTrigger::OnStateCompleted);
|
|
|
|
|
}
|
|
|
|
|
return EVisibility::Visible;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
FText SStateTreeViewRow::GetCompletedTransitionsDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsDesc(*State, EStateTreeTransitionTrigger::OnStateCompleted);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return LOCTEXT("Invalid", "Invalid");
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
FText SStateTreeViewRow::GetCompletedTransitionWithBreakpointDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
FTransitionDescFilterOptions FilterOptions;
|
|
|
|
|
FilterOptions.WithBreakpoint = ETransitionDescRequirement::RequiredTrue;
|
|
|
|
|
return GetTransitionsDesc(*State, EStateTreeTransitionTrigger::OnStateCompleted, FilterOptions);
|
|
|
|
|
}
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
FText SStateTreeViewRow::GetCompletedTransitionsIcon() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsIcon(*State, EStateTreeTransitionTrigger::OnStateCompleted);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EVisibility SStateTreeViewRow::GetSucceededTransitionVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsVisibility(*State, EStateTreeTransitionTrigger::OnStateSucceeded);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetSucceededTransitionBreakpointVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
return GetTransitionsBreakpointVisibility(*State, EStateTreeTransitionTrigger::OnStateSucceeded);
|
|
|
|
|
}
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
FText SStateTreeViewRow::GetSucceededTransitionDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsDesc(*State, EStateTreeTransitionTrigger::OnStateSucceeded);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
FText SStateTreeViewRow::GetSucceededTransitionWithBreakpointDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
FTransitionDescFilterOptions FilterOptions;
|
|
|
|
|
FilterOptions.WithBreakpoint = ETransitionDescRequirement::RequiredTrue;
|
|
|
|
|
return GetTransitionsDesc(*State, EStateTreeTransitionTrigger::OnStateSucceeded, FilterOptions);
|
|
|
|
|
}
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
FText SStateTreeViewRow::GetSucceededTransitionIcon() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsIcon(*State, EStateTreeTransitionTrigger::OnStateSucceeded);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EVisibility SStateTreeViewRow::GetFailedTransitionVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsVisibility(*State, EStateTreeTransitionTrigger::OnStateFailed);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetFailedTransitionBreakpointVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
return GetTransitionsBreakpointVisibility(*State, EStateTreeTransitionTrigger::OnStateFailed);
|
|
|
|
|
}
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
FText SStateTreeViewRow::GetFailedTransitionDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsDesc(*State, EStateTreeTransitionTrigger::OnStateFailed);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return LOCTEXT("Invalid", "Invalid");
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
FText SStateTreeViewRow::GetFailedTransitionWithBreakpointDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
FTransitionDescFilterOptions FilterOptions;
|
|
|
|
|
FilterOptions.WithBreakpoint = ETransitionDescRequirement::RequiredTrue;
|
|
|
|
|
return GetTransitionsDesc(*State, EStateTreeTransitionTrigger::OnStateFailed, FilterOptions);
|
|
|
|
|
}
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
FText SStateTreeViewRow::GetFailedTransitionIcon() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsIcon(*State, EStateTreeTransitionTrigger::OnStateFailed);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return FEditorFontGlyphs::Ban;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EVisibility SStateTreeViewRow::GetConditionalTransitionsVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
return GetTransitionsVisibility(*State, EStateTreeTransitionTrigger::OnTick | EStateTreeTransitionTrigger::OnEvent);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 13:49:25 -04:00
|
|
|
EVisibility SStateTreeViewRow::GetConditionalTransitionsBreakpointVisibility() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
return GetTransitionsBreakpointVisibility(*State, EStateTreeTransitionTrigger::OnTick | EStateTreeTransitionTrigger::OnEvent);
|
|
|
|
|
}
|
|
|
|
|
return EVisibility::Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 13:33:17 -04:00
|
|
|
FText SStateTreeViewRow::GetConditionalTransitionsDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
2023-06-20 13:49:25 -04:00
|
|
|
FTransitionDescFilterOptions FilterOptions;
|
|
|
|
|
FilterOptions.bUseMask = true;
|
|
|
|
|
return GetTransitionsDesc(*State, EStateTreeTransitionTrigger::OnTick | EStateTreeTransitionTrigger::OnEvent, FilterOptions);
|
|
|
|
|
}
|
|
|
|
|
return FText::GetEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FText SStateTreeViewRow::GetConditionalTransitionsWithBreakpointDesc() const
|
|
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
FTransitionDescFilterOptions FilterOptions;
|
|
|
|
|
FilterOptions.WithBreakpoint = ETransitionDescRequirement::RequiredTrue;
|
|
|
|
|
FilterOptions.bUseMask = true;
|
|
|
|
|
return GetTransitionsDesc(*State, EStateTreeTransitionTrigger::OnTick | EStateTreeTransitionTrigger::OnEvent, FilterOptions);
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
2022-09-01 09:06:53 -04:00
|
|
|
return FText::GetEmpty();
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
|
2022-04-28 03:54:07 -04:00
|
|
|
bool SStateTreeViewRow::IsRootState() const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
// Routines can be identified by not having parent state.
|
|
|
|
|
const UStateTreeState* State = WeakState.Get();
|
|
|
|
|
return State ? State->Parent == nullptr : false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-01 09:06:53 -04:00
|
|
|
bool SStateTreeViewRow::IsStateSelected() const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
if (const UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
if (StateTreeViewModel)
|
|
|
|
|
{
|
|
|
|
|
return StateTreeViewModel->IsSelected(State);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-01 09:06:53 -04:00
|
|
|
void SStateTreeViewRow::HandleNodeLabelTextCommitted(const FText& NewLabel, ETextCommit::Type CommitType) const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
if (StateTreeViewModel)
|
|
|
|
|
{
|
|
|
|
|
if (UStateTreeState* State = WeakState.Get())
|
|
|
|
|
{
|
|
|
|
|
StateTreeViewModel->RenameState(State, FName(*FText::TrimPrecedingAndTrailing(NewLabel).ToString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-01 09:06:53 -04:00
|
|
|
FReply SStateTreeViewRow::HandleDragDetected(const FGeometry&, const FPointerEvent&) const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
return FReply::Handled().BeginDragDrop(FActionTreeViewDragDrop::New(WeakState.Get()));
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-30 11:31:57 -04:00
|
|
|
TOptional<EItemDropZone> SStateTreeViewRow::HandleCanAcceptDrop(const FDragDropEvent& DragDropEvent, EItemDropZone DropZone, TWeakObjectPtr<UStateTreeState> TargetState) const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
const TSharedPtr<FActionTreeViewDragDrop> DragDropOperation = DragDropEvent.GetOperationAs<FActionTreeViewDragDrop>();
|
2021-09-28 13:33:17 -04:00
|
|
|
if (DragDropOperation.IsValid())
|
|
|
|
|
{
|
|
|
|
|
// Cannot drop on selection or child of selection.
|
2022-09-30 11:31:57 -04:00
|
|
|
if (StateTreeViewModel && StateTreeViewModel->IsChildOfSelection(TargetState.Get()))
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
|
|
|
|
return TOptional<EItemDropZone>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DropZone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TOptional<EItemDropZone>();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-30 11:31:57 -04:00
|
|
|
FReply SStateTreeViewRow::HandleAcceptDrop(const FDragDropEvent& DragDropEvent, EItemDropZone DropZone, TWeakObjectPtr<UStateTreeState> TargetState) const
|
2021-09-28 13:33:17 -04:00
|
|
|
{
|
2022-09-01 09:06:53 -04:00
|
|
|
const TSharedPtr<FActionTreeViewDragDrop> DragDropOperation = DragDropEvent.GetOperationAs<FActionTreeViewDragDrop>();
|
2021-09-28 13:33:17 -04:00
|
|
|
if (DragDropOperation.IsValid())
|
|
|
|
|
{
|
|
|
|
|
if (StateTreeViewModel)
|
|
|
|
|
{
|
|
|
|
|
if (DropZone == EItemDropZone::AboveItem)
|
|
|
|
|
{
|
2022-09-30 11:31:57 -04:00
|
|
|
StateTreeViewModel->MoveSelectedStatesBefore(TargetState.Get());
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
else if (DropZone == EItemDropZone::BelowItem)
|
|
|
|
|
{
|
2022-09-30 11:31:57 -04:00
|
|
|
StateTreeViewModel->MoveSelectedStatesAfter(TargetState.Get());
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-09-30 11:31:57 -04:00
|
|
|
StateTreeViewModel->MoveSelectedStatesInto(TargetState.Get());
|
2021-09-28 13:33:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FReply::Handled();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FReply::Unhandled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|