Compare commits

..

No commits in common. "main" and "trying-to-add-a-combo-graph-editor" have entirely different histories.

27 changed files with 191 additions and 456 deletions

View File

@ -6,7 +6,7 @@
"Description": "A set of components and classes for capturing Enhanced Input actions for buffering actions and stringing them into complex combos.",
"Category": "Input",
"CreatedBy": "Jamie Greunbaum",
"EngineVersion": "5.4.0",
"EngineVersion": "5.3.0",
"CanContainContent": true,
"IsBetaVersion": true,
"IsExperimentalVersion": true,

View File

@ -26,6 +26,24 @@ UComboActionGraph::UComboActionGraph()
#endif
}
bool UComboActionGraph::CanStartDialogueGraph() const
{
if (this->AllNodes.Num() == 0)
{
return false;
}
for (const UComboActionGraphNode *Itr : this->AllNodes)
{
if (!Itr || !Itr->ValidateNodeRuntime())
{
return false;
}
}
return true;
}
void UComboActionGraph::CreateGraph()
{
#if WITH_EDITOR
@ -51,7 +69,7 @@ void UComboActionGraph::ClearGraph()
for (UComboActionGraphNode *Node : this->AllNodes)
{
Node->ParentNodes.Empty();
Node->ChildNodes.Empty();
Node->ChildrenNodes.Empty();
Node->Edges.Empty();
}
@ -108,10 +126,9 @@ bool UComboActionGraph::ValidateGraph(TArray<FText> &ValidationErrors, bool Rich
EDataValidationResult UComboActionGraph::IsDataValid(TArray<FText>& ValidationErrors)
{
//return this->ValidateGraph(ValidationErrors, false)
// ? EDataValidationResult::Valid
// : EDataValidationResult::Invalid;
return EDataValidationResult::NotValidated;
return this->ValidateGraph(ValidationErrors, false)
? EDataValidationResult::Valid
: EDataValidationResult::Invalid;
}
#endif

View File

@ -19,28 +19,14 @@ UComboManagerComponent::UComboManagerComponent()
this->PrimaryComponentTick.bStartWithTickEnabled = false;
this->PrimaryComponentTick.bTickEvenWhenPaused = false;
this->PrimaryComponentTick.bCanEverTick = false;
this->bWantsInitializeComponent = true;
}
void UComboManagerComponent::InitializeComponent()
void UComboManagerComponent::BeginPlay()
{
Super::InitializeComponent();
Super::BeginPlay();
checkf(this->ComboGraph, TEXT("No combo graph is set for %s in actor %s"), *UComboManagerComponent::StaticClass()->GetName(), *this->GetOwner()->GetName());
this->PreviousNode = this->ActiveNode = this->ComboGraph->StartNode;
}
void UComboManagerComponent::SetComboGraph(const UComboActionGraph *Graph)
{
checkf(Graph, TEXT("Attempting to set a null combo graph."));
this->ComboGraph = Graph;
this->FoundInputsCache.Empty();
this->FindAllUsedInputs();
this->ResetCombo();
this->ActiveNode = this->ComboGraph->StartNode;
}
@ -124,41 +110,12 @@ void UComboManagerComponent::DEBUG__UnlockAction(TObjectPtr<const UComboInputAss
void UComboManagerComponent::ReleaseComboAction(const class UComboInputAsset *Input)
{
if (this->LastComboAction && this->ActiveNode)
if (this->LastComboAction)
{
// See if we have a fallback we can release.
const TObjectPtr<const UComboAction> *FallbackAction = this->FallbackActions.Find(Input);
if (FallbackAction && *FallbackAction == this->LastComboAction)
{
this->ResetCombo();
this->BroadcastDelegates(*FallbackAction, EComboActionTriggerEvent::Released);
UE_LOG(LogComboManagerComponent, Verbose, TEXT("Fallback action %s released"), *(*FallbackAction)->ActionName.ToString());
}
else
{
// Find a node that matches the release action.
const UComboAction *ComboAction = nullptr;
for (const UComboActionGraphNode *Node : this->ActiveNode->ChildNodes)
{
if (const UComboActionGraphNode_ActionNode *ActionNode = StaticCast<const UComboActionGraphNode_ActionNode *>(Node))
{
if (ActionNode->GetTriggerEvent() == EComboActionTriggerEvent::Released)
{
ComboAction = ActionNode->GetComboAction();
break;
}
}
}
if (ComboAction)
{
this->BroadcastDelegates(ComboAction, EComboActionTriggerEvent::Released);
UE_LOG(LogComboManagerComponent, Verbose, TEXT("%s released"), *ComboAction->ActionName.ToString());
}
}
}
this->BroadcastDelegates(this->LastComboAction, EComboActionTriggerEvent::Released);
this->LastComboAction = nullptr;
}
}
void UComboManagerComponent::BeginNodeTransition(const UComboActionGraphNode *NextNode)
@ -178,73 +135,25 @@ void UComboManagerComponent::FinishTransition()
void UComboManagerComponent::ResetCombo()
{
this->GetWorld()->GetTimerManager().ClearTimer(this->DEBUG__ResetComboTimer);
this->PreviousNode = this->ActiveNode = this->ComboGraph->StartNode;
APlayerController *Controller = UGameplayStatics::GetPlayerController(this, 0);
if (UInputBufferComponent *InputComponent = Cast<UInputBufferComponent>(Controller->InputComponent))
{
for (const UComboInputAsset *Unlock : this->FoundInputsCache)
{
InputComponent->UnlockComboInput(Unlock);
}
}
this->PreviousNode = this->ActiveNode;
this->ActiveNode = this->ComboGraph->StartNode;
}
TSet<const UComboInputAsset *> &UComboManagerComponent::FindAllUsedInputs()
{
if (this->FoundInputsCache.IsEmpty())
{
// First check the graph for inputs to respond to.
this->FindAllUsedInputs_RecurseGraph(this->ComboGraph->StartNode, this->FoundInputsCache);
// Next check the fallback actions for supplementary inputs to respond to.
TArray<TObjectPtr<const UComboInputAsset>> FallbackInputs;
this->FallbackActions.GetKeys(FallbackInputs);
for (const TObjectPtr<const UComboInputAsset> &FallbackInput : FallbackInputs)
{
this->FoundInputsCache.Add(FallbackInput);
}
// Finally check the offset action for the final input to respond to.
if (this->OffsetMap.ComboInput)
{
this->FoundInputsCache.Add(this->OffsetMap.ComboInput);
}
}
return this->FoundInputsCache;
}
void UComboManagerComponent::FindAllUsedInputs_RecurseGraph(const UComboActionGraphNode *CurrentNode, TSet<const UComboInputAsset *> &FoundInputs)
{
for (const UComboActionGraphNode *NextNode : CurrentNode->ChildNodes)
{
// It should be safe to assume all of our nodes are action nodes. If at some point
// this becomes less reliable, this should be changed. But just for the sake of
// saving a bit of performance on start-up, we're doing this right now.
checkf(NextNode->GetClass() == UComboActionGraphNode_ActionNode::StaticClass(), TEXT("This graph contains non-action nodes. The cast in this function will fail."));
FoundInputs.Add(StaticCast<const UComboActionGraphNode_ActionNode *>(NextNode)->GetComboInput());
this->FindAllUsedInputs_RecurseGraph(NextNode, FoundInputs);
}
}
const UComboActionGraphNode *UComboManagerComponent::FindActiveNodeData(const UComboActionGraphNode *CurrentNode, const UComboInputAsset *Input, const EComboActionTriggerEvent TriggerEvent, const UComboAction *&ComboAction)
{
checkf(CurrentNode, TEXT("Attempting to find an active node from a null node."));
// Find a node that matches both the combo input and the trigger action.
const UComboActionGraphNode *NextNode = nullptr;
for (const UComboActionGraphNode *GraphNode : CurrentNode->ChildNodes)
for (const UComboActionGraphNode *GraphNode : CurrentNode->ChildrenNodes)
{
if (const UComboActionGraphNode_ActionNode *ActionNode = Cast<UComboActionGraphNode_ActionNode>(GraphNode))
{
if (ActionNode->GetComboInput() == Input && ActionNode->GetTriggerEvent() == EComboActionTriggerEvent::Activated)
{
// If we found the right node, only acknowledge it if it's enabled.
const UComboAction *CheckAction = ActionNode->GetComboAction();
if (ActionNode->bEnabled || this->ComboGraph->UnlockedActions.Contains(CheckAction))
// If we found the right node, only acknowledge it if it's enabled. Otherwise just skip it.
if (ActionNode->bEnabled)
{
ComboAction = CheckAction;
ComboAction = ActionNode->GetComboAction();
NextNode = ActionNode;
}
break;

View File

@ -12,14 +12,9 @@
DEFINE_LOG_CATEGORY(LogInputBufferComponent);
UInputBufferComponent::UInputBufferComponent()
void UInputBufferComponent::BeginPlay()
{
this->bWantsInitializeComponent = true;
}
void UInputBufferComponent::InitializeComponent()
{
Super::InitializeComponent();
Super::BeginPlay();
if (APlayerController *PlayerController = UGameplayStatics::GetPlayerController(this, 0))
{
@ -28,15 +23,14 @@ void UInputBufferComponent::InitializeComponent()
// Get the player character and try to connect to its combo manager.
this->OnNewComboInput.BindUObject(ComboManager, &UComboManagerComponent::HandleComboInput);
const TSet<const UComboInputAsset *> &ComboInputs = ComboManager->FindAllUsedInputs();
// Get all unique EnhancedInput actions bound to combo input actions.
const UInputBufferGlobalSettings *Settings = GetDefault<UInputBufferGlobalSettings>();
TSet<const UInputAction *> InputActionsToBind;
for (const UComboInputAsset *ComboInput : ComboInputs)
for (TSoftObjectPtr<const UComboInputAsset> ComboInput : Settings->ComboInputs)
{
if (ComboInput)
if (ComboInput.IsValid())
{
this->ComboInputList.Emplace(ComboInput);
this->ComboInputList.Emplace(ComboInput.Get());
for (const UInputAction *InputAction : ComboInput->ActionGroup)
{
InputActionsToBind.Add(InputAction);
@ -44,7 +38,7 @@ void UInputBufferComponent::InitializeComponent()
}
else
{
UE_LOG(LogInputBufferComponent, Verbose, TEXT("Invalid combo input found"));
UE_LOG(LogInputBufferComponent, Verbose, TEXT("Invalid combo action found in Combo Actions list in %s"), *Settings->GetClass()->GetName());
}
}
for (const UInputAction *InputAction : InputActionsToBind)
@ -59,47 +53,20 @@ void UInputBufferComponent::InitializeComponent()
void UInputBufferComponent::AddActionToBuffer(const FInputActionValue &Value, const class UInputAction *Action)
{
this->MultiPressActions.Add(Action);
this->MostRecentActions.Add(Action);
this->ExpiringActions.Remove(Action);
// Find any combo input that matches this action, plus buffered actions.
bool bComboInputFound = false;
for (TObjectPtr<const UComboInputAsset> ComboInput : this->ComboInputList)
{
if (ComboInput->MatchesInputActions(this->MultiPressActions))
if (ComboInput->MatchesInputActions(this->MostRecentActions))
{
this->ActivateComboInput(ComboInput.Get());
bComboInputFound = true;
break;
}
}
// If we haven't found any matching inputs, check if anything was somehow unhandled.
// This can happen if, for example, a jump input can combine with an attack input to
// create a combo action, but jump by itself has no action on its own.
if (!bComboInputFound)
{
if (!this->UnhandledActions.IsEmpty())
{
TSet<const UInputAction*> HandledActions = this->MultiPressActions;
for (const UInputAction *UnhandledAction : this->UnhandledActions)
{
HandledActions.Remove(UnhandledAction);
}
for (TObjectPtr<const UComboInputAsset> ComboInput : this->ComboInputList)
{
if (ComboInput->MatchesInputActions(HandledActions))
{
this->ActivateComboInput(ComboInput);
bComboInputFound = true;
break;
}
}
}
this->UnhandledActions.Add(Action);
}
const UInputBufferGlobalSettings *Settings = GetDefault<UInputBufferGlobalSettings>();
this->GetWorld()->GetTimerManager().SetTimer(this->MultiPressTimerHandle, this, &UInputBufferComponent::ClearMultiPresses, Settings->MultiPressTimerLength);
}
@ -107,14 +74,13 @@ void UInputBufferComponent::ClearMultiPresses()
{
#if WITH_EDITOR
TArray<FString> ActionNames;
for (const UInputAction *Action : this->MultiPressActions)
for (const UInputAction *Action : this->MostRecentActions)
{
ActionNames.Add(Action->GetName());
}
UE_LOG(LogInputBufferComponent, Verbose, TEXT("Multi-press buffer cleared (%s)"), *FString::Join(ActionNames, TEXT(" | ")));
#endif
this->MultiPressActions.Empty();
this->UnhandledActions.Empty();
this->MostRecentActions.Empty();
}
void UInputBufferComponent::ActivateComboInput(const UComboInputAsset *ComboInput)

View File

@ -15,12 +15,11 @@ UComboActionGraphNode::UComboActionGraphNode()
{
this->NodeGUID = FGuid::NewGuid();
this->bEnabled = true;
#if WITH_EDITORONLY_DATA
this->CompatibleGraphType = UComboActionGraph::StaticClass();
this->BackgroundColor = FLinearColor::Black;
this->bEnabled = true;
this->bAllowInputNodes = true;
this->bAllowOutputNodes = true;
@ -38,11 +37,11 @@ UComboActionGraphNode::UComboActionGraphNode()
void UComboActionGraphNode::SetNewWorld(UWorld *NewWorld)
{
if (NewWorld)
{
if (!NewWorld) return;
if (NewWorld == this->OwningWorld) return;
this->OwningWorld = NewWorld;
}
}
void UComboActionGraphNode::InitializeNode_Implementation(UWorld *InWorld)
{
@ -104,7 +103,7 @@ bool UComboActionGraphNode::CanCreateConnection(UComboActionGraphNode *Other, en
ErrorMessage = FText::FromString("Invalid Other Node!");
}
if (Other->GetMaxChildNodes() > -1 && Other->ChildNodes.Num() >= Other->GetMaxChildNodes())
if (Other->GetMaxChildNodes() > -1 && Other->ChildrenNodes.Num() >= Other->GetMaxChildNodes())
{
const FString TextReturn =
FString(Other->GetNodeTitle().ToString()).
@ -143,7 +142,7 @@ bool UComboActionGraphNode::ValidateNode(TArray<FText> &ValidationsMessages, con
{
bool bResult = true;
if (this->ParentNodes.Num() == 0 && this->ChildNodes.Num() == 0)
if (this->ParentNodes.Num() == 0 && this->ChildrenNodes.Num() == 0)
{
bResult = false;
@ -187,7 +186,7 @@ void UComboActionGraphNode::OnPasted()
this->NodeGUID = FGuid::NewGuid();
this->ParentNodes.Empty();
this->ChildNodes.Empty();
this->ChildrenNodes.Empty();
this->Edges.Empty();
}

View File

@ -19,7 +19,7 @@ UComboActionGraphNode_ActionNode::UComboActionGraphNode_ActionNode()
this->AllowedInputClasses.Add(UComboActionGraphNode_StartNode::StaticClass());
this->AllowedInputClasses.Add(UComboActionGraphNode_ActionNode::StaticClass());
this->MaxChildNodes = -1;
this->MaxChildrenNodes = -1;
}
void UComboActionGraphNode_ActionNode::PreProcessNode(const TScriptInterface<IComboActionGraphManagerInterface> &Manager)

View File

@ -45,7 +45,7 @@ bool UComboActionGraphNode_ActionNodeBase::ValidateNodeRuntime_Implementation()
return false;
}
if (this->MaxChildNodes > -1 && this->ChildNodes.Num() > this->MaxChildNodes)
if (this->MaxChildrenNodes > -1 && this->ChildrenNodes.Num() > this->MaxChildrenNodes)
{
return false;
}
@ -113,7 +113,7 @@ bool UComboActionGraphNode_ActionNodeBase::ValidateNode(TArray<FText> &Validatio
ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
}
if (this->MaxChildNodes > -1 && this->ChildNodes.Num() > this->MaxChildNodes)
if (this->MaxChildrenNodes > -1 && this->ChildrenNodes.Num() > this->MaxChildrenNodes)
{
const FString RichTextReturn = FString("* ")
.Append("<RichTextBlock.Bold>")
@ -121,12 +121,12 @@ bool UComboActionGraphNode_ActionNodeBase::ValidateNode(TArray<FText> &Validatio
.Append("</>")
.Append(": Has more than ")
.Append("<RichTextBlock.Bold>")
.Append(FString::FromInt(this->MaxChildNodes))
.Append(FString::FromInt(this->MaxChildrenNodes))
.Append("</>")
.Append(" child nodes!");
const FString TextReturn = FString(this->NodeTitle.ToString())
.Append(": Has more than ").Append(FString::FromInt(this->MaxChildNodes)).Append(" child nodes!");
.Append(": Has more than ").Append(FString::FromInt(this->MaxChildrenNodes)).Append(" child nodes!");
ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
}
@ -151,8 +151,7 @@ void UComboActionGraphNode_ActionNodeBase::PostEditChangeProperty(FPropertyChang
}
}
#if WITH_EDITOR
FLinearColor UComboActionGraphNode_ActionNodeBase::GetBackgroundColour() const
FLinearColor UComboActionGraphNode_ActionNodeBase::GetBackgroundColor() const
{
if (this->ComboAction && this->ComboAction->NodeColor != FLinearColor())
{
@ -162,9 +161,8 @@ FLinearColor UComboActionGraphNode_ActionNodeBase::GetBackgroundColour() const
{
return this->ComboInput->NodeColor;
}
return Super::GetBackgroundColour();
return Super::GetBackgroundColor();
}
#endif
FText UComboActionGraphNode_ActionNodeBase::GetDescription_Implementation() const
{

View File

@ -23,7 +23,7 @@ UComboActionGraphNode_StartNode::UComboActionGraphNode_StartNode()
this->NodeTooltipText = LOCTEXT("ComboActionGraphNode_CompleteTooltip", "* This Node will be added to the graph automatically.\n* This Node cannot be created manually.\n* This Node cannot be deleted.\n* Does not implement any logic.");
#endif
this->MaxChildNodes = -1;
this->MaxChildrenNodes = -1;
}
#if WITH_EDITOR
@ -37,7 +37,7 @@ bool UComboActionGraphNode_StartNode::ValidateNode(TArray<FText>& ValidationsMes
{
bool bResult = Super::ValidateNode(ValidationsMessages, RichFormat);
if (this->ChildNodes.Num() == 0)
if (ChildrenNodes.Num() == 0)
{
bResult = false;

View File

@ -43,17 +43,17 @@ public:
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
class UComboActionGraphNode *StartNode = nullptr;
/**
* The class of the action node represented by this instance.
* The class of the dialogue node represented by this instance.
*/
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
TSubclassOf<UComboActionGraphNode> NodeType;
/**
* The class of the action edge represented by this instance.
* The class of the dialogue edge represented by this instance.
*/
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
TSubclassOf<UComboActionGraphEdge> EdgeType;
/**
* An array of root nodes in the action graph. These are the nodes that do not have any incoming connections.
* An array of root nodes in the dialogue graph. These are the nodes that do not have any incoming connections.
*/
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
TArray<UComboActionGraphNode*> RootNodes;
@ -62,13 +62,6 @@ public:
*/
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
TArray<UComboActionGraphNode*> AllNodes;
/**
* Set containing actions to be unlocked if their associated nodes are currently locked.
*/
UPROPERTY(BlueprintReadWrite, Category="Combo Input|Action")
TSet<const class UComboAction*> UnlockedActions;
// Flag indicating whether an edge is enabled
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
bool bEdgeEnabled;
@ -95,12 +88,18 @@ public:
UFUNCTION(BlueprintCallable, Category="Combo Input|Action")
TArray<UComboActionGraphNode*> GetRootNodes() const { return this->RootNodes; }
/**
* Returns the first node in the graph.
* Returns the root nodes of the dialogue graph.
*
* @return The start node of this graph.
* @return An array of all root nodes.
*/
UFUNCTION(BlueprintCallable, Category="Combo Input|Action")
UComboActionGraphNode *GetStartNode() const { return this->StartNode; }
/**
* Determines whether the dialogue graph can be started.
*
* @return true if the graph can be started, false otherwise.
*/
bool CanStartDialogueGraph() const;
public:
void CreateGraph();
@ -116,7 +115,7 @@ public:
public:
UPROPERTY()
TObjectPtr<class UEdGraph> EdGraph;
class UEdGraph *EdGraph;
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action|Editor")
bool bCanRenameNode;

View File

@ -42,10 +42,8 @@ class COMBOINPUT_API UComboManagerComponent : public UActorComponent
public:
UComboManagerComponent();
virtual void InitializeComponent() override;
UFUNCTION(BlueprintCallable)
void SetComboGraph(const class UComboActionGraph *Graph);
virtual void BeginPlay() override;
UFUNCTION(BlueprintCallable)
void HandleComboInput(const class UComboInputAsset *Input, const EComboActionTriggerEvent &TriggerEvent);
@ -58,9 +56,6 @@ public:
this->ComboActionEventBindings.Emplace(Key.Key, MoveTemp(Delegate));
}
// Recursively search the graph for all inputs used by the graph.
TSet<const UComboInputAsset *> &FindAllUsedInputs();
protected:
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
TObjectPtr<const class UComboActionGraph> ComboGraph;
@ -92,7 +87,6 @@ private:
void ResetCombo();
const UComboActionGraphNode *FindActiveNodeData(const UComboActionGraphNode *CurrentNode, const UComboInputAsset *Input, const EComboActionTriggerEvent TriggerEvent, const UComboAction *&ComboAction);
void FindAllUsedInputs_RecurseGraph(const UComboActionGraphNode *CurrentNode, TSet<const UComboInputAsset *> &FoundInputs);
void BroadcastDelegates(const class UComboAction *ComboAction, const EComboActionTriggerEvent &TriggerEvent);
@ -107,9 +101,6 @@ private:
TObjectPtr<class UInputBufferComponent> AttachedInputBuffer;
// Cache of combo inputs found in the current graph.
TSet<const UComboInputAsset *> FoundInputsCache;
FTimerHandle FinishTransitionTimer;
FTimerHandle DEBUG__ResetComboTimer;

View File

@ -21,8 +21,7 @@ class COMBOINPUT_API UInputBufferComponent : public UEnhancedInputComponent
GENERATED_BODY()
public:
UInputBufferComponent();
virtual void InitializeComponent() override;
virtual void BeginPlay() override;
UFUNCTION(BlueprintCallable)
void LockComboInput(const class UComboInputAsset *Input);
@ -53,8 +52,7 @@ private:
// A local backup of the global setting containing the list of combo inputs to respond to.
TSet<TObjectPtr<const UComboInputAsset>> ComboInputList;
TSet<const class UInputAction*> MultiPressActions;
TSet<const class UInputAction*> UnhandledActions;
TSet<const class UInputAction*> MostRecentActions;
TSet<const class UInputAction*> ExpiringActions;
FNewComboInput OnNewComboInput;

View File

@ -16,6 +16,12 @@ class COMBOINPUT_API UInputBufferGlobalSettings : public UDeveloperSettingsBacke
GENERATED_BODY()
public:
// List of possible combo inputs that can be taken. A combo input is selected from this list
// either if an action is made while the current combo is inactive, or when the previous
// action expires.
UPROPERTY(Config, BlueprintReadOnly, EditDefaultsOnly)
TSet<TSoftObjectPtr<const class UComboInputAsset>> ComboInputs;
// Length of time after releasing an input to keep the associated combo action buffered before clearing it.
UPROPERTY(Config, BlueprintReadOnly, EditDefaultsOnly, meta=(UIMin="0.0", UIMax="0.5", ClampMin="0.0", ClampMax="0.5"))
float InputReleaseExpirationTimerLength = 0.15f;

View File

@ -38,7 +38,7 @@ public:
* The array of child nodes of the current dialogue node.
*/
UPROPERTY(BlueprintReadOnly, Category="Private")
TArray<class UComboActionGraphNode *> ChildNodes;
TArray<class UComboActionGraphNode*> ChildrenNodes;
/**
* Map of edges connecting this Node in the Combo Action graph.
* The key of the map is the source node, and the value is the edge connecting it to its target node.
@ -94,7 +94,7 @@ public:
* Can be used to enforce a maximum number of connections for certain types of nodes.
*/
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category="Combo Input|Action")
int32 MaxChildNodes = -1;
int32 MaxChildrenNodes = -1;
/**
* The array of allowed input classes for this Dialogue Node.
@ -126,10 +126,10 @@ public:
* Returns how many Children Nodes this Node allows to have.
* -1 means no limits.
*
* @return Max child nodes
* @return MaxChildrenNodes
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
int32 GetMaxChildNodes() const { return this->MaxChildNodes; }
int32 GetMaxChildNodes() const { return MaxChildrenNodes; }
/**
@ -164,6 +164,23 @@ public:
class UComboActionGraph *GetGraph() const { return this->Graph; }
/**
* Gets children Nodes this one has,
* Might be empty
*
* @return Amount of children Nodes
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
FORCEINLINE TArray<UComboActionGraphNode*> GetChildrenNodes() const { return ChildrenNodes; }
/**
* Gets how many parent Nodes point to this one
* Might be empty
*
* @return Amount of how parent Nodes
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
FORCEINLINE TArray<UComboActionGraphNode*> GetParentNodes() const { return ParentNodes; }
/**
* Serves purpose of validating Node before Dialogue gets Started.
* Any broken Node results in non-starting Dialogue to avoid crashes.
@ -308,11 +325,11 @@ public:
virtual FString GetNodeDocumentationLink_Implementation() const;
/**
* Returns the background colour for this graph node.
* Returns the Background Colour for this graph node.
*
* @return The background colour for this node.
* @return The Background Colour for this node.
*/
virtual FLinearColor GetBackgroundColour() const { return this->BackgroundColor; }
virtual FLinearColor GetBackgroundColor() const { return this->BackgroundColor; }
FText GetInternalName() const { return this->NodeTypeName; }
// Allows setting up the Node Title

View File

@ -39,9 +39,9 @@ public:
virtual bool ValidateNodeRuntime_Implementation() const override;
#if WITH_EDITOR
virtual FLinearColor GetBackgroundColour() const override;
#endif
virtual FLinearColor GetBackgroundColor() const override;
public:
#if WITH_EDITORONLY_DATA

View File

@ -95,7 +95,7 @@ public:
virtual UEdGraphNode *PerformAction(class UEdGraph *ParentGraph, UEdGraphPin *FromPin, const FVector2D Location, bool bSelectNewNode = true) override;
virtual void AddReferencedObjects(FReferenceCollector &Collector) override;
TObjectPtr<class UEdComboActionGraphNode> NodeTemplate;
class UEdComboActionGraphNode *NodeTemplate;
};
USTRUCT()
@ -114,7 +114,7 @@ public:
virtual UEdGraphNode *PerformAction(class UEdGraph *ParentGraph, UEdGraphPin *FromPin, const FVector2D Location, bool bSelectNewNode = true) override;
virtual void AddReferencedObjects(FReferenceCollector &Collector) override;
TObjectPtr<class UEdComboActionGraphEdge> NodeTemplate;
class UEdComboActionGraphEdge *NodeTemplate;
};

View File

@ -234,6 +234,7 @@ FComboInputSlateStyle::FComboInputSlateStyle() : FSlateStyleSet("ComboInputEdito
this->Set("MDSStyleSet.Node.Icon.small", new IMAGE_BRUSH(TEXT("DialogueNodeIcon"), Icon12));
this->Set("MDSStyleSet.Icon.Close", new IMAGE_BRUSH(TEXT("CloseIcon"), Icon12));
this->Set("MDSStyleSet.Icon.SupportDiscord", new IMAGE_BRUSH(TEXT("DiscordIcon"), Icon12));
this->Set("MDSStyleSet.Icon.HeartIcon", new IMAGE_BRUSH(TEXT("HeartIcon"), Icon12));
this->Set("MDSStyleSet.Icon.UBIcon", new IMAGE_BRUSH(TEXT("UnrealBucketIcon"), Icon12));
this->Set("MDSStyleSet.Icon.MoneyIcon", new IMAGE_BRUSH(TEXT("MoneyIcon"), Icon12));

View File

@ -2,26 +2,28 @@
#include "AssetEditor_ComboActionGraph.h"
#include "ComboActionGraph.h"
#include "ComboActionGraphSchema.h"
#include "ComboInputEditor.h"
#include "EdGraphUtilities.h"
#include "GraphEditorActions.h"
#include "Framework/Commands/GenericCommands.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "HAL/PlatformApplicationMisc.h"
#include "EdGraphUtilities.h"
#include "ComboInputEditor.h"
#include "ComboActionGraph.h"
#include "Nodes/ComboActionGraphNode.h"
#include "Ed/EdComboActionGraph.h"
#include "Ed/EdComboActionGraphEdge.h"
#include "Ed/EdComboActionGraphNode.h"
#include "Ed/FAssetEditorToolbarComboActionGraph.h"
#include "Ed/FComboActionGraphEditorCommands.h"
#include "Framework/Commands/GenericCommands.h"
#include "HAL/PlatformApplicationMisc.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "ComboActionGraphSchema.h"
//#include "Helpers/ComboActionGraphHelpers.h"
//#include "Helpers/ComboActionSystemEditorBFC.h"
#include "Layout/AssetEditorTabs.h"
#include "Layout/ComboActionGraphLayoutStrategy.h"
#include "Layout/ComboActionForceDirectedSolveLayoutStrategy.h"
#include "Layout/ComboActionTreeSolveLayoutStrategy.h"
#include "Nodes/ComboActionGraphNode.h"
#include "Popups/ComboInputPopup_GraphValidation.h"
//#include "Popups/MDSPopup_GraphValidation.h"
#include "Search/ComboActionSearchUtils.h"
#include "Search/SComboActionSearch.h"
#include "Settings/ComboActionGraphEditorSettings.h"
@ -740,41 +742,35 @@ bool FAssetEditor_ComboActionGraph::CanPasteNodes() const
void FAssetEditor_ComboActionGraph::AutoArrange()
{
// For now, auto-arrange is broken. Just in case it can be activated by accident,
// show a popup saying as much if an auto-arrange is attempted.
TArray<FText> ValidationMessages;
ValidationMessages.Add(LOCTEXT("AssetEditor_ComboActionGraph_AutoArrangeDisabled", "Auto-arrange is currently broken."));
ComboInputPopup_GraphValidation::Open(ValidationMessages);
UEdComboActionGraph *EdGraph = Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph);
check(EdGraph != nullptr);
//UEdComboActionGraph *EdGraph = Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph);
//check(EdGraph != nullptr);
const FScopedTransaction Transaction(LOCTEXT("ComboActionGraphEditorAutoArrange", "Combo Action Graph Editor: Auto Arrange all Nodes"));
//const FScopedTransaction Transaction(LOCTEXT("ComboActionGraphEditorAutoArrange", "Combo Action Graph Editor: Auto Arrange all Nodes"));
EdGraph->Modify(true);
//EdGraph->Modify(true);
UComboActionGraphLayoutStrategy *LayoutStrategy = nullptr;
switch (this->ComboActionGraphEditorSettings->GetAutoLayoutStrategy())
{
case EComboActionAutoLayoutStrategyType::Tree:
LayoutStrategy = NewObject<UComboActionGraphLayoutStrategy>(EdGraph, UComboActionTreeSolveLayoutStrategy::StaticClass());
break;
case EComboActionAutoLayoutStrategyType::ForceDirected:
LayoutStrategy = NewObject<UComboActionGraphLayoutStrategy>(EdGraph, UComboActionForceDirectedSolveLayoutStrategy::StaticClass());
break;
default:
break;
}
//UComboActionGraphLayoutStrategy *LayoutStrategy = nullptr;
//switch (this->ComboActionGraphEditorSettings->GetAutoLayoutStrategy())
//{
// case EComboActionAutoLayoutStrategyType::Tree:
// LayoutStrategy = NewObject<UComboActionGraphLayoutStrategy>(EdGraph, UComboActionTreeSolveLayoutStrategy::StaticClass());
// break;
// case EComboActionAutoLayoutStrategyType::ForceDirected:
// LayoutStrategy = NewObject<UComboActionGraphLayoutStrategy>(EdGraph, UComboActionForceDirectedSolveLayoutStrategy::StaticClass());
// break;
// default:
// break;
//}
//if (LayoutStrategy != nullptr)
//{
// LayoutStrategy->Layout(EdGraph);
// LayoutStrategy->ConditionalBeginDestroy();
//}
//else
//{
// UE_LOG(LogAssetEditorComboActionGraph, Error, TEXT("[AutoArrange] LayoutStrategy is null."));
//}
if (LayoutStrategy != nullptr)
{
LayoutStrategy->Layout(EdGraph);
LayoutStrategy->ConditionalBeginDestroy();
}
else
{
UE_LOG(LogAssetEditorComboActionGraph, Error, TEXT("[AutoArrange] LayoutStrategy is null."));
}
}
bool FAssetEditor_ComboActionGraph::CanAutoArrange() const
@ -802,12 +798,12 @@ void FAssetEditor_ComboActionGraph::ValidateGraph()
TArray<FText> ValidationMessages;
if (ComboActionGraph->ValidateGraph(ValidationMessages, true) == false)
{
this->ValidationWindow = ComboInputPopup_GraphValidation::Open(ValidationMessages);
//ValidationWindow = MDSPopup_GraphValidation::Open(ValidationMessages);
}
else
{
ValidationMessages.Empty();
this->ValidationWindow = ComboInputPopup_GraphValidation::Open(ValidationMessages);
//ValidationWindow = MDSPopup_GraphValidation::Open(ValidationMessages);
}
}

View File

@ -146,7 +146,7 @@ private:
class UComboActionGraphEditorSettings *ComboActionGraphEditorSettings;
TObjectPtr<class UComboActionGraph> EditingGraph;
class UComboActionGraph *EditingGraph;
//Toolbar
TSharedPtr<FAssetEditorToolbarComboActionGraph> ToolbarBuilder;

View File

@ -63,7 +63,7 @@ void UEdComboActionGraph::RebuildComboActionGraph()
if (ChildNode != nullptr)
{
ComboActionGraphNode->ChildNodes.Add(ChildNode);
ComboActionGraphNode->ChildrenNodes.Add(ChildNode);
ChildNode->ParentNodes.Add(ComboActionGraphNode);
}
@ -168,7 +168,7 @@ void UEdComboActionGraph::Clear()
{
UComboActionGraphNode *MounteaDialogueGraphNode = EdNode->ComboActionGraphNode;
MounteaDialogueGraphNode->ParentNodes.Reset();
MounteaDialogueGraphNode->ChildNodes.Reset();
MounteaDialogueGraphNode->ChildrenNodes.Reset();
MounteaDialogueGraphNode->Edges.Reset();
}
}
@ -194,12 +194,12 @@ void UEdComboActionGraph::SortNodes(UComboActionGraphNode *RootNode)
return EdNode_LNode->NodePosX < EdNode_RNode->NodePosX;
};
Node->ChildNodes.Sort(Comp);
Node->ChildrenNodes.Sort(Comp);
Node->ParentNodes.Sort(Comp);
for (int j = 0; j < Node->ChildNodes.Num(); ++j)
for (int j = 0; j < Node->ChildrenNodes.Num(); ++j)
{
NextLevelNodes.Add(Node->ChildNodes[j]);
NextLevelNodes.Add(Node->ChildrenNodes[j]);
}
}

View File

@ -82,6 +82,11 @@ void UEdComboActionGraphNode::AutowireNewNode(UEdGraphPin* FromPin)
}
}
FLinearColor UEdComboActionGraphNode::GetBackgroundColor() const
{
return this->ComboActionGraphNode ? this->ComboActionGraphNode->GetBackgroundColor() : FLinearColor::Black;
}
UEdGraphPin* UEdComboActionGraphNode::GetInputPin() const
{
return Pins[0];
@ -146,19 +151,12 @@ FText UEdComboActionGraphNode::GetTooltipText() const
return NSLOCTEXT("UEdComboActionGraphNode", "DefaultToolTip", "Combo Action Node");
}
#if WITH_EDITOR
FLinearColor UEdComboActionGraphNode::GetBackgroundColor() const
{
return this->ComboActionGraphNode ? this->ComboActionGraphNode->GetBackgroundColour() : FLinearColor::Black;
}
FSlateIcon UEdComboActionGraphNode::GetIconAndTint(FLinearColor& OutColor) const
{
static const FSlateIcon Icon = FSlateIcon(FComboInputSlateStyle::GetAppStyleSetName(), "MDSStyleSet.Node.Icon.small");
OutColor = this->ComboActionGraphNode->GetBackgroundColour();
OutColor = this->ComboActionGraphNode->GetBackgroundColor();
return Icon;
}
#endif
void UEdComboActionGraphNode::PostEditUndo()
{

View File

@ -31,6 +31,7 @@ public:
virtual void PrepareForCopying() override;
virtual void AutowireNewNode(UEdGraphPin *FromPin) override;
virtual FLinearColor GetBackgroundColor() const;
virtual UEdGraphPin *GetInputPin() const;
virtual UEdGraphPin *GetOutputPin() const;
@ -40,13 +41,11 @@ public:
virtual bool CanUserPasteNodes() const;
virtual FText GetTooltipText() const override;
virtual FSlateIcon GetIconAndTint(FLinearColor &OutColor) const override;
#if WITH_EDITOR
virtual void PostEditUndo() override;
virtual void PostEditChangeProperty(FPropertyChangedEvent &PropertyChangedEvent) override;
virtual FLinearColor GetBackgroundColor() const;
virtual FSlateIcon GetIconAndTint(FLinearColor &OutColor) const override;
#endif
UPROPERTY(VisibleAnywhere, Instanced, Category="Combo Action Graph")

View File

@ -113,11 +113,11 @@ FBox2D UComboActionForceDirectedSolveLayoutStrategy::LayoutOneTree(UComboActionG
UEdComboActionGraphNode *EdNode_ParentNode = this->EdGraph->NodeMap[Node];
for (int32 j = 0; j < Node->ChildNodes.Num(); j++)
for (int32 j = 0; j < Node->ChildrenNodes.Num(); j++)
{
NextLevelNodes.Add(Node->ChildNodes[j]);
NextLevelNodes.Add(Node->ChildrenNodes[j]);
UEdComboActionGraphNode *EdNode_ChildNode = this->EdGraph->NodeMap[Node->ChildNodes[j]];
UEdComboActionGraphNode *EdNode_ChildNode = this->EdGraph->NodeMap[Node->ChildrenNodes[j]];
Diff.X = EdNode_ChildNode->NodePosX - EdNode_ParentNode->NodePosY;
Diff.Y = EdNode_ChildNode->NodePosY - EdNode_ParentNode->NodePosY;

View File

@ -52,7 +52,7 @@ FBox2D UComboActionGraphLayoutStrategy::GetActualBounds(UComboActionGraphNode *R
Rtn += GetNodeBound(this->EdGraph->NodeMap[Node]);
for (UComboActionGraphNode *ChildNode : Node->ChildNodes)
for (UComboActionGraphNode *ChildNode : Node->ChildrenNodes)
{
NextLevelNodes.Add(ChildNode);
}
@ -82,7 +82,7 @@ void UComboActionGraphLayoutStrategy::RandomLayoutOneTree(UComboActionGraphNode
EdNode_Node->NodePosX = UKismetMathLibrary::RandomFloatInRange(Bound.Min.X, Bound.Max.X);
EdNode_Node->NodePosY = UKismetMathLibrary::RandomFloatInRange(Bound.Min.Y, Bound.Max.Y);
for (UComboActionGraphNode *ChildNode : Node->ChildNodes)
for (UComboActionGraphNode *ChildNode : Node->ChildrenNodes)
{
NextLevelNodes.Add(ChildNode);
}

View File

@ -66,13 +66,13 @@ void UComboActionTreeSolveLayoutStrategy::InitPass(UComboActionGraphNode *RootNo
UEdComboActionGraphNode *EdNode_RootNode = this->EdGraph->NodeMap[RootNode];
FVector2D ChildAnchor(FVector2D(0.0f, this->GetNodeHeight(EdNode_RootNode) + this->OptimalDistance + Anchor.Y));
for (int32 i = 0; i < RootNode->ChildNodes.Num(); i++)
for (int32 i = 0; i < RootNode->ChildrenNodes.Num(); i++)
{
UComboActionGraphNode *Child = RootNode->ChildNodes[i];
UComboActionGraphNode *Child = RootNode->ChildrenNodes[i];
UEdComboActionGraphNode *EdNode_ChildNode = this->EdGraph->NodeMap[Child];
if (i > 0)
{
UComboActionGraphNode *PreChild = RootNode->ChildNodes[i - 1];
UComboActionGraphNode *PreChild = RootNode->ChildrenNodes[i - 1];
UEdComboActionGraphNode *EdNode_PreChildNode = this->EdGraph->NodeMap[PreChild];
ChildAnchor.X += this->OptimalDistance + this->GetNodeWidth(EdNode_PreChildNode) / 2;
}
@ -83,7 +83,7 @@ void UComboActionTreeSolveLayoutStrategy::InitPass(UComboActionGraphNode *RootNo
float NodeWidth = this->GetNodeWidth(EdNode_RootNode);
EdNode_RootNode->NodePosY = Anchor.Y;
if (RootNode->ChildNodes.Num() == 0)
if (RootNode->ChildrenNodes.Num() == 0)
{
EdNode_RootNode->NodePosX = Anchor.X - NodeWidth / 2;
}
@ -96,9 +96,9 @@ void UComboActionTreeSolveLayoutStrategy::InitPass(UComboActionGraphNode *RootNo
bool UComboActionTreeSolveLayoutStrategy::ResolveConflictPass(UComboActionGraphNode *Node)
{
bool HasConflict = false;
for (int32 i = 0; i < Node->ChildNodes.Num(); ++i)
for (int32 i = 0; i < Node->ChildrenNodes.Num(); ++i)
{
UComboActionGraphNode *Child = Node->ChildNodes[i];
UComboActionGraphNode *Child = Node->ChildrenNodes[i];
if (this->ResolveConflictPass(Child))
{
HasConflict = true;
@ -107,7 +107,7 @@ bool UComboActionTreeSolveLayoutStrategy::ResolveConflictPass(UComboActionGraphN
for (const UComboActionGraphNode *ParentNode : Node->ParentNodes)
{
for (UComboActionGraphNode *LeftSibling : ParentNode->ChildNodes)
for (UComboActionGraphNode *LeftSibling : ParentNode->ChildrenNodes)
{
if (LeftSibling == Node)
{
@ -183,7 +183,7 @@ void UComboActionTreeSolveLayoutStrategy::GetLeftContour(UComboActionGraphNode *
Contour[Level] = EdNode_Node;
}
for (UComboActionGraphNode *Child : RootNode->ChildNodes)
for (UComboActionGraphNode *Child : RootNode->ChildrenNodes)
{
this->GetLeftContour(Child, Level + 1, Contour);
}
@ -201,7 +201,7 @@ void UComboActionTreeSolveLayoutStrategy::GetRightContour(UComboActionGraphNode
Contour[Level] = EdNode_Node;
}
for (UComboActionGraphNode *Child : RootNode->ChildNodes)
for (UComboActionGraphNode *Child : RootNode->ChildrenNodes)
{
this->GetRightContour(Child, Level + 1, Contour);
}
@ -213,7 +213,7 @@ void UComboActionTreeSolveLayoutStrategy::ShiftSubTree(UComboActionGraphNode *Ro
EdNode_Node->NodePosX += Offset.X;
EdNode_Node->NodePosY += Offset.Y;
for (UComboActionGraphNode *Child : RootNode->ChildNodes)
for (UComboActionGraphNode *Child : RootNode->ChildrenNodes)
{
if (Child->ParentNodes[0] == RootNode)
{
@ -225,17 +225,17 @@ void UComboActionTreeSolveLayoutStrategy::ShiftSubTree(UComboActionGraphNode *Ro
void UComboActionTreeSolveLayoutStrategy::UpdateParentNodePosition(UComboActionGraphNode *RootNode)
{
UEdComboActionGraphNode *EdNode_ParentNode = this->EdGraph->NodeMap[RootNode];
if (RootNode->ChildNodes.Num() % 2 == 0)
if (RootNode->ChildrenNodes.Num() % 2 == 0)
{
UEdComboActionGraphNode *FirstChild = this->EdGraph->NodeMap[RootNode->ChildNodes[0]];
UEdComboActionGraphNode *LastChild = this->EdGraph->NodeMap[RootNode->ChildNodes.Last()];
UEdComboActionGraphNode *FirstChild = this->EdGraph->NodeMap[RootNode->ChildrenNodes[0]];
UEdComboActionGraphNode *LastChild = this->EdGraph->NodeMap[RootNode->ChildrenNodes.Last()];
float LeftBound = FirstChild->NodePosX;
float RightBound = LastChild->NodePosX + this->GetNodeWidth(LastChild);
EdNode_ParentNode->NodePosX = (LeftBound + RightBound) / 2 - this->GetNodeWidth(EdNode_ParentNode) / 2;
}
else
{
UEdComboActionGraphNode *MidChild = this->EdGraph->NodeMap[RootNode->ChildNodes[RootNode->ChildNodes.Num() / 2]];
UEdComboActionGraphNode *MidChild = this->EdGraph->NodeMap[RootNode->ChildrenNodes[RootNode->ChildrenNodes.Num() / 2]];
EdNode_ParentNode->NodePosX = MidChild->NodePosX + this->GetNodeWidth(MidChild) / 2 - this->GetNodeWidth(EdNode_ParentNode) / 2;
}
}

View File

@ -1,147 +0,0 @@
#include "Popups/ComboInputPopup_GraphValidation.h"
#include "ComboInputEditor.h"
#include "Helpers/ComboActionGraphColors.h"
#include "Interfaces/IPluginManager.h"
#include "Settings/ComboActionGraphEditorSettings.h"
#include "Widgets/Layout/SScrollBox.h"
#include "Widgets/Text/SRichTextBlock.h"
#define LOCTEXT_NAMESPACE "ComboInputPopup_GraphValidation"
void ComboInputPopup_GraphValidation::OnBrowserLinkClicked(const FSlateHyperlinkRun::FMetadata &Metadata)
{
const FString *URL = Metadata.Find(TEXT("href"));
if (URL)
{
FPlatformProcess::LaunchURL(**URL, nullptr, nullptr);
}
}
TSharedPtr<SWindow> ComboInputPopup_GraphValidation::Open(const TArray<FText> ValidationMessages)
{
if (!FSlateApplication::Get().CanDisplayWindows())
{
return nullptr;
}
const FComboInputEditorModule &Module = FModuleManager::GetModuleChecked<FComboInputEditorModule>("ComboInputEditor");
const TSharedPtr<FSlateStyleSet> &EditorStyle = Module.Get().GetComboInputEditorStyleSet();
const TSharedRef<SBorder> WindowContent = SNew(SBorder)
.BorderImage(EditorStyle->GetBrush("MDSStyleSet.Node.TextSoftEdges"))
.BorderBackgroundColor
(
ComboActionGraphColors::ValidationGraph::DarkTheme
)
.Padding(FMargin(8.0f, 8.0f));
TSharedPtr<SWindow> Window = SNew(SWindow)
.AutoCenter(EAutoCenter::PreferredWorkArea)
.SupportsMaximize(false)
.SupportsMinimize(false)
.SizingRule(ESizingRule::FixedSize)
.ClientSize(FVector2D(650, 750))
.Title(FText::FromString("Combo Action Graph Validation"))
.IsTopmostWindow(true)
[
WindowContent
];
const FSlateFontInfo Heading1Font = FCoreStyle::GetDefaultFontStyle("Bold", 24);
const FSlateFontInfo Heading2Font = FCoreStyle::GetDefaultFontStyle("Bold", 18);
const FSlateFontInfo NormalFont = FCoreStyle::GetDefaultFontStyle("Regular", 12);
const TSharedRef<SScrollBox> ListOfMessages = SNew(SScrollBox);
for (auto Itr : ValidationMessages)
{
ListOfMessages->AddSlot()
[
SNew(SBox)
.Padding(FMargin(0.f, 3.5f, 0.f, 3.5f))
[
SNew(SRichTextBlock)
.Text(Itr)
.TextStyle(FAppStyle::Get(), "NormalText")
.DecoratorStyleSet(&FAppStyle::Get())
.AutoWrapText(true)
]
];
}
if (ValidationMessages.Num() == 0)
{
ListOfMessages->AddSlot()
[
SNew(STextBlock)
.Text(FText::FromString("There are no issues with your graph. You can close this window."))
.TextStyle(FAppStyle::Get(), "NormalText")
.AutoWrapText(true)
];
}
const TSharedRef<SVerticalBox> InnerContent =
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.FillHeight(1.0)
.Padding(10)
[
SNew(SBorder)
.Padding(10)
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
[
ListOfMessages
]
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(10)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot().FillWidth(1.0f)
[
SNew(SButton)
.HAlign(HAlign_Center)
.OnClicked_Lambda([Window]()
{
Window->RequestDestroyWindow();
return FReply::Handled();
})
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Text(FText::FromString("Close window"))
]
+ SHorizontalBox::Slot()
[
SNew(SSpacer)
.Size(FVector2D(5, 0))
]
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(SImage)
.ColorAndOpacity(FLinearColor::Red)
.Image(EditorStyle->GetBrush("MDSStyleSet.Icon.Close"))
]
]
]
];
const int32 A = InnerContent.Get().GetAllChildren()->Num();
WindowContent->SetContent(InnerContent);
Window = FSlateApplication::Get().AddWindow(Window.ToSharedRef());
return Window;
}
#undef LOCTEXT_NAMESPACE

View File

@ -1,13 +0,0 @@
#pragma once
#include "Framework/Text/SlateHyperlinkRun.h"
class SScrollBox;
class ComboInputPopup_GraphValidation
{
public:
static TSharedPtr<SWindow> Open(const TArray<FText> ValidationMessages);
static void OnBrowserLinkClicked(const FSlateHyperlinkRun::FMetadata &Metadata);
};

View File

@ -95,6 +95,7 @@ private:
TArray<TSharedPtr<IAssetTypeActions>> CreatedAssetTypeActions;
TSharedPtr<class FSlateStyleSet> ComboInputEditorStyleSet;
TSharedPtr<class FSlateStyleSet> ComboActionGraphEditorStyleSet;
TSharedPtr<struct FGraphPanelNodeFactory> ComboActionGraphPanelNodeFactory;
TSharedPtr<class FAssetTypeActions_ComboActionGraph> ComboActionGraphAssetActions;
};