Trying to add a combo graph editor.
This commit is contained in:
parent
bf43acf0dc
commit
ea4dd54ec9
@ -44,6 +44,7 @@ public class ComboInput : ModuleRules
|
|||||||
"Core",
|
"Core",
|
||||||
"CoreUObject",
|
"CoreUObject",
|
||||||
"Engine",
|
"Engine",
|
||||||
|
"GameplayTags",
|
||||||
"Slate",
|
"Slate",
|
||||||
"SlateCore",
|
"SlateCore",
|
||||||
"DeveloperSettings",
|
"DeveloperSettings",
|
||||||
|
|||||||
315
Source/ComboInput/Private/ComboActionGraph.cpp
Normal file
315
Source/ComboInput/Private/ComboActionGraph.cpp
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "ComboActionGraph.h"
|
||||||
|
|
||||||
|
#include "Nodes/ComboActionGraphEdge.h"
|
||||||
|
#include "Nodes/ComboActionGraphNode.h"
|
||||||
|
#include "Nodes/ComboActionGraphNode_StartNode.h"
|
||||||
|
|
||||||
|
#define LOCTEXT_NAMESPACE "ComboActionGraph"
|
||||||
|
|
||||||
|
DEFINE_LOG_CATEGORY(LogComboActionGraph);
|
||||||
|
|
||||||
|
|
||||||
|
UComboActionGraph::UComboActionGraph()
|
||||||
|
{
|
||||||
|
this->NodeType = UComboActionGraph::StaticClass();
|
||||||
|
this->EdgeType = UComboActionGraph::StaticClass();
|
||||||
|
|
||||||
|
this->bEdgeEnabled = false;
|
||||||
|
this->GraphGUID = FGuid::NewGuid();
|
||||||
|
|
||||||
|
#if WITH_EDITORONLY_DATA
|
||||||
|
this->EdGraph = nullptr;
|
||||||
|
|
||||||
|
this->bCanRenameNode = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FComboActionDecorator> UComboActionGraph::GetGraphDecorators() const
|
||||||
|
{
|
||||||
|
TArray<FComboActionDecorator> TempReturn;
|
||||||
|
TArray<FComboActionDecorator> Return;
|
||||||
|
|
||||||
|
for (const FComboActionDecorator &Itr : this->GraphDecorators)
|
||||||
|
{
|
||||||
|
if (Itr.DecoratorType != nullptr)
|
||||||
|
{
|
||||||
|
TempReturn.AddUnique(Itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Cleanup duplicates
|
||||||
|
for (auto Itr : TempReturn)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Return = TempReturn;
|
||||||
|
return Return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FComboActionDecorator> UComboActionGraph::GetAllDecorators() const
|
||||||
|
{
|
||||||
|
TArray<FComboActionDecorator> TempReturn;
|
||||||
|
TArray<FComboActionDecorator> Return;
|
||||||
|
|
||||||
|
for (const UComboActionGraphNode *Itr : this->AllNodes)
|
||||||
|
{
|
||||||
|
if (Itr && Itr->GetNodeDecorators().Num() > 0)
|
||||||
|
{
|
||||||
|
TempReturn.Append(Itr->NodeDecorators);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TempReturn.Append(this->GetGraphDecorators());
|
||||||
|
|
||||||
|
return TempReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraph::CanStartDialogueGraph() const
|
||||||
|
{
|
||||||
|
bool bSatisfied = true;
|
||||||
|
|
||||||
|
if (this->AllNodes.Num() == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& Itr : this->AllNodes)
|
||||||
|
{
|
||||||
|
if (!Itr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Itr->ValidateNodeRuntime() == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const TArray<FComboActionDecorator> &Decorators = this->GetAllDecorators();
|
||||||
|
|
||||||
|
if (Decorators.Num() == 0)
|
||||||
|
{
|
||||||
|
return bSatisfied;
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FText> DecoratorValidations;
|
||||||
|
for (const FComboActionDecorator &Itr : Decorators)
|
||||||
|
{
|
||||||
|
if (Itr.ValidateDecorator(DecoratorValidations) == false) bSatisfied = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DecoratorValidations.Num() > 0)
|
||||||
|
{
|
||||||
|
for(auto Itr : DecoratorValidations)
|
||||||
|
{
|
||||||
|
UE_LOG(LogComboActionGraph, Error, TEXT("%s"), *Itr.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bSatisfied;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraph::CreateGraph()
|
||||||
|
{
|
||||||
|
#if WITH_EDITOR
|
||||||
|
// We already have existing Graph
|
||||||
|
if (this->EdGraph != nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We already have existing Start Node
|
||||||
|
if (this->StartNode != nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->StartNode = ConstructDialogueNode<UComboActionGraphNode_StartNode>();
|
||||||
|
if (this->StartNode != nullptr )
|
||||||
|
{
|
||||||
|
this->StartNode->Graph = this;
|
||||||
|
|
||||||
|
this->RootNodes.Add(this->StartNode);
|
||||||
|
this->AllNodes.Add(this->StartNode);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraph::ClearGraph()
|
||||||
|
{
|
||||||
|
for (UComboActionGraphNode *Node : this->AllNodes)
|
||||||
|
{
|
||||||
|
Node->ParentNodes.Empty();
|
||||||
|
Node->ChildrenNodes.Empty();
|
||||||
|
Node->Edges.Empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->AllNodes.Empty();
|
||||||
|
this->RootNodes.Empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraph::PostInitProperties()
|
||||||
|
{
|
||||||
|
UObject::PostInitProperties();
|
||||||
|
|
||||||
|
// Ignore these cases
|
||||||
|
if (this->HasAnyFlags(EObjectFlags::RF_ClassDefaultObject | EObjectFlags::RF_NeedLoad))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
this->CreateGraph();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
bool UComboActionGraph::ValidateGraph(TArray<FText>& ValidationErrors, bool RichTextFormat)
|
||||||
|
{
|
||||||
|
bool bReturnValue = true;
|
||||||
|
|
||||||
|
// GRAPH DECORATORS VALIDATION
|
||||||
|
{
|
||||||
|
TArray<UComboActionDecoratorBase*> UsedNodeDecorators;
|
||||||
|
for (int i = 0; i < this->GraphDecorators.Num(); i++)
|
||||||
|
{
|
||||||
|
const FComboActionDecorator &Decorator = this->GraphDecorators[i];
|
||||||
|
if (Decorator.DecoratorType)
|
||||||
|
{
|
||||||
|
UsedNodeDecorators.Add(Decorator.DecoratorType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const FString RichTextReturn =
|
||||||
|
FString("* ")
|
||||||
|
.Append( TEXT("<RichTextBlock.Bold>Dialogue Graph</>"))
|
||||||
|
.Append(": has ")
|
||||||
|
.Append(TEXT("<RichTextBlock.Bold>invalid</> Node Decorator at Index: "))
|
||||||
|
.Append(FString::FromInt(i))
|
||||||
|
.Append(".");
|
||||||
|
|
||||||
|
const FString TextReturn =
|
||||||
|
this->GetName()
|
||||||
|
.Append(": has ")
|
||||||
|
.Append(TEXT("INVALID Node Decorator at Index: "))
|
||||||
|
.Append(FString::FromInt(i))
|
||||||
|
.Append(".");
|
||||||
|
|
||||||
|
ValidationErrors.Add(FText::FromString(RichTextFormat ? RichTextReturn : TextReturn));
|
||||||
|
|
||||||
|
bReturnValue = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TMap<UClass*, int32> DuplicatedDecoratorsMap;
|
||||||
|
for (const auto& Itr : UsedNodeDecorators)
|
||||||
|
{
|
||||||
|
int32 ClassAppearance = 1;
|
||||||
|
for (const auto& Itr2 : UsedNodeDecorators)
|
||||||
|
{
|
||||||
|
if (Itr != Itr2 && Itr->GetClass() == Itr2->GetClass())
|
||||||
|
{
|
||||||
|
auto A = Itr->GetClass()->GetName();
|
||||||
|
ClassAppearance++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClassAppearance > 1 && DuplicatedDecoratorsMap.Contains(Itr->GetClass()) == false)
|
||||||
|
{
|
||||||
|
DuplicatedDecoratorsMap.Add(Itr->GetClass(), ClassAppearance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DuplicatedDecoratorsMap.Num() > 0)
|
||||||
|
{
|
||||||
|
for (const TTuple<UClass*, int32> &Itr : DuplicatedDecoratorsMap)
|
||||||
|
{
|
||||||
|
bReturnValue = false;
|
||||||
|
|
||||||
|
const FString RichTextReturn =
|
||||||
|
FString("* ")
|
||||||
|
.Append(TEXT("<RichTextBlock.Bold>Dialogue Graph</>"))
|
||||||
|
.Append(": has Node Decorator ")
|
||||||
|
.Append("<RichTextBlock.Bold>")
|
||||||
|
.Append(Itr.Key->GetName().LeftChop(2))
|
||||||
|
.Append("</> ")
|
||||||
|
.Append(FString::FromInt(Itr.Value))
|
||||||
|
.Append("x times! Please, avoid duplicates!");
|
||||||
|
|
||||||
|
const FString TextReturn =
|
||||||
|
FString(TEXT("Dialogue Graph: has Node Decorator "))
|
||||||
|
.Append( Itr.Key->GetName().LeftChop(2))
|
||||||
|
.Append(" ")
|
||||||
|
.Append(FString::FromInt(Itr.Value))
|
||||||
|
.Append("x times! Please, avoid duplicates!");
|
||||||
|
|
||||||
|
ValidationErrors.Add(FText::FromString(RichTextFormat ? RichTextReturn : TextReturn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GRAPH DECORATORS VALIDATION
|
||||||
|
for (const FComboActionDecorator &Itr : this->GraphDecorators)
|
||||||
|
{
|
||||||
|
TArray<FText> DecoratorErrors;
|
||||||
|
if (!Itr.ValidateDecorator(DecoratorErrors))
|
||||||
|
{
|
||||||
|
for (auto Error : DecoratorErrors)
|
||||||
|
{
|
||||||
|
const FString ErrorTextRich =
|
||||||
|
FString("* ")
|
||||||
|
.Append(TEXT("<RichTextBlock.Bold>Dialogue Graph</>: "))
|
||||||
|
.Append(FString(Error.ToString()));
|
||||||
|
|
||||||
|
const FString ErrorTextSimple =
|
||||||
|
this->GetName()
|
||||||
|
.Append(": ")
|
||||||
|
.Append(FString(Error.ToString()));
|
||||||
|
|
||||||
|
ValidationErrors.Add(FText::FromString(RichTextFormat ? ErrorTextRich : ErrorTextSimple));
|
||||||
|
|
||||||
|
bReturnValue = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->StartNode == nullptr)
|
||||||
|
{
|
||||||
|
const FString RichTextReturn =
|
||||||
|
FString("* ")
|
||||||
|
.Append(TEXT("<RichTextBlock.Bold>Dialogue Graph</>"))
|
||||||
|
.Append(": Has no Start Node!");
|
||||||
|
|
||||||
|
const FString TextReturn =
|
||||||
|
this->GetName()
|
||||||
|
.Append(": Has no Start Node!");
|
||||||
|
|
||||||
|
ValidationErrors.Add(FText::FromString(RichTextFormat ? RichTextReturn : TextReturn));
|
||||||
|
|
||||||
|
bReturnValue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UComboActionGraphNode *Itr : this->AllNodes)
|
||||||
|
{
|
||||||
|
if (Itr != nullptr && !Itr->ValidateNode(ValidationErrors, RichTextFormat))
|
||||||
|
{
|
||||||
|
bReturnValue = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bReturnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDataValidationResult UComboActionGraph::IsDataValid(TArray<FText>& ValidationErrors)
|
||||||
|
{
|
||||||
|
return this->ValidateGraph(ValidationErrors, false)
|
||||||
|
? EDataValidationResult::Valid
|
||||||
|
: EDataValidationResult::Invalid;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef LOCTEXT_NAMESPACE
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Data/ComboActionAdditionalData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
222
Source/ComboInput/Private/Data/ComboActionContext.cpp
Normal file
222
Source/ComboInput/Private/Data/ComboActionContext.cpp
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Data/ComboActionContext.h"
|
||||||
|
|
||||||
|
#include "Interfaces/ComboActionInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool UComboActionContext::IsValid() const
|
||||||
|
{
|
||||||
|
return ActiveNode != nullptr;// && DialogueParticipant.GetInterface() != nullptr && PlayerDialogueParticipant.GetInterface() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionContext::SetComboActionContext(UComboActionGraphNode *NewActiveNode, const TArray<UComboActionGraphNode*> NewAllowedChildNodes)
|
||||||
|
{
|
||||||
|
//DialogueParticipant = NewParticipant;
|
||||||
|
//ActiveNode = NewActiveNode;
|
||||||
|
//AllowedChildNodes = NewAllowedChildNodes;
|
||||||
|
|
||||||
|
//if (!DialogueParticipants.Contains(NewParticipant))
|
||||||
|
//{
|
||||||
|
// DialogueParticipants.Add(NewParticipant);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
//void UComboActionContext::UpdateDialogueParticipant(const TScriptInterface<IComboActionParticipantInterface> NewParticipant)
|
||||||
|
//{
|
||||||
|
// DialogueParticipant = NewParticipant;
|
||||||
|
//
|
||||||
|
// AddDialogueParticipant(NewParticipant);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateActiveDialogueNode(UComboActionGraphNode *NewActiveNode)
|
||||||
|
//{
|
||||||
|
// ActiveNode = NewActiveNode;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateAllowedChildrenNodes(const TArray<UComboActionGraphNode*> &NewNodes)
|
||||||
|
//{
|
||||||
|
// AllowedChildNodes = NewNodes;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateActiveDialogueRowDataIndex(const int32 NewIndex)
|
||||||
|
//{
|
||||||
|
// ActiveDialogueRowDataIndex = NewIndex;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateDialoguePlayerParticipant(const TScriptInterface<IComboActionParticipantInterface> NewParticipant)
|
||||||
|
//{
|
||||||
|
// PlayerDialogueParticipant = NewParticipant;
|
||||||
|
//
|
||||||
|
// AddDialogueParticipant(NewParticipant);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateActiveDialogueParticipant(const TScriptInterface<IComboActionParticipantInterface> NewParticipant)
|
||||||
|
//{
|
||||||
|
// if (NewParticipant != PlayerDialogueParticipant && NewParticipant != DialogueParticipant)
|
||||||
|
// {
|
||||||
|
// //TODO: Properly log this
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ActiveDialogueParticipant = NewParticipant;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::AddTraversedNode(const UComboActionGraphNode *TraversedNode)
|
||||||
|
//{
|
||||||
|
// if (!TraversedNode) return;
|
||||||
|
//
|
||||||
|
// // If we have already passed over this Node, then just increase the counter
|
||||||
|
// if (TraversedPath.Contains(TraversedNode->GetNodeGUID()))
|
||||||
|
// {
|
||||||
|
// TraversedPath[TraversedNode->GetNodeGUID()]++;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// TraversedPath.Add(TraversedNode->GetNodeGUID(), 1);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//bool UComboActionContext::AddDialogueParticipants(const TArray<TScriptInterface<IComboActionParticipantInterface>>& NewParticipants)
|
||||||
|
//{
|
||||||
|
// bool bSatisfied = true;
|
||||||
|
// for (const auto& Itr : NewParticipants)
|
||||||
|
// {
|
||||||
|
// const bool bTempSatisfied = AddDialogueParticipant(Itr);
|
||||||
|
// bSatisfied = bTempSatisfied ? bSatisfied : bTempSatisfied;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return bSatisfied;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//bool UComboActionContext::AddDialogueParticipant(const TScriptInterface<IComboActionParticipantInterface>& NewParticipant)
|
||||||
|
//{
|
||||||
|
// if (DialogueParticipants.Contains(NewParticipant))
|
||||||
|
// {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// DialogueParticipants.Add(NewParticipant);
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//bool UComboActionContext::RemoveDialogueParticipants(const TArray<TScriptInterface<IComboActionParticipantInterface>>& NewParticipants)
|
||||||
|
//{
|
||||||
|
// bool bSatisfied = true;
|
||||||
|
// for (const auto& Itr : NewParticipants)
|
||||||
|
// {
|
||||||
|
// const bool bTempSatisfied = RemoveDialogueParticipant(Itr);
|
||||||
|
// bSatisfied = bTempSatisfied ? bSatisfied : bTempSatisfied;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return bSatisfied;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//bool UComboActionContext::RemoveDialogueParticipant(const TScriptInterface<IComboActionParticipantInterface>& NewParticipant)
|
||||||
|
//{
|
||||||
|
// if (DialogueParticipants.Contains(NewParticipant))
|
||||||
|
// {
|
||||||
|
// DialogueParticipants.Remove(NewParticipant);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::ClearDialogueParticipants()
|
||||||
|
//{
|
||||||
|
// DialogueParticipants.Empty();
|
||||||
|
//}
|
||||||
|
|
||||||
|
void UComboActionContext::SetComboActionContextBP(UComboActionGraphNode *NewActiveNode,TArray<UComboActionGraphNode*> NewAllowedChildNodes)
|
||||||
|
{
|
||||||
|
//this->SetComboActionContext(NewParticipant, NewActiveNode, NewAllowedChildNodes);
|
||||||
|
|
||||||
|
ComboActionContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//void UComboActionContext::UpdateDialogueParticipantBP(const TScriptInterface<IComboActionParticipantInterface> NewParticipant)
|
||||||
|
//{
|
||||||
|
// UpdateDialogueParticipant(NewParticipant);
|
||||||
|
//
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateActiveDialogueNodeBP(UComboActionGraphNode *NewActiveNode)
|
||||||
|
//{
|
||||||
|
// UpdateActiveDialogueNode(NewActiveNode);
|
||||||
|
//
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateActiveDialogueRowBP(const FDialogueRow &NewActiveRow)
|
||||||
|
//{
|
||||||
|
// UpdateActiveDialogueRow(NewActiveRow);
|
||||||
|
//
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateActiveDialogueRowDataIndexBP(const int32 NewIndex)
|
||||||
|
//{
|
||||||
|
// UpdateActiveDialogueRowDataIndex(NewIndex);
|
||||||
|
//
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateDialoguePlayerParticipantBP(const TScriptInterface<IComboActionParticipantInterface> NewParticipant)
|
||||||
|
//{
|
||||||
|
// UpdateDialoguePlayerParticipant(NewParticipant);
|
||||||
|
//
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void UComboActionContext::UpdateActiveDialogueParticipantBP(const TScriptInterface<IComboActionParticipantInterface> NewParticipant)
|
||||||
|
//{
|
||||||
|
// UpdateActiveDialogueParticipant(NewParticipant);
|
||||||
|
//
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//bool UComboActionContext::AddDialogueParticipantBP(const TScriptInterface<IComboActionParticipantInterface> &NewParticipant)
|
||||||
|
//{
|
||||||
|
// if (AddDialogueParticipant(NewParticipant))
|
||||||
|
// {
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//bool UComboActionContext::RemoveDialogueParticipantBP(const TScriptInterface<IComboActionParticipantInterface> &NewParticipant)
|
||||||
|
//{
|
||||||
|
// if (RemoveDialogueParticipant(NewParticipant))
|
||||||
|
// {
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//bool UComboActionContext::AddDialogueParticipantsBP(const TArray<TScriptInterface<IComboActionParticipantInterface>> &NewParticipants)
|
||||||
|
//{
|
||||||
|
// if (AddDialogueParticipants(NewParticipants))
|
||||||
|
// {
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//bool UComboActionContext::RemoveDialogueParticipantsBP(const TArray<TScriptInterface<IComboActionParticipantInterface>> &NewParticipants)
|
||||||
|
//{
|
||||||
|
// if (RemoveDialogueParticipants(NewParticipants))
|
||||||
|
// {
|
||||||
|
// DialogueContextUpdatedFromBlueprint.Broadcast(this);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Decorators/ComboActionDecoratorBase.h"
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
#include "Editor.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DEFINE_LOG_CATEGORY(LogComboActionDecoratorBase);
|
||||||
|
|
||||||
|
#define LOCTEXT_NAMESPACE "ComboActionDecoratorBase"
|
||||||
|
|
||||||
|
|
||||||
|
bool UComboActionDecoratorBase::ValidateDecorator_Implementation(TArray<FText>& ValidationMessages)
|
||||||
|
{
|
||||||
|
bool bSatisfied = true;
|
||||||
|
const FText Name = FText::FromString(GetName());
|
||||||
|
|
||||||
|
// This is to ensure we are not throwing InvalidWorld errors in Editor with no Gameplay.
|
||||||
|
bool bIsEditorCall = false;
|
||||||
|
#if WITH_EDITOR
|
||||||
|
if (GEditor != nullptr)
|
||||||
|
{
|
||||||
|
bIsEditorCall = !GEditor->GetPlayInEditorSessionInfo().IsSet();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (GetOwningWorld() == nullptr && bIsEditorCall == false)
|
||||||
|
{
|
||||||
|
const FText TempText = FText::Format(LOCTEXT("ComboActionDecorator_Base_Validation_World", "[{0}]: No valid World!"), Name);
|
||||||
|
ValidationMessages.Add(TempText);
|
||||||
|
|
||||||
|
bSatisfied = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DecoratorState == EComboActionDecoratorState::Uninitialized && bIsEditorCall == false)
|
||||||
|
{
|
||||||
|
const FText TempText = FText::Format(LOCTEXT("ComboActionDecorator_Base_Validation_State", "[{0}]: Not Initialized properly!"), Name);
|
||||||
|
ValidationMessages.Add(TempText);
|
||||||
|
|
||||||
|
bSatisfied = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetOwner() == nullptr)
|
||||||
|
{
|
||||||
|
const FText TempText = FText::Format(LOCTEXT("ComboActionDecorator_Base_Validation_Owner", "[{0}]: No valid Owner!"), Name);
|
||||||
|
ValidationMessages.Add(TempText);
|
||||||
|
|
||||||
|
bSatisfied = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bSatisfied;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef LOCTEXT_NAMESPACE
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Interfaces/ComboActionGraphManagerInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Interfaces/ComboActionInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
6
Source/ComboInput/Private/Nodes/ComboActionGraphEdge.cpp
Normal file
6
Source/ComboInput/Private/Nodes/ComboActionGraphEdge.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Nodes/ComboActionGraphEdge.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
396
Source/ComboInput/Private/Nodes/ComboActionGraphNode.cpp
Normal file
396
Source/ComboInput/Private/Nodes/ComboActionGraphNode.cpp
Normal file
@ -0,0 +1,396 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Nodes/ComboActionGraphNode.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraph.h"
|
||||||
|
|
||||||
|
#include "Data/ComboActionContext.h"
|
||||||
|
#include "Decorators/ComboActionDecoratorBase.h"
|
||||||
|
#include "Interfaces/ComboActionGraphManagerInterface.h"
|
||||||
|
|
||||||
|
DEFINE_LOG_CATEGORY(LogComboActionGraphNode);
|
||||||
|
|
||||||
|
#define LOCTEXT_NAMESPACE "ComboActionGraphNode"
|
||||||
|
|
||||||
|
|
||||||
|
UComboActionGraphNode::UComboActionGraphNode()
|
||||||
|
{
|
||||||
|
NodeGUID = FGuid::NewGuid();
|
||||||
|
bInheritGraphDecorators = true;
|
||||||
|
|
||||||
|
#if WITH_EDITORONLY_DATA
|
||||||
|
CompatibleGraphType = UComboActionGraph::StaticClass();
|
||||||
|
|
||||||
|
BackgroundColor = FLinearColor::Black;
|
||||||
|
|
||||||
|
bAllowInputNodes = true;
|
||||||
|
bAllowOutputNodes = true;
|
||||||
|
|
||||||
|
bAllowCopy = true;
|
||||||
|
bAllowCut = true;
|
||||||
|
bAllowDelete = true;
|
||||||
|
bAllowPaste = true;
|
||||||
|
bAllowManualCreate = true;
|
||||||
|
|
||||||
|
NodeTypeName = LOCTEXT("ComboActionGraphNode_InternalName", "ComboActionGraphNode");
|
||||||
|
NodeTooltipText = LOCTEXT("ComboActionGraphNode_Tooltip", "Combo action graph base node. Child nodes provide more information.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bAutoStarts = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphNode::SetNewWorld(UWorld *NewWorld)
|
||||||
|
{
|
||||||
|
if (!NewWorld) return;
|
||||||
|
if (NewWorld == this->OwningWorld) return;
|
||||||
|
|
||||||
|
this->OwningWorld = NewWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphNode::InitializeNode_Implementation(UWorld *InWorld)
|
||||||
|
{
|
||||||
|
this->SetNewWorld(InWorld);
|
||||||
|
|
||||||
|
if (this->Graph)
|
||||||
|
{
|
||||||
|
this->SetNodeIndex(this->Graph->AllNodes.Find(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphNode::ProcessNode()
|
||||||
|
{
|
||||||
|
if (!this->GetWorld())
|
||||||
|
{
|
||||||
|
UE_LOG(LogComboActionGraphNode, Error, TEXT("[ProcessNode] Cannot find World!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->GetGraph())
|
||||||
|
{
|
||||||
|
UE_LOG(LogComboActionGraphNode, Error, TEXT("[ProcessNode] Invalid owning Graph!!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//UComboActionContext *Context = Manager->GetDialogueContext();
|
||||||
|
//if (!Context || !UComboActionSystemBFC::IsContextValid(Context))
|
||||||
|
//{
|
||||||
|
// Manager->GetDialogueFailedEventHandle().Broadcast(TEXT("[ProcessNode] Invalid Dialogue Context!!"));
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//UComboActionSystemBFC::ExecuteDecorators(this, Context);
|
||||||
|
//
|
||||||
|
//Manager->GetDialogueNodeStartedEventHandle().Broadcast(Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FComboActionDecorator> UComboActionGraphNode::GetNodeDecorators() const
|
||||||
|
{
|
||||||
|
TArray<FComboActionDecorator> TempReturn;
|
||||||
|
TArray<FComboActionDecorator> Return;
|
||||||
|
|
||||||
|
for (auto Itr : NodeDecorators)
|
||||||
|
{
|
||||||
|
if (Itr.DecoratorType != nullptr)
|
||||||
|
{
|
||||||
|
TempReturn.AddUnique(Itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Cleanup duplicates
|
||||||
|
for (auto Itr : TempReturn)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Return = TempReturn;
|
||||||
|
return Return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraphNode::CanStartNode() const
|
||||||
|
{
|
||||||
|
return this->EvaluateDecorators();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraphNode::EvaluateDecorators() const
|
||||||
|
{
|
||||||
|
if (this->GetGraph() == nullptr)
|
||||||
|
{
|
||||||
|
UE_LOG(LogComboActionGraphNode, Error, TEXT("[EvaluateDecorators] Graph is null (invalid)!"))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bSatisfied = true;
|
||||||
|
TArray<FComboActionDecorator> AllDecorators;
|
||||||
|
if (this->bInheritGraphDecorators)
|
||||||
|
{
|
||||||
|
// Add those Decorators rather than asking Graph to evaluate, because Nodes might introduce specific context
|
||||||
|
AllDecorators.Append(GetGraph()->GetGraphDecorators());
|
||||||
|
}
|
||||||
|
|
||||||
|
AllDecorators.Append(GetNodeDecorators());
|
||||||
|
|
||||||
|
if (AllDecorators.Num() == 0) return bSatisfied;
|
||||||
|
|
||||||
|
for (auto Itr : AllDecorators)
|
||||||
|
{
|
||||||
|
if (Itr.EvaluateDecorator() == false) bSatisfied = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bSatisfied;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphNode::SetNodeIndex(const int32 NewIndex)
|
||||||
|
{
|
||||||
|
check(NewIndex>INDEX_NONE);
|
||||||
|
this->NodeIndex = NewIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
|
||||||
|
FText UComboActionGraphNode::GetDescription_Implementation() const
|
||||||
|
{
|
||||||
|
return LOCTEXT("NodeDesc", "Mountea Dialogue Graph Node");
|
||||||
|
}
|
||||||
|
|
||||||
|
FText UComboActionGraphNode::GetNodeCategory_Implementation() const
|
||||||
|
{
|
||||||
|
return LOCTEXT("NodeCategory", "Mountea Dialogue Tree Node");
|
||||||
|
}
|
||||||
|
|
||||||
|
FString UComboActionGraphNode::GetNodeDocumentationLink_Implementation() const
|
||||||
|
{
|
||||||
|
return TEXT("A link to the documentation for this plugin will go here.");
|
||||||
|
}
|
||||||
|
|
||||||
|
FText UComboActionGraphNode::GetNodeTooltipText_Implementation() const
|
||||||
|
{
|
||||||
|
return FText::Format(LOCTEXT("ComboActionGraphNode_FinalTooltip", "{0}\n\n{1}"), this->GetDefaultTooltipBody(), this->NodeTooltipText);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraphNode::CanCreateConnection(UComboActionGraphNode *Other, enum EEdGraphPinDirection Direction, FText &ErrorMessage)
|
||||||
|
{
|
||||||
|
if (Other == nullptr)
|
||||||
|
{
|
||||||
|
ErrorMessage = FText::FromString("Invalid Other Node!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Other->GetMaxChildNodes() > -1 && Other->ChildrenNodes.Num() >= Other->GetMaxChildNodes())
|
||||||
|
{
|
||||||
|
const FString TextReturn =
|
||||||
|
FString(Other->GetNodeTitle().ToString()).
|
||||||
|
Append(": Cannot have more than ").Append(FString::FromInt(Other->GetMaxChildNodes())).Append(" Children Nodes!");
|
||||||
|
|
||||||
|
ErrorMessage = FText::FromString(TextReturn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Direction == EEdGraphPinDirection::EGPD_Output)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Fast checking for native classes
|
||||||
|
if ( AllowedInputClasses.Contains(Other->GetClass()) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slower iterative checking for child classes
|
||||||
|
for (auto Itr : AllowedInputClasses)
|
||||||
|
{
|
||||||
|
if (Other->GetClass()->IsChildOf(Itr))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorMessage = FText::FromString("Invalid Node Connection!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraphNode::ValidateNode(TArray<FText> &ValidationsMessages, const bool RichFormat)
|
||||||
|
{
|
||||||
|
bool bResult = true;
|
||||||
|
if (this->ParentNodes.Num() == 0 && this->ChildrenNodes.Num() == 0)
|
||||||
|
{
|
||||||
|
bResult = false;
|
||||||
|
|
||||||
|
const FString RichTextReturn =
|
||||||
|
FString("* ")
|
||||||
|
.Append("<RichTextBlock.Bold>")
|
||||||
|
.Append(this->NodeTitle.ToString())
|
||||||
|
.Append("</>")
|
||||||
|
.Append(": This Node has no Connections!");
|
||||||
|
|
||||||
|
const FString TextReturn =
|
||||||
|
FString(this->NodeTitle.ToString())
|
||||||
|
.Append(": This Node has no Connections!");
|
||||||
|
|
||||||
|
ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->bAllowInputNodes && this->ParentNodes.Num() == 0)
|
||||||
|
{
|
||||||
|
bResult = false;
|
||||||
|
|
||||||
|
const FString RichTextReturn =
|
||||||
|
FString("* ")
|
||||||
|
.Append("<RichTextBlock.Bold>")
|
||||||
|
.Append(this->NodeTitle.ToString())
|
||||||
|
.Append("</>")
|
||||||
|
.Append(": This Node requires Inputs, however, none are found!");
|
||||||
|
|
||||||
|
const FString TextReturn =
|
||||||
|
FString(this->NodeTitle.ToString())
|
||||||
|
.Append(": This Node requires Inputs, however, none are found!");
|
||||||
|
|
||||||
|
ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
}
|
||||||
|
|
||||||
|
// DECORATORS VALIDATION
|
||||||
|
{
|
||||||
|
TArray<UComboActionDecoratorBase*> UsedNodeDecorators;
|
||||||
|
for (int i = 0; i < this->NodeDecorators.Num(); i++)
|
||||||
|
{
|
||||||
|
if (this->NodeDecorators.IsValidIndex(i) && this->NodeDecorators[i].DecoratorType && !UsedNodeDecorators.Contains(this->NodeDecorators[i].DecoratorType))
|
||||||
|
{
|
||||||
|
UsedNodeDecorators.Add(NodeDecorators[i].DecoratorType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const FString RichTextReturn =
|
||||||
|
FString("* ")
|
||||||
|
.Append( TEXT("<RichTextBlock.Bold>"))
|
||||||
|
.Append(GetNodeTitle().ToString())
|
||||||
|
.Append(TEXT("</>"))
|
||||||
|
.Append(": has ")
|
||||||
|
.Append(TEXT("<RichTextBlock.Bold>invalid</> Node Decorator at Index: "))
|
||||||
|
.Append(FString::FromInt(i))
|
||||||
|
.Append(".");
|
||||||
|
|
||||||
|
FString TextReturn = FString(GetNodeTitle().ToString())
|
||||||
|
.Append(": has ")
|
||||||
|
.Append(TEXT("INVALID Node Decorator at Index: "))
|
||||||
|
.Append(FString::FromInt(i))
|
||||||
|
.Append(".");
|
||||||
|
|
||||||
|
ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
|
||||||
|
bResult = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TMap<UClass*, int32> DuplicatedDecoratorsMap;
|
||||||
|
for (const UComboActionDecoratorBase *Itr : UsedNodeDecorators)
|
||||||
|
{
|
||||||
|
int32 ClassAppearance = 1;
|
||||||
|
for (const UComboActionDecoratorBase *Itr2 : UsedNodeDecorators)
|
||||||
|
{
|
||||||
|
if (Itr != Itr2 && Itr->GetClass() == Itr2->GetClass())
|
||||||
|
{
|
||||||
|
auto A = Itr->GetClass()->GetName();
|
||||||
|
ClassAppearance++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClassAppearance > 1 && DuplicatedDecoratorsMap.Contains(Itr->GetClass()) == false)
|
||||||
|
{
|
||||||
|
DuplicatedDecoratorsMap.Add(Itr->GetClass(), ClassAppearance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DuplicatedDecoratorsMap.Num() > 0)
|
||||||
|
{
|
||||||
|
for (const TTuple<UClass*, int32> &Itr : DuplicatedDecoratorsMap)
|
||||||
|
{
|
||||||
|
bResult = false;
|
||||||
|
|
||||||
|
const FString RichTextReturn =
|
||||||
|
FString("* ")
|
||||||
|
.Append("<RichTextBlock.Bold>")
|
||||||
|
.Append(this->NodeTitle.ToString())
|
||||||
|
.Append("</>")
|
||||||
|
.Append(": has Node Decorator ")
|
||||||
|
.Append("<RichTextBlock.Bold>")
|
||||||
|
.Append(Itr.Key->GetName().LeftChop(2))
|
||||||
|
.Append("</> ")
|
||||||
|
.Append(FString::FromInt(Itr.Value))
|
||||||
|
.Append("x times! Please, avoid duplicates!");
|
||||||
|
|
||||||
|
const FString TextReturn =
|
||||||
|
FString(this->NodeTitle.ToString())
|
||||||
|
.Append(this->NodeTitle.ToString())
|
||||||
|
.Append(": has Node Decorator ")
|
||||||
|
.Append(Itr.Key->GetName().LeftChop(2))
|
||||||
|
.Append(" ")
|
||||||
|
.Append(FString::FromInt(Itr.Value))
|
||||||
|
.Append("x times! Please, avoid duplicates!");
|
||||||
|
|
||||||
|
ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const FComboActionDecorator &Itr : this->GetNodeDecorators())
|
||||||
|
{
|
||||||
|
TArray<FText> DecoratorErrors;
|
||||||
|
if (!Itr.ValidateDecorator(DecoratorErrors))
|
||||||
|
{
|
||||||
|
for (auto Error : DecoratorErrors)
|
||||||
|
{
|
||||||
|
const FString ErrorTextRich =
|
||||||
|
FString("* ")
|
||||||
|
.Append("<RichTextBlock.Bold>")
|
||||||
|
.Append(this->NodeTitle.ToString())
|
||||||
|
.Append("</>: ")
|
||||||
|
.Append(FString(Error.ToString()));
|
||||||
|
|
||||||
|
const FString ErrorTextSimple =
|
||||||
|
FString(this->GetClass()->GetDisplayNameText().ToString())
|
||||||
|
.Append(": ")
|
||||||
|
.Append(FString(Error.ToString()));
|
||||||
|
|
||||||
|
ValidationsMessages.Add(FText::FromString(RichFormat ? ErrorTextRich : ErrorTextSimple));
|
||||||
|
|
||||||
|
bResult = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphNode::OnPasted()
|
||||||
|
{
|
||||||
|
NodeGUID = FGuid::NewGuid();
|
||||||
|
|
||||||
|
ParentNodes.Empty();
|
||||||
|
ChildrenNodes.Empty();
|
||||||
|
Edges.Empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
FText UComboActionGraphNode::GetDefaultTooltipBody() const
|
||||||
|
{
|
||||||
|
const FText InheritsValue = this->bInheritGraphDecorators ? LOCTEXT("True","Yes") : LOCTEXT("False","No");
|
||||||
|
const FText Inherits = FText::Format(LOCTEXT("UComboActionGraphNode_InheritsTooltip", "Inherits Graph Decorators: {0}"), InheritsValue);
|
||||||
|
|
||||||
|
FText ImplementsNumber;
|
||||||
|
if (this->NodeDecorators.Num() == 0)
|
||||||
|
{
|
||||||
|
ImplementsNumber = LOCTEXT("None", "-");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImplementsNumber = FText::FromString(FString::FromInt(this->NodeDecorators.Num()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const FText Implements = FText::Format(LOCTEXT("UComboActionGraphNode_ImplementsTooltip", "Implements Decorators: {0}"), ImplementsNumber);
|
||||||
|
|
||||||
|
return FText::Format(LOCTEXT("UComboActionGraphNode_BaseTooltip", "{0}\n\n{1}\n{2}"), this->NodeTypeName, Inherits, Implements);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef LOCTEXT_NAMESPACE
|
||||||
@ -0,0 +1,268 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
|
||||||
|
#include "Nodes/ComboActionGraphNode_ActionNodeBase.h"
|
||||||
|
|
||||||
|
//#include "Helpers/ComboActionSystemBFC.h"
|
||||||
|
|
||||||
|
#define LOCTEXT_NAMESPACE "ComboActionGraphNode_ActionNodeBase"
|
||||||
|
|
||||||
|
|
||||||
|
UComboActionGraphNode_ActionNodeBase::UComboActionGraphNode_ActionNodeBase()
|
||||||
|
{
|
||||||
|
#if WITH_EDITORONLY_DATA
|
||||||
|
this->NodeTitle = LOCTEXT("ComboActionGraphNode_ActionNodeBaseTitle", "Action Node Base");
|
||||||
|
this->NodeTypeName = LOCTEXT("ComboActionGraphNode_ActionNodeBaseInternalTitle", "Action Node Base");
|
||||||
|
this->ContextMenuName = LOCTEXT("ComboActionGraphNode_ActionNodeBaseContextMenu", "Action Node");
|
||||||
|
this->BackgroundColor = FLinearColor(FColor::Orange);
|
||||||
|
|
||||||
|
this->NodeTooltipText = LOCTEXT("ComboActionGraphNode_BaseTooltip", "* Abstract class, should not appear in graph editor.\n* Enhances 'ComboActionGraphNode' Base class with action data.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
this->bAutoStarts = false;
|
||||||
|
this->bUseGameplayTags = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphNode_ActionNodeBase::ProcessNode()
|
||||||
|
{
|
||||||
|
//if (Manager)
|
||||||
|
//{
|
||||||
|
// if (UComboActionContext *Context = Manager->GetDialogueContext())
|
||||||
|
// {
|
||||||
|
// this->GetWorld()->GetTimerManager().ClearTimer(Manager->GetDialogueRowTimerHandle());
|
||||||
|
|
||||||
|
// const FDialogueRow DialogueRow = UComboActionSystemBFC::GetDialogueRow(Context->ActiveNode);
|
||||||
|
// if (UComboActionSystemBFC::IsDialogueRowValid(DialogueRow) && DialogueRow.DialogueRowData.Array().IsValidIndex(Context->GetActiveDialogueRowDataIndex()))
|
||||||
|
// {
|
||||||
|
// Context->UpdateActiveDialogueRow(DialogueRow);
|
||||||
|
// Context->UpdateActiveDialogueRowDataIndex(Context->ActiveDialogueRowDataIndex);
|
||||||
|
// Manager->GetDialogueContextUpdatedEventHande().Broadcast(Context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
Super::ProcessNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphNode_ActionNodeBase::PreProcessNode()
|
||||||
|
{
|
||||||
|
//if (bUseGameplayTags)
|
||||||
|
//{
|
||||||
|
// // Switch Participants based on Tags
|
||||||
|
// if (Manager.GetInterface())
|
||||||
|
// {
|
||||||
|
// if (const auto TempContext = Manager->GetDialogueContext())
|
||||||
|
// {
|
||||||
|
// const TScriptInterface<IComboActionParticipantInterface> BestMatchingParticipant = UComboActionSystemBFC::FindBestMatchingParticipant(Manager.GetObject(), TempContext);
|
||||||
|
//
|
||||||
|
// TempContext->UpdateActiveDialogueParticipant(BestMatchingParticipant);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
Super::PreProcessNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
UDataTable *UComboActionGraphNode_ActionNodeBase::GetDataTable() const
|
||||||
|
{
|
||||||
|
return DataTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraphNode_ActionNodeBase::ValidateNodeRuntime_Implementation() const
|
||||||
|
{
|
||||||
|
//if (DataTable == nullptr)
|
||||||
|
//{
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (RowName.IsNone())
|
||||||
|
//{
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (MaxChildrenNodes > -1 && ChildrenNodes.Num() > MaxChildrenNodes)
|
||||||
|
//{
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//const FString Context;
|
||||||
|
//const FDialogueRow* SelectedRow = DataTable->FindRow<FDialogueRow>(RowName, Context);
|
||||||
|
|
||||||
|
//if (SelectedRow == nullptr)
|
||||||
|
//{
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (SelectedRow)
|
||||||
|
//{
|
||||||
|
// if (SelectedRow->DialogueRowData.Num() == 0)
|
||||||
|
// {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
|
||||||
|
bool UComboActionGraphNode_ActionNodeBase::ValidateNode(TArray<FText>& ValidationsMessages, const bool RichFormat)
|
||||||
|
{
|
||||||
|
bool bResult = Super::ValidateNode(ValidationsMessages, RichFormat);
|
||||||
|
|
||||||
|
//if (DataTable == nullptr)
|
||||||
|
//{
|
||||||
|
// bResult = false;
|
||||||
|
|
||||||
|
// const FString RichTextReturn =
|
||||||
|
// FString("* ").
|
||||||
|
// Append("<RichTextBlock.Bold>").
|
||||||
|
// Append(NodeTitle.ToString()).
|
||||||
|
// Append("</>").
|
||||||
|
// Append(": Does not contain any Dialogue Data Table!");
|
||||||
|
|
||||||
|
// const FString TextReturn =
|
||||||
|
// FString(NodeTitle.ToString()).
|
||||||
|
// Append(": Does not contain any Dialogue Data Table!");
|
||||||
|
//
|
||||||
|
// ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (RowName.IsNone())
|
||||||
|
//{
|
||||||
|
// bResult = false;
|
||||||
|
|
||||||
|
// const FString RichTextReturn =
|
||||||
|
// FString("* ").
|
||||||
|
// Append("<RichTextBlock.Bold>").
|
||||||
|
// Append(NodeTitle.ToString()).
|
||||||
|
// Append("</>").
|
||||||
|
// Append(": Does not contain valid Dialogue Row!");
|
||||||
|
|
||||||
|
// const FString TextReturn =
|
||||||
|
// FString(NodeTitle.ToString()).
|
||||||
|
// Append(": Does not contain valid Dialogue Row!");
|
||||||
|
//
|
||||||
|
// ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (MaxChildrenNodes > -1 && ChildrenNodes.Num() > MaxChildrenNodes)
|
||||||
|
//{
|
||||||
|
// const FString RichTextReturn =
|
||||||
|
// FString("* ").
|
||||||
|
// Append("<RichTextBlock.Bold>").
|
||||||
|
// Append(NodeTitle.ToString()).
|
||||||
|
// Append("</>").
|
||||||
|
// Append(": Has more than ").
|
||||||
|
// Append("<RichTextBlock.Bold>").
|
||||||
|
// Append(FString::FromInt(MaxChildrenNodes)).
|
||||||
|
// Append("</>").
|
||||||
|
// Append(" Children Nodes!");
|
||||||
|
|
||||||
|
// const FString TextReturn =
|
||||||
|
// FString(NodeTitle.ToString()).
|
||||||
|
// Append(": Has more than ").Append(FString::FromInt(MaxChildrenNodes)).Append(" Children Nodes!");
|
||||||
|
//
|
||||||
|
// ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//const FString Context;
|
||||||
|
//const FDialogueRow* SelectedRow = DataTable!=nullptr ? DataTable->FindRow<FDialogueRow>(RowName, Context) : nullptr;
|
||||||
|
|
||||||
|
//if (SelectedRow == nullptr)
|
||||||
|
//{
|
||||||
|
// bResult = false;
|
||||||
|
|
||||||
|
// const FString RichTextReturn =
|
||||||
|
// FString("* ").
|
||||||
|
// Append("<RichTextBlock.Bold>").
|
||||||
|
// Append(NodeTitle.ToString()).
|
||||||
|
// Append("</>").
|
||||||
|
// Append(": Invalid Selected Row!");
|
||||||
|
|
||||||
|
// const FString TextReturn =
|
||||||
|
// FString(NodeTitle.ToString()).
|
||||||
|
// Append(": Invalid Selected Row!");
|
||||||
|
//
|
||||||
|
// ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (SelectedRow)
|
||||||
|
//{
|
||||||
|
// if (SelectedRow->DialogueRowData.Num() == 0)
|
||||||
|
// {
|
||||||
|
// bResult = false;
|
||||||
|
|
||||||
|
// const FString RichTextReturn =
|
||||||
|
// FString("* ").
|
||||||
|
// Append("<RichTextBlock.Bold>").
|
||||||
|
// Append(NodeTitle.ToString()).
|
||||||
|
// Append("</>").
|
||||||
|
// Append(": Invalid Selected Row! No Dialogue Data Rows inside!");
|
||||||
|
|
||||||
|
// const FString TextReturn =
|
||||||
|
// FString(NodeTitle.ToString()).
|
||||||
|
// Append(": Invalid Selected Row! No Dialogue Data Rows inside!");
|
||||||
|
//
|
||||||
|
// ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
return bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphNode_ActionNodeBase::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||||
|
{
|
||||||
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||||
|
|
||||||
|
if (PropertyChangedEvent.GetPropertyName() == GET_MEMBER_NAME_CHECKED(UComboActionGraphNode_ActionNodeBase, DataTable))
|
||||||
|
{
|
||||||
|
RowName = FName("");
|
||||||
|
Preview.Empty();
|
||||||
|
PreviewsUpdated.ExecuteIfBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PropertyChangedEvent.GetPropertyName() == GET_MEMBER_NAME_CHECKED(UComboActionGraphNode_ActionNodeBase, RowName))
|
||||||
|
{
|
||||||
|
UpdatePreviews();
|
||||||
|
PreviewsUpdated.ExecuteIfBound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FText UComboActionGraphNode_ActionNodeBase::GetDescription_Implementation() const
|
||||||
|
{
|
||||||
|
return LOCTEXT("ComboActionGraphNode_BaseDescription", "Action base node has no logic tied to itself.");
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FText> UComboActionGraphNode_ActionNodeBase::GetPreviews() const
|
||||||
|
{
|
||||||
|
TArray<FText> ReturnValues;
|
||||||
|
|
||||||
|
//const auto Row = UComboActionSystemBFC::GetDialogueRow( this );
|
||||||
|
//if (UComboActionSystemBFC::IsDialogueRowValid(Row))
|
||||||
|
//{
|
||||||
|
// for (auto Itr : Row.DialogueRowData.Array())
|
||||||
|
// {
|
||||||
|
// ReturnValues.Add( Itr.RowText );
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// ReturnValues.Empty();
|
||||||
|
//}
|
||||||
|
|
||||||
|
return ReturnValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphNode_ActionNodeBase::UpdatePreviews()
|
||||||
|
{
|
||||||
|
if (!DataTable) Preview.Empty();
|
||||||
|
|
||||||
|
Preview.Empty();
|
||||||
|
|
||||||
|
Preview = GetPreviews();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef LOCTEXT_NAMESPACE
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Nodes/ComboActionGraphNode_StartNode.h"
|
||||||
|
|
||||||
|
#define LOCTEXT_NAMESPACE "ComboActionGraphNode_StartNode"
|
||||||
|
|
||||||
|
|
||||||
|
UComboActionGraphNode_StartNode::UComboActionGraphNode_StartNode()
|
||||||
|
{
|
||||||
|
#if WITH_EDITORONLY_DATA
|
||||||
|
this->bAllowInputNodes = false;
|
||||||
|
this->NodeTitle = LOCTEXT("ComboActionGraphNode_StartNodeTitle", "Start Action");
|
||||||
|
this->NodeTypeName = LOCTEXT("ComboActionGraphNode_StartNodeInternalTitle", "Start Action");
|
||||||
|
this->ContextMenuName = LOCTEXT("ComboActionGraphNode_StartNodeContextMenuName", "Start Action");
|
||||||
|
this->BackgroundColor = FLinearColor(0, 1, 0, 1);
|
||||||
|
|
||||||
|
this->bAllowCopy = false;
|
||||||
|
this->bAllowCut = false;
|
||||||
|
this->bAllowPaste = false;
|
||||||
|
this->bAllowDelete = false;
|
||||||
|
this->bAllowManualCreate = false;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// TODO: Once there are Conditional Decorators, this will be replaced
|
||||||
|
MaxChildrenNodes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
|
||||||
|
FText UComboActionGraphNode_StartNode::GetDescription_Implementation() const
|
||||||
|
{
|
||||||
|
return LOCTEXT("ComboActionGraphNode_StartNodeDescription", "Start node is automatically placed and cannot be deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraphNode_StartNode::ValidateNode(TArray<FText>& ValidationsMessages, const bool RichFormat)
|
||||||
|
{
|
||||||
|
bool bResult = Super::ValidateNode(ValidationsMessages, RichFormat);
|
||||||
|
|
||||||
|
if (ChildrenNodes.Num() == 0)
|
||||||
|
{
|
||||||
|
bResult = false;
|
||||||
|
|
||||||
|
const FString RichTextReturn =
|
||||||
|
FString("* ")
|
||||||
|
.Append("<RichTextBlock.Bold>")
|
||||||
|
.Append(this->NodeTitle.ToString())
|
||||||
|
.Append("</>")
|
||||||
|
.Append(": Does not have any child nodes!");
|
||||||
|
|
||||||
|
const FString TextReturn =
|
||||||
|
FString(this->NodeTitle.ToString())
|
||||||
|
.Append(": Does not have any child nodes!");
|
||||||
|
|
||||||
|
ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ChildrenNodes.Num() > 1)
|
||||||
|
{
|
||||||
|
bResult = false;
|
||||||
|
|
||||||
|
const FString RichTextReturn =
|
||||||
|
FString("* ")
|
||||||
|
.Append("<RichTextBlock.Bold>")
|
||||||
|
.Append(this->NodeTitle.ToString())
|
||||||
|
.Append("</>")
|
||||||
|
.Append(": Has more than 1 child node.");
|
||||||
|
|
||||||
|
const FString TextReturn = FString(this->NodeTitle.ToString())
|
||||||
|
.Append(": Has more than 1 child node.");
|
||||||
|
|
||||||
|
ValidationsMessages.Add(FText::FromString(RichFormat ? RichTextReturn : TextReturn));
|
||||||
|
}
|
||||||
|
|
||||||
|
return bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef LOCTEXT_NAMESPACE
|
||||||
172
Source/ComboInput/Public/ComboActionGraph.h
Normal file
172
Source/ComboInput/Public/ComboActionGraph.h
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "GameplayTagContainer.h"
|
||||||
|
#include "Decorators/ComboActionDecoratorBase.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraph.generated.h"
|
||||||
|
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(LogComboActionGraph, Log, All);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combo Action graph.
|
||||||
|
*
|
||||||
|
* Can be manually created from Content Browser, using Combo Action category.
|
||||||
|
* Comes with a node editor, which provides easy to follow visual way to create combo strings.
|
||||||
|
*/
|
||||||
|
UCLASS(BlueprintType, ClassGroup=("Combo Input|Action"), DisplayName="Combo Action Tree", HideCategories=("Hidden", "Private", "Base"), AutoExpandCategories=("Combo Input", "Action"))
|
||||||
|
class COMBOINPUT_API UComboActionGraph : public UObject
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
UComboActionGraph();
|
||||||
|
|
||||||
|
#pragma region Variables
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of decorators for the dialogue graph.
|
||||||
|
* Decorators are used to add extra functionality or behavior to the nodes in the graph.
|
||||||
|
* This array should contain an instance of each decorator used in the graph.
|
||||||
|
* The order of the decorators in this array determines the order in which they will be applied to the nodes.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Combo Input|Action", NoClear, meta=(NoResetToDefault))
|
||||||
|
TArray<FComboActionDecorator> GraphDecorators;
|
||||||
|
/**
|
||||||
|
* A set of gameplay tags associated with this dialogue graph.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
FGameplayTagContainer GraphTags;
|
||||||
|
/**
|
||||||
|
* GUID for this Mountea Dialogue Graph.
|
||||||
|
*❗ Unique identifier for this Dialogue Graph instance.
|
||||||
|
*❔ Can be used for debugging and tracing purposes.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category="Combo Input")
|
||||||
|
FGuid GraphGUID;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Pointer to the starting node of the dialogue graph.
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
class UComboActionGraphNode *StartNode = nullptr;
|
||||||
|
/**
|
||||||
|
* The class of the dialogue node represented by this instance.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
TSubclassOf<UComboActionGraphNode> NodeType;
|
||||||
|
/**
|
||||||
|
* 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 dialogue graph. These are the nodes that do not have any incoming connections.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
TArray<UComboActionGraphNode*> RootNodes;
|
||||||
|
/**
|
||||||
|
* Array containing all the nodes in the graph, including both root nodes and child nodes.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
TArray<UComboActionGraphNode*> AllNodes;
|
||||||
|
// Flag indicating whether an edge is enabled
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
bool bEdgeEnabled;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Functions
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Returns the GUID of the graph.
|
||||||
|
*
|
||||||
|
* @return The GUID of the graph.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category="Combo Input|Action")
|
||||||
|
FGuid GetGraphGUID() const { return this->GraphGUID; }
|
||||||
|
/**
|
||||||
|
* Returns an array containing all nodes in the dialogue graph.
|
||||||
|
* @return An array of all nodes in the dialogue graph.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category="Combo Input|Action")
|
||||||
|
TArray<UComboActionGraphNode*> GetAllNodes() const { return this->AllNodes; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category="Combo Input|Action")
|
||||||
|
TArray<UComboActionGraphNode*> GetRootNodes() const { return this->RootNodes; }
|
||||||
|
/**
|
||||||
|
* Returns the root nodes of the dialogue graph.
|
||||||
|
*
|
||||||
|
* @return An array of all root nodes.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category="Combo Input|Action")
|
||||||
|
UComboActionGraphNode *GetStartNode() const { return this->StartNode; }
|
||||||
|
/**
|
||||||
|
* Returns the array of decorators that are associated with this graph.
|
||||||
|
*
|
||||||
|
* @return The array of decorators.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
TArray<FComboActionDecorator> GetGraphDecorators() const;
|
||||||
|
/**
|
||||||
|
* Returns the array of decorators that are associated with this graph and its nodes.
|
||||||
|
*
|
||||||
|
* @return The array of decorators.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
TArray<FComboActionDecorator> GetAllDecorators() const;
|
||||||
|
/**
|
||||||
|
* Determines whether the dialogue graph can be started.
|
||||||
|
*
|
||||||
|
* @return true if the graph can be started, false otherwise.
|
||||||
|
*/
|
||||||
|
bool CanStartDialogueGraph() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void CreateGraph();
|
||||||
|
void ClearGraph();
|
||||||
|
|
||||||
|
FORCEINLINE bool IsEdgeEnabled() const { return bEdgeEnabled; }
|
||||||
|
|
||||||
|
virtual void PostInitProperties() override;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#if WITH_EDITORONLY_DATA
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY()
|
||||||
|
class UEdGraph *EdGraph;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action|Editor")
|
||||||
|
bool bCanRenameNode;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
|
||||||
|
virtual bool ValidateGraph(TArray<FText> &ValidationErrors, bool RichTextFormat);
|
||||||
|
virtual EDataValidationResult IsDataValid(TArray<FText> &ValidationErrors) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Construct and initialize a node within this Dialogue.
|
||||||
|
template<class T>
|
||||||
|
T* ConstructDialogueNode(TSubclassOf<class UComboActionGraphNode> DialogueNodeClass = T::StaticClass())
|
||||||
|
{
|
||||||
|
// Set flag to be transactional so it registers with undo system
|
||||||
|
T *DialogueNode = NewObject<T>(this, DialogueNodeClass, NAME_None, EObjectFlags::RF_Transactional);
|
||||||
|
DialogueNode->OnCreatedInEditor();
|
||||||
|
return DialogueNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
};
|
||||||
14
Source/ComboInput/Public/Data/ComboActionAdditionalData.h
Normal file
14
Source/ComboInput/Public/Data/ComboActionAdditionalData.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "ComboActionAdditionalData.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
UCLASS(Abstract, BlueprintType, meta=(UsesHierarchy=true), Blueprintable, ClassGroup="Combo Input|Action")
|
||||||
|
class COMBOINPUT_API UComboActionAdditionalData : public UObject
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
};
|
||||||
203
Source/ComboInput/Public/Data/ComboActionContext.h
Normal file
203
Source/ComboInput/Public/Data/ComboActionContext.h
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "Data/ComboActionGraphDataTypes.h"
|
||||||
|
#include "Nodes/ComboActionGraphNode.h"
|
||||||
|
#include "UObject/Object.h"
|
||||||
|
|
||||||
|
#include "ComboActionContext.generated.h"
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FComboActionContextUpdatedFromBlueprint, class UComboActionContext *, Context);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialogue Context.
|
||||||
|
*
|
||||||
|
* Contains information needed to successfully start Dialogue.
|
||||||
|
* Also helps tracking Dialogue Specific data. Is recycled for whole Dialogue Graph.
|
||||||
|
*
|
||||||
|
* In Dialogue Manager Component is used as Transient object, which is nullified once Dialogue ends and is never saved.
|
||||||
|
*/
|
||||||
|
UCLASS()
|
||||||
|
class COMBOINPUT_API UComboActionContext : public UObject
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
///**
|
||||||
|
// * Active Dialogue Participant Interface reference.
|
||||||
|
// *
|
||||||
|
// * This is the Participant who is Active right now.
|
||||||
|
// * ❔ Lead Node sets this value to Dialogue Participant.
|
||||||
|
// * ❔ Answer Node sets this value to Player Participant.
|
||||||
|
// * ❗ Might be invalid
|
||||||
|
// */
|
||||||
|
//UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
// TScriptInterface<IComboActionParticipantInterface> ActionParticipant;
|
||||||
|
|
||||||
|
///**
|
||||||
|
// * Player Dialogue Participant Interface reference.
|
||||||
|
// *
|
||||||
|
// * This is the Participant who represent the Player.
|
||||||
|
// * ❗ Might be invalid
|
||||||
|
// */
|
||||||
|
//UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
// TScriptInterface<class IComboActionParticipantInterface> PlayerDialogueParticipant;
|
||||||
|
|
||||||
|
//UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
// TScriptInterface<class IComboActionParticipantInterface> DialogueParticipant;
|
||||||
|
|
||||||
|
//UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
// TArray<TScriptInterface<class IComboActionParticipantInterface>> DialogueParticipants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to the Node which is currently active.
|
||||||
|
* ❗ Might be null
|
||||||
|
*/
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
class UComboActionGraphNode *ActiveNode = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of Nodes that can be accessed from Active Node.
|
||||||
|
* Already filtered to contain only those that can be triggered.
|
||||||
|
*
|
||||||
|
* ❔ Filter is done by 'CanStartNode', which can have its own logic and can be driven by Decorators as well.
|
||||||
|
* ❗ Might be empty
|
||||||
|
*/
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
TArray<class UComboActionGraphNode*> AllowedChildNodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index of currently used Dialogue Row Data row.
|
||||||
|
*/
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
int32 ActiveDialogueRowDataIndex = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains mapped list of Traversed Nodes by GUIDs.
|
||||||
|
* Each time Dialogue is updated, like node is selected or starts itself, this Path is updated.
|
||||||
|
* Updates Participant once Dialogue is done.
|
||||||
|
*/
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combo Input|Action", meta=(NoResetToDefault))
|
||||||
|
TMap<FGuid, int32> TraversedPath;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action|Debug")
|
||||||
|
virtual bool IsValid() const;
|
||||||
|
|
||||||
|
//TScriptInterface<class IComboActionParticipantInterface> GetDialoguePlayerParticipant() const { return this->PlayerDialogueParticipant; }
|
||||||
|
//TScriptInterface<class IComboActionParticipantInterface> GetDialogueParticipant() const { return this->DialogueParticipant; }
|
||||||
|
//TArray<TScriptInterface<class IComboActionParticipantInterface>> GetDialogueParticipants() const { return this->DialogueParticipants; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Active Node object.
|
||||||
|
* ❗ Might be null
|
||||||
|
*
|
||||||
|
* @return Active Node if any specified
|
||||||
|
*/
|
||||||
|
class UComboActionGraphNode *GetActiveNode() const { return this->ActiveNode; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns lsit of Children Nodes from Active Node.
|
||||||
|
* ❗ Might be empty
|
||||||
|
*
|
||||||
|
* @return List of allowed Children Nodes
|
||||||
|
*/
|
||||||
|
TArray<class UComboActionGraphNode*> GetChildrenNodes() const { return this->AllowedChildNodes; }
|
||||||
|
///**
|
||||||
|
// *Returns the Active Dialogue Row Data Index.
|
||||||
|
// *
|
||||||
|
// * @return Active Row Index
|
||||||
|
// */
|
||||||
|
//int32 GetActiveDialogueRowDataIndex() const { return this->ActiveDialogueRowDataIndex; }
|
||||||
|
/**
|
||||||
|
* Returns the map of nodes traversed during this dialogue instance.
|
||||||
|
*
|
||||||
|
* @return The map of nodes traversed during this dialogue instance.
|
||||||
|
*/
|
||||||
|
TMap<FGuid, int32> GetTraversedPath() const { return TraversedPath; }
|
||||||
|
|
||||||
|
virtual void SetComboActionContext(class UComboActionGraphNode *NewActiveNode, TArray<class UComboActionGraphNode*> NewAllowedChildNodes);
|
||||||
|
//virtual void UpdateDialogueParticipant(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
|
||||||
|
//virtual void UpdateActiveDialogueNode(class UComboActionGraphNode *NewActiveNode);
|
||||||
|
//virtual void UpdateAllowedChildrenNodes(const TArray<class UComboActionGraphNode*> &NewNodes);
|
||||||
|
//virtual void UpdateActiveDialogueRowDataIndex(int32 NewIndex);
|
||||||
|
//void UpdateDialoguePlayerParticipant(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
|
||||||
|
//void UpdateActiveDialogueParticipant(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
|
||||||
|
//void AddTraversedNode(const class UComboActionGraphNode* TraversedNode);
|
||||||
|
|
||||||
|
//virtual bool AddDialogueParticipants(const TArray<TScriptInterface<class IComboActionParticipantInterface>> &NewParticipants);
|
||||||
|
//virtual bool AddDialogueParticipant(const TScriptInterface<class IComboActionParticipantInterface> &NewParticipant);
|
||||||
|
//virtual bool RemoveDialogueParticipants(const TArray<TScriptInterface<class IComboActionParticipantInterface>> &NewParticipants);
|
||||||
|
//virtual bool RemoveDialogueParticipant(const TScriptInterface<class IComboActionParticipantInterface> &NewParticipant);
|
||||||
|
//virtual void ClearDialogueParticipants();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the dialogue context.
|
||||||
|
*
|
||||||
|
* @param NewParticipant The new dialogue participant.
|
||||||
|
* @param NewActiveNode The new active dialogue node.
|
||||||
|
* @param NewAllowedChildNodes The new allowed child dialogue nodes.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="SetDialogueContext"))
|
||||||
|
virtual void SetComboActionContextBP(class UComboActionGraphNode *NewActiveNode, TArray<class UComboActionGraphNode*> NewAllowedChildNodes);
|
||||||
|
|
||||||
|
///**
|
||||||
|
// * Updates Dialogue Participant.
|
||||||
|
// *
|
||||||
|
// * @param NewParticipant - new Dialogue Participant.
|
||||||
|
// * ❗ Must implement IComboActionParticipantInterface.
|
||||||
|
// */
|
||||||
|
//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateDialogueParticipant"))
|
||||||
|
// virtual void UpdateDialogueParticipantBP(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
|
||||||
|
/**
|
||||||
|
* Updates Active Dialogue Node in Context.
|
||||||
|
*
|
||||||
|
* @param NewActiveNode - New Active Dialogue Node to update to.
|
||||||
|
* ❗ Must not be Null
|
||||||
|
*/
|
||||||
|
//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateActiveDialogueNode"))
|
||||||
|
// virtual void UpdateActiveDialogueNodeBP(class UComboActionGraphNode *NewActiveNode);
|
||||||
|
/**
|
||||||
|
* Updates the active dialogue row Data Index.
|
||||||
|
*
|
||||||
|
* @param NewIndex - The new active dialogue data row Index.
|
||||||
|
*/
|
||||||
|
//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateActiveDialogueRowDataIndex"))
|
||||||
|
// virtual void UpdateActiveDialogueRowDataIndexBP(int32 NewIndex);
|
||||||
|
///**
|
||||||
|
// * Updates Dialogue Player Participant.
|
||||||
|
// *
|
||||||
|
// * @param NewParticipant - new Dialogue Player Participant.
|
||||||
|
// * ❗ Must implement IMounteaDialogueParticipantInterface.
|
||||||
|
// */
|
||||||
|
//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateDialoguePlayerParticipant"))
|
||||||
|
// void UpdateDialoguePlayerParticipantBP(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
|
||||||
|
///**
|
||||||
|
// * Updates Dialogue Active Participant.
|
||||||
|
// *
|
||||||
|
// * @param NewParticipant - new Dialogue Active Participant.
|
||||||
|
// * ❗ Must implement IMounteaDialogueParticipantInterface.
|
||||||
|
// */
|
||||||
|
//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="UpdateActiveDialogueParticipant"))
|
||||||
|
// void UpdateActiveDialogueParticipantBP(TScriptInterface<class IComboActionParticipantInterface> NewParticipant);
|
||||||
|
|
||||||
|
//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="AddDialogueParticipant"))
|
||||||
|
// virtual bool AddDialogueParticipantBP(const TScriptInterface<class IComboActionParticipantInterface>& NewParticipant);
|
||||||
|
//
|
||||||
|
//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="RemoveDialogueParticipant"))
|
||||||
|
// virtual bool RemoveDialogueParticipantBP(const TScriptInterface<class IComboActionParticipantInterface>& NewParticipant);
|
||||||
|
|
||||||
|
//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="AddDialogueParticipants"))
|
||||||
|
// virtual bool AddDialogueParticipantsBP(const TArray<TScriptInterface<class IComboActionParticipantInterface>>& NewParticipants);
|
||||||
|
//
|
||||||
|
//UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Context", meta=(DisplayName="RemoveDialogueParticipants"))
|
||||||
|
// virtual bool RemoveDialogueParticipantsBP(const TArray<TScriptInterface<class IComboActionParticipantInterface>>& NewParticipants);
|
||||||
|
|
||||||
|
FComboActionContextUpdatedFromBlueprint ComboActionContextUpdatedFromBlueprint;
|
||||||
|
};
|
||||||
27
Source/ComboInput/Public/Data/ComboActionGraphDataTypes.h
Normal file
27
Source/ComboInput/Public/Data/ComboActionGraphDataTypes.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "ComboActionAdditionalData.h"
|
||||||
|
#include "GameplayTagContainer.h"
|
||||||
|
#include "Blueprint/UserWidget.h"
|
||||||
|
#include "Engine/DataTable.h"
|
||||||
|
#include "UObject/Object.h"
|
||||||
|
|
||||||
|
#include "Fonts/SlateFontInfo.h"
|
||||||
|
#include "Styling/CoreStyle.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraphDataTypes.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combo Action Manager state
|
||||||
|
*/
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EComboActionManagerState : uint8
|
||||||
|
{
|
||||||
|
Disabled UMETA(DisplayName="Disabled", Tooltip="Disabled. Combo action cannot be used."),
|
||||||
|
Enabled UMETA(DisplayName="Enabled", Tooltip="Enabled. Combo action can start."),
|
||||||
|
Active UMETA(DisplayName="Activated", Tooltip="Combo action is activated"),
|
||||||
|
};
|
||||||
254
Source/ComboInput/Public/Decorators/ComboActionDecoratorBase.h
Normal file
254
Source/ComboInput/Public/Decorators/ComboActionDecoratorBase.h
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Engine/Level.h"
|
||||||
|
|
||||||
|
#include "ComboActionDecoratorBase.generated.h"
|
||||||
|
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(LogComboActionDecoratorBase, Log, All);
|
||||||
|
|
||||||
|
#define LOCTEXT_NAMESPACE "NodeDecoratorBase"
|
||||||
|
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EComboActionDecoratorState : uint8
|
||||||
|
{
|
||||||
|
Uninitialized,
|
||||||
|
Initialized
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combo Action Decorator
|
||||||
|
*
|
||||||
|
* Decorators are instanced and exist only as "triggers".
|
||||||
|
* Could be used to start audio, play animation or do some logic behind the curtains, like triggering Cutscene etc.
|
||||||
|
*/
|
||||||
|
UCLASS(Abstract, Blueprintable, BlueprintType, EditInlineNew, ClassGroup=("Combo Input|Action"), AutoExpandCategories=("Combo Input, Action"))
|
||||||
|
class COMBOINPUT_API UComboActionDecoratorBase : public UObject
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE ULevel *GetLevel() const { return this->GetTypedOuter<ULevel>(); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual UWorld *GetWorld() const override
|
||||||
|
{
|
||||||
|
if (this->OwningWorld)
|
||||||
|
{
|
||||||
|
return this->OwningWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDO objects do not belong to a world
|
||||||
|
// If the actors outer is destroyed or unreachable we are shutting down and the world should be nullptr
|
||||||
|
if (!this->HasAnyFlags(EObjectFlags::RF_ClassDefaultObject) && ensureMsgf(this->GetOuter(), TEXT("Actor: %s has a null OuterPrivate in AActor::GetWorld()"), *this->GetFullName()) &&
|
||||||
|
!this->GetOuter()->HasAnyFlags(EObjectFlags::RF_BeginDestroyed) && !this->GetOuter()->IsUnreachable())
|
||||||
|
{
|
||||||
|
if (ULevel *Level = this->GetLevel())
|
||||||
|
{
|
||||||
|
return Level->OwningWorld;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintNativeEvent, Category="Combo Input|Action|Decorators")
|
||||||
|
FString GetDecoratorDocumentationLink() const;
|
||||||
|
virtual FString GetDecoratorDocumentationLink_Implementation() const { return TEXT("This is a place where a link to the documentation will go eventually."); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the Decorator.
|
||||||
|
* In C++ saves the World for later use.
|
||||||
|
* In Blueprints should be used to cache values to avoid overhead in 'ExecuteDecorator'.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, Category="Combo Input|Action|Decorators")
|
||||||
|
void InitializeDecorator(UWorld *World);
|
||||||
|
virtual void InitializeDecorator_Implementation(UWorld *World)
|
||||||
|
{
|
||||||
|
this->OwningWorld = World;
|
||||||
|
if (World)
|
||||||
|
{
|
||||||
|
this->DecoratorState = EComboActionDecoratorState::Initialized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up the Decorator.
|
||||||
|
* In Blueprints should be used to reset cached values to avoid blocking garbage collector.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, Category="Combo Input|Action|Decorators")
|
||||||
|
void CleanupDecorator();
|
||||||
|
virtual void CleanupDecorator_Implementation() { this->DecoratorState = EComboActionDecoratorState::Uninitialized; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the Decorator.
|
||||||
|
* Called for each Node it is attached to.
|
||||||
|
* Works as safety measure to avoid calling broken Decorators with invalid references.
|
||||||
|
*
|
||||||
|
* False value stops Dialogue whatsoever.
|
||||||
|
* Validation is called before Context is initialized!
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, Category="Combo Input|Action|Decorators")
|
||||||
|
bool ValidateDecorator(TArray<FText> &ValidationMessages);
|
||||||
|
virtual bool ValidateDecorator_Implementation(TArray<FText> &ValidationMessages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the Decorator.
|
||||||
|
* Called for each Node it is attached to.
|
||||||
|
* Could enhance Node's 'CanStartNode'. Example would be: BP_RequireItem decorator, which would return true if Player has specific Item in inventory. Otherwise it returns false and its Node is not available in Selection of Answers.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, Category="Combo Input|Action|Decorators")
|
||||||
|
bool EvaluateDecorator();
|
||||||
|
virtual bool EvaluateDecorator_Implementation() { return this->OwningWorld != nullptr; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the Decorator.
|
||||||
|
* Useful for triggering special events per Node, for instance, switching dialogue cameras.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, Category="Combo Input|Action|Decorators")
|
||||||
|
void ExecuteDecorator();
|
||||||
|
virtual bool ExecuteDecorator_Implementation() { return true; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores reference to World.
|
||||||
|
* World is needed to perform World affecting tasks.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Decorators")
|
||||||
|
void StoreWorldReference(UWorld *World) { this->OwningWorld = World; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns Owning World this Decorator belongs to.
|
||||||
|
*
|
||||||
|
* ❗ Should not return Null, but possibly can.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category="Combo Input|Action|Decorators", meta=(CompactNodeTitle="World"))
|
||||||
|
UWorld *GetOwningWorld() const { return this->OwningWorld; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns Owning Node of this Decorator.
|
||||||
|
*
|
||||||
|
* ❗ Might return Null if this Decorator is owned by Graph!
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action|Decorators", meta=(CompactNodeTitle="OwningNode"))
|
||||||
|
class UComboActionGraphNode *GetOwningNode() const { return this->GetTypedOuter<UComboActionGraphNode>(); }
|
||||||
|
/**
|
||||||
|
* Returns Owning Graph of this Decorator.
|
||||||
|
*
|
||||||
|
* ❗ Might return Null if this Decorator is owned by Node!
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action|Decorators", meta=(CompactNodeTitle="OwningGraph"))
|
||||||
|
class UComboActionGraph *GetOwningGraph() const { return this->GetTypedOuter<UComboActionGraph>(); }
|
||||||
|
/**
|
||||||
|
* Returns Owning Object of this Decorator.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action|Decorators", meta=(CompactNodeTitle="Owner"))
|
||||||
|
UObject *GetOwner() const { return this->GetOuter(); }
|
||||||
|
|
||||||
|
FText GetDecoratorName() const
|
||||||
|
{
|
||||||
|
#if WITH_EDITORONLY_DATA
|
||||||
|
return this->GetClass()->GetDisplayNameText();
|
||||||
|
#else
|
||||||
|
return FText::FromString(GetName());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
UPROPERTY() EComboActionDecoratorState DecoratorState = EComboActionDecoratorState::Uninitialized;
|
||||||
|
|
||||||
|
UPROPERTY() UWorld *OwningWorld = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialogue Decorator Structure.
|
||||||
|
* Holds reference to its Instanced Decorator.
|
||||||
|
*/
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FComboActionDecorator
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
FComboActionDecorator() : DecoratorType(nullptr) {};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void InitializeDecorator(UWorld *World) const
|
||||||
|
{
|
||||||
|
if (this->DecoratorType)
|
||||||
|
{
|
||||||
|
this->DecoratorType->InitializeDecorator(World);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(LogComboActionDecoratorBase, Error, TEXT("[InitializeDecorator] DecoratorType is null (invalid)!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValidateDecorator(TArray<FText>& ValidationMessages) const
|
||||||
|
{
|
||||||
|
if (this->DecoratorType)
|
||||||
|
{
|
||||||
|
return this->DecoratorType->ValidateDecorator(ValidationMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
UE_LOG(LogComboActionDecoratorBase, Error, TEXT("[EvaluateDecorator] DecoratorType is null (invalid)!"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanupDecorator() const
|
||||||
|
{
|
||||||
|
if (this->DecoratorType)
|
||||||
|
{
|
||||||
|
this->DecoratorType->CleanupDecorator();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(LogComboActionDecoratorBase, Error, TEXT("[CleanupDecorator] DecoratorType is null (invalid)!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EvaluateDecorator() const
|
||||||
|
{
|
||||||
|
if (this->DecoratorType)
|
||||||
|
{
|
||||||
|
return this->DecoratorType->EvaluateDecorator();
|
||||||
|
}
|
||||||
|
|
||||||
|
UE_LOG(LogComboActionDecoratorBase, Error, TEXT("[EvaluateDecorator] DecoratorType is null (invalid)!"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExecuteDecorator() const
|
||||||
|
{
|
||||||
|
if (this->DecoratorType)
|
||||||
|
{
|
||||||
|
this->DecoratorType->ExecuteDecorator();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(LogComboActionDecoratorBase, Error, TEXT("[ExecuteDecorator] DecoratorType is null (invalid)!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorators can help out with enhancing the Dialogue flow.
|
||||||
|
* Those Decorators are instanced and exist only as "triggers".
|
||||||
|
* Could be used to start audio, play animation or do some logic behind the curtains, like triggering Cutscene etc.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "Combo Input|Action", meta=(NoResetToDefault, AllowAbstract = "false", BlueprintBaseOnly = "true"))
|
||||||
|
UComboActionDecoratorBase *DecoratorType = nullptr;
|
||||||
|
|
||||||
|
bool operator==(const FComboActionDecorator &Other) const { return this->DecoratorType == Other.DecoratorType; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef LOCTEXT_NAMESPACE
|
||||||
@ -0,0 +1,233 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Data/ComboActionGraphDataTypes.h"
|
||||||
|
#include "UObject/Interface.h"
|
||||||
|
#include "ComboActionGraphManagerInterface.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
// This class does not need to be modified.
|
||||||
|
UINTERFACE(MinimalAPI, BlueprintType, Blueprintable)
|
||||||
|
class UComboActionGraphManagerInterface : public UInterface
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueInitialized, UMounteaDialogueContext*, Context);
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueEvent, UMounteaDialogueContext*, Context);
|
||||||
|
//
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueContextUpdated, UMounteaDialogueContext*, Context);
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDialogueUserInterfaceChanged, TSubclassOf<UUserWidget>, DialogueWidgetClass, UUserWidget*, DialogueWidget);
|
||||||
|
//
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueNodeEvent, UMounteaDialogueContext*, Context);
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueRowEvent, UMounteaDialogueContext*, Context);
|
||||||
|
//
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueFailed, const FString&, ErrorMessage);
|
||||||
|
//
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueManagerStateChanged, const EDialogueManagerState&, NewState);
|
||||||
|
//
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueVoiceEvent, class USoundBase*, NewDialogueVoice);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mountea Dialogue Manager Interface.
|
||||||
|
*
|
||||||
|
* Should attached directly to Player Controller or used for Components that are attached to some Controller.
|
||||||
|
* Provides options to start and stop dialogue as well as ability to select dialogue options.
|
||||||
|
*/
|
||||||
|
class COMBOINPUT_API IComboActionGraphManagerInterface
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the Dialogue that a node has been selected.
|
||||||
|
*
|
||||||
|
* @param NodeGUID The GUID of the selected node.
|
||||||
|
*/
|
||||||
|
//UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="Combo Input|Action", meta=(Keywords="select, chosen, option"))
|
||||||
|
// void CallDialogueNodeSelected(const FGuid &NodeGUID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the Dialogue if possible.
|
||||||
|
*/
|
||||||
|
//virtual void StartDialogue() = 0;
|
||||||
|
/**
|
||||||
|
* Closes the Dialogue if is active.
|
||||||
|
*/
|
||||||
|
//virtual void CloseDialogue() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to Invoke Dialogue UI.
|
||||||
|
* This function servers a purpose to try showing Dialogue UI to player.
|
||||||
|
* ❔ If this function fails, Message will be populated with error message explaining what went wrong.
|
||||||
|
*
|
||||||
|
* @param Message InMessage to be populated with error message explaining why returns false
|
||||||
|
* @return true if UI can be added to screen, false if cannot
|
||||||
|
*/
|
||||||
|
//virtual bool InvokeDialogueUI(FString& Message) = 0;
|
||||||
|
/**
|
||||||
|
* Gets the widget class used to display Dialogue UI.
|
||||||
|
*
|
||||||
|
* @return The widget class used to display Dialogue UI.
|
||||||
|
*/
|
||||||
|
//virtual TSubclassOf<UUserWidget> GetDialogueWidgetClass() const = 0;
|
||||||
|
/**
|
||||||
|
* Sets the widget class for the Dialogue UI.
|
||||||
|
* ❗ This is a pure virtual function that must be implemented in derived classes.
|
||||||
|
*
|
||||||
|
* @param NewWidgetClass The new widget class to set.
|
||||||
|
*/
|
||||||
|
//virtual void SetDialogueWidgetClass(TSubclassOf<UUserWidget> NewWidgetClass) = 0;
|
||||||
|
/**
|
||||||
|
* Returns Dialogue UI pointer.
|
||||||
|
*
|
||||||
|
* ❗ Could be null
|
||||||
|
* @return UserWidget pointer to created UI
|
||||||
|
*/
|
||||||
|
//virtual UUserWidget *GetDialogueUIPtr() const = 0;
|
||||||
|
/**
|
||||||
|
* Sets Dialogue UI pointer.
|
||||||
|
*
|
||||||
|
* ❔ Using null value resets saved value
|
||||||
|
* @param DialogueUIPtr UserWidget pointer to be saved as Dialogue UI
|
||||||
|
*/
|
||||||
|
//virtual void SetDialogueUIPtr(UUserWidget *DialogueUIPtr) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts Dialogue Row execution.
|
||||||
|
* ❔ Dialogue Data contain Dialogue Data Rows, which are individual dialogue lines, which can be skipped.
|
||||||
|
* ❔ Once all Dialogue Data Rows are finished, Dialogue Data is finished as well.
|
||||||
|
*/
|
||||||
|
//virtual void StartExecuteDialogueRow() = 0;
|
||||||
|
/**
|
||||||
|
* Function responsible for cleanup once Dialogue Row is finished.
|
||||||
|
* ❔ Dialogue Data contain Dialogue Data Rows, which are individual dialogue lines, which can be skipped.
|
||||||
|
* ❔ Once all Dialogue Data Rows are finished, Dialogue Data is finished as well.
|
||||||
|
*/
|
||||||
|
//virtual void FinishedExecuteDialogueRow() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the current dialogue context associated with this dialogue instance.
|
||||||
|
*
|
||||||
|
* @return The dialogue context object for this instance.
|
||||||
|
*/
|
||||||
|
//UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
//UMounteaDialogueContext* GetDialogueContextEvent() const;
|
||||||
|
//UMounteaDialogueContext* GetDialogueContextEvent_Implementation() const
|
||||||
|
//{
|
||||||
|
// return GetDialogueContext();
|
||||||
|
//}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the widget used to display the current dialogue.
|
||||||
|
*
|
||||||
|
* @return The widget used to display the current dialogue.
|
||||||
|
*/
|
||||||
|
//UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="Combo Input|Action", meta=(Keywords="UI, Widget"))
|
||||||
|
//UUserWidget* GetDialogueWidget();
|
||||||
|
//UUserWidget* GetDialogueWidget_Implementation()
|
||||||
|
//{
|
||||||
|
// return GetDialogueWidget();
|
||||||
|
//};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the owning actor for this Dialogue Manager Component.
|
||||||
|
*
|
||||||
|
* @return The owning actor for this Dialogue Manager Component.
|
||||||
|
*/
|
||||||
|
//UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
//AActor* GetOwningActor() const;
|
||||||
|
//virtual AActor* GetOwningActor_Implementation() const
|
||||||
|
//{
|
||||||
|
// return nullptr;
|
||||||
|
//};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the node for execution.
|
||||||
|
* Asks Active Node to 'PreProcessNode' and then to 'ProcessNode'.
|
||||||
|
* In this preparation stage, Nodes are asked to process all Decorators.
|
||||||
|
*/
|
||||||
|
//UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
//void PrepareNode();
|
||||||
|
//virtual void PrepareNode_Implementation() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves current Dialogue Context.
|
||||||
|
*
|
||||||
|
* ❗ Could be null
|
||||||
|
* @return DialogueContext Dialogue Context is transient data holder for current dialogue instance.
|
||||||
|
*/
|
||||||
|
//virtual UMounteaDialogueContext* GetDialogueContext() const = 0;
|
||||||
|
/**
|
||||||
|
* Sets new Dialogue Context.
|
||||||
|
*
|
||||||
|
* ❔ Null value clears saved data
|
||||||
|
* @param NewContext Dialogue Context to be set as Dialogue Context
|
||||||
|
*/
|
||||||
|
//virtual void SetDialogueContext(UMounteaDialogueContext* NewContext) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface call.
|
||||||
|
* Retrieves current Dialogue Manager State.
|
||||||
|
* State defines whether Manager can start/close dialogue or not.
|
||||||
|
*
|
||||||
|
* @return ManagerState Manager state value
|
||||||
|
*/
|
||||||
|
//UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
//EDialogueManagerState GetState() const;
|
||||||
|
//EDialogueManagerState GetState_Implementation() const
|
||||||
|
//{ return GetDialogueManagerState(); };
|
||||||
|
/**
|
||||||
|
* Retrieves current Dialogue Manager State.
|
||||||
|
* State defines whether Manager can start/close dialogue or not.
|
||||||
|
*
|
||||||
|
* @return ManagerState Manager state value
|
||||||
|
*/
|
||||||
|
//virtual EDialogueManagerState GetDialogueManagerState() const = 0;
|
||||||
|
/**
|
||||||
|
* Sets new Dialogue Manager State.
|
||||||
|
*
|
||||||
|
* @param NewState Manager State to be set as Manager State
|
||||||
|
*/
|
||||||
|
//virtual void SetDialogueManagerState(const EDialogueManagerState NewState) = 0;
|
||||||
|
/**
|
||||||
|
* Retrieves current Default Dialogue Manager State.
|
||||||
|
* Default Dialogue Manager State sets Dialogue Manager state upon BeginPlay and is used as fallback once Dialogue ends.
|
||||||
|
*
|
||||||
|
* @return ManagerState Default Manager state value
|
||||||
|
*/
|
||||||
|
//virtual EDialogueManagerState GetDefaultDialogueManagerState() const = 0;
|
||||||
|
/**
|
||||||
|
* Sets new Default Dialogue Manager State.
|
||||||
|
*
|
||||||
|
* @param NewState Manager State to be set as Default Manager State
|
||||||
|
*/
|
||||||
|
//virtual void SetDefaultDialogueManagerState(const EDialogueManagerState NewState) = 0;
|
||||||
|
//
|
||||||
|
//virtual FDialogueInitialized& GetDialogueInitializedEventHandle() = 0;
|
||||||
|
//virtual FDialogueEvent& GetDialogueStartedEventHandle() = 0;
|
||||||
|
//virtual FDialogueEvent& GetDialogueClosedEventHandle() = 0;
|
||||||
|
//
|
||||||
|
//virtual FDialogueContextUpdated& GetDialogueContextUpdatedEventHande() = 0;
|
||||||
|
//virtual FDialogueUserInterfaceChanged& GetDialogueUserInterfaceChangedEventHandle() = 0;
|
||||||
|
|
||||||
|
//virtual FDialogueNodeEvent& GetDialogueNodeSelectedEventHandle() = 0;
|
||||||
|
|
||||||
|
//virtual FDialogueNodeEvent& GetDialogueNodeStartedEventHandle() = 0;
|
||||||
|
//virtual FDialogueNodeEvent& GetDialogueNodeFinishedEventHandle() = 0;
|
||||||
|
//virtual FDialogueRowEvent& GetDialogueRowStartedEventHandle() = 0;
|
||||||
|
//virtual FDialogueRowEvent& GetDialogueRowFinishedEventHandle() = 0;
|
||||||
|
|
||||||
|
//virtual FDialogueFailed& GetDialogueFailedEventHandle() = 0;
|
||||||
|
|
||||||
|
//virtual FDialogueManagerStateChanged& GetDialogueManagerStateChangedEventHandle() = 0;
|
||||||
|
|
||||||
|
//virtual FDialogueVoiceEvent& GetDialogueVoiceStartRequestEventHandle() = 0;
|
||||||
|
//virtual FDialogueVoiceEvent& GetDialogueVoiceSkipRequestEventHandle() = 0;
|
||||||
|
|
||||||
|
//virtual FTimerHandle& GetDialogueRowTimerHandle() = 0;
|
||||||
|
};
|
||||||
199
Source/ComboInput/Public/Interfaces/ComboActionInterface.h
Normal file
199
Source/ComboInput/Public/Interfaces/ComboActionInterface.h
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Data/ComboActionGraphDataTypes.h"
|
||||||
|
#include "UObject/Interface.h"
|
||||||
|
|
||||||
|
#include "ComboActionInterface.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
UINTERFACE(MinimalAPI, BlueprintType, Blueprintable)
|
||||||
|
class UComboActionInterface : public UInterface
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
};
|
||||||
|
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueGraphChanged, UMounteaDialogueGraph*, NewGraph);
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueParticipantStateChanged, const EDialogueParticipantState&, NewState);
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDialogueParticipantAudioComponentChanged, const UAudioComponent*, NewAudioComp);
|
||||||
|
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FParticipantStartingNodeSaved, const UMounteaDialogueGraphNode*, NewSavedNode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combo Action Interface
|
||||||
|
*/
|
||||||
|
class COMBOINPUT_API IComboActionInterface
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
#pragma region EventFunctions
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A way to determine whether the Dialogue can even start.
|
||||||
|
* It does come with Native C++ implementation, which can be overriden in child C++ classes.
|
||||||
|
* ❗ If you are using Blueprint implementation, don't forget to call Parent Node, which contains all parent implementations.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
bool CanStartDialogueEvent() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the owning actor for this Dialogue Participant Component.
|
||||||
|
*
|
||||||
|
* @return The owning actor for this Dialogue Participant Component.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
AActor *GetOwningActor() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the starting node for this Dialogue Participant Component.
|
||||||
|
*
|
||||||
|
* @param NewStartingNode The node to set as the starting node
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
void SaveStartingNode(class UComboActionGraphNode *NewStartingNode);
|
||||||
|
/**
|
||||||
|
* Saves the traversed path for this Dialogue Participant Component.
|
||||||
|
* This function is called once Dialogue ends and is updated from Dialogue Context.
|
||||||
|
*
|
||||||
|
* @param InPath The traversed path of the dialogue graph to be saved.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
void SaveTraversedPath(TMap<FGuid,int32> &InPath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface call.
|
||||||
|
* Retrieves current Dialogue Participant State.
|
||||||
|
* State defines whether Participant can start/close dialogue or not.
|
||||||
|
*
|
||||||
|
* @return ParticipantState Participant state value
|
||||||
|
*/
|
||||||
|
//UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
// EDialogueParticipantState GetState() const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Combo Input|Action")
|
||||||
|
FGameplayTag GetTag() const;
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
#pragma region EventFunctions_Implementations
|
||||||
|
|
||||||
|
bool CanStartDialogueEvent_Implementation() const { return CanStartDialogue(); }
|
||||||
|
|
||||||
|
virtual void SaveStartingNode_Implementation(UComboActionGraphNode *NewStartingNode){}
|
||||||
|
|
||||||
|
virtual AActor *GetOwningActor_Implementation() const { return nullptr; }
|
||||||
|
|
||||||
|
virtual void SaveTraversedPath_Implementation(TMap<FGuid,int32> &InPath){}
|
||||||
|
|
||||||
|
//EDialogueParticipantState GetState_Implementation() const { return GetParticipantState(); }
|
||||||
|
|
||||||
|
FGameplayTag GetTag_Implementation() const { return GetParticipantTag(); }
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
#pragma region Functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the Participant can be start Dialogue.
|
||||||
|
* ❔ To enhance this, you can implement 'CanStartDialogueEvent' and add custom checks to that function.
|
||||||
|
*
|
||||||
|
* @return Whether the dialogue can be started
|
||||||
|
*/
|
||||||
|
virtual bool CanStartDialogue() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the saved starting node for this Dialogue Participant.
|
||||||
|
* ❗ Could be null
|
||||||
|
*
|
||||||
|
* @return The saved starting node, or nullptr if there is none
|
||||||
|
*/
|
||||||
|
virtual UComboActionGraphNode *GetSavedStartingNode() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to play the specified sound as the voice of this dialogue participant.
|
||||||
|
*
|
||||||
|
* @param ParticipantVoice The sound to play as the voice of this dialogue participant
|
||||||
|
*/
|
||||||
|
virtual void PlayParticipantVoice(USoundBase *ParticipantVoice) = 0;
|
||||||
|
/**
|
||||||
|
* Tries to skip the specified sound this participant is playing as voice.
|
||||||
|
*
|
||||||
|
* @param ParticipantVoice The sound to skip this participant is playing as voice.
|
||||||
|
*/
|
||||||
|
virtual void SkipParticipantVoice(USoundBase *ParticipantVoice) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the dialogue graph assigned to this Participant.
|
||||||
|
* ❔ Could be updated using 'SetDialogueGraph', providing ability to swith Dialogue graphs on fly
|
||||||
|
* ❗ Could be null
|
||||||
|
*
|
||||||
|
* @return A pointer to the dialogue graph
|
||||||
|
*/
|
||||||
|
virtual class UComboActionGraph *GetDialogueGraph() const = 0;
|
||||||
|
/**
|
||||||
|
* Sets new Dialogue graph for this Participant.
|
||||||
|
* ❗ Should not be null
|
||||||
|
*
|
||||||
|
* @param NewDialogueGraph A pointer to the dialogue graph to be used
|
||||||
|
*/
|
||||||
|
virtual void SetDialogueGraph(class UComboActionGraph *NewDialogueGraph) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current state of the Dialogue Participant.
|
||||||
|
*/
|
||||||
|
//virtual EDialogueParticipantState GetParticipantState() const = 0;
|
||||||
|
/**
|
||||||
|
* Sets the state of the dialogue participant to the given state.
|
||||||
|
*
|
||||||
|
* @param NewState The new state to set the dialogue participant to
|
||||||
|
*/
|
||||||
|
//virtual void SetParticipantState(const EDialogueParticipantState NewState) = 0;
|
||||||
|
/**
|
||||||
|
* Returns the default state of the Dialogue Participant.
|
||||||
|
*/
|
||||||
|
//virtual EDialogueParticipantState GetDefaultParticipantState() const = 0;
|
||||||
|
/**
|
||||||
|
* Sets the Default state of the dialogue participant to the given state.
|
||||||
|
*
|
||||||
|
* @param NewState The new state to set the dialogue participant to
|
||||||
|
*/
|
||||||
|
//virtual void SetDefaultParticipantState(const EDialogueParticipantState NewState) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the audio component used to play the participant voices.
|
||||||
|
* ❗ Could be null
|
||||||
|
*/
|
||||||
|
virtual UAudioComponent *GetAudioComponent() const = 0;
|
||||||
|
/**
|
||||||
|
* Sets the audio component used to play dialogue audio.
|
||||||
|
*
|
||||||
|
* @param NewAudioComponent The new audio component to use for dialogue audio.
|
||||||
|
*/
|
||||||
|
virtual void SetAudioComponent(UAudioComponent *NewAudioComponent) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the map of nodes traversed during the dialogue.
|
||||||
|
*
|
||||||
|
* @return The map of nodes traversed during the dialogue.
|
||||||
|
*/
|
||||||
|
virtual TMap<FGuid,int32> GetTraversedPath() const = 0;
|
||||||
|
|
||||||
|
virtual FGameplayTag GetParticipantTag() const = 0;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region EventHandles
|
||||||
|
|
||||||
|
//virtual FDialogueGraphChanged &GetDialogueGraphChangedEventHandle() = 0;
|
||||||
|
//virtual FDialogueParticipantStateChanged &GetDialogueParticipantStateChangedEventHandle() = 0;
|
||||||
|
//virtual FDialogueParticipantAudioComponentChanged &GetDialogueParticipantAudioComponentChangedEventHandle() = 0;
|
||||||
|
//virtual FParticipantStartingNodeSaved &GetParticipantStartingNodeSavedEventHandle() = 0;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
};
|
||||||
40
Source/ComboInput/Public/Nodes/ComboActionGraphEdge.h
Normal file
40
Source/ComboInput/Public/Nodes/ComboActionGraphEdge.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraphEdge.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combo Action edges.
|
||||||
|
*
|
||||||
|
* Currently those edges are just connecting objects with no advanced logic.
|
||||||
|
*/
|
||||||
|
UCLASS(ClassGroup=("Combo Input|Action"), NotBlueprintType)
|
||||||
|
class COMBOINPUT_API UComboActionGraphEdge : public UObject
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
#pragma region Variables
|
||||||
|
public:
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, Category="Combo Input|Action")
|
||||||
|
UComboActionGraph *Graph = nullptr;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
UComboActionGraphNode *StartNode = nullptr;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
UComboActionGraphNode *EndNode = nullptr;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Functions
|
||||||
|
public:
|
||||||
|
//UFUNCTION(BlueprintPure, Category="Combo Input|Action")
|
||||||
|
UComboActionGraph *GetGraph() const { return Graph; }
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
};
|
||||||
397
Source/ComboInput/Public/Nodes/ComboActionGraphNode.h
Normal file
397
Source/ComboInput/Public/Nodes/ComboActionGraphNode.h
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Decorators/ComboActionDecoratorBase.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraphNode.generated.h"
|
||||||
|
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(LogComboActionGraphNode, Log, All);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combo Action graph Node abstract base class.
|
||||||
|
*
|
||||||
|
* Provides generic functionality to be enhanced or overriden by Child Classes.
|
||||||
|
* Does come with ability to define Colours, Name, Description and Title.
|
||||||
|
* Contains information about Parent and Children Nodes.
|
||||||
|
*/
|
||||||
|
UCLASS(Abstract, BlueprintType, ClassGroup=("Combo Input|Action"), AutoExpandCategories=("Combo Input", "Action", "Combo Input|Action"))
|
||||||
|
class COMBOINPUT_API UComboActionGraphNode : public UObject
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UComboActionGraphNode();
|
||||||
|
|
||||||
|
#pragma region Variables
|
||||||
|
|
||||||
|
#pragma region ReadOnly
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Array of parent nodes for the current active node in the combo string.
|
||||||
|
*❗ Parent nodes are nodes that have a directed edge pointing to the current active node.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Private")
|
||||||
|
TArray<class UComboActionGraphNode*> ParentNodes;
|
||||||
|
/**
|
||||||
|
* The array of child nodes of the current dialogue node.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Private")
|
||||||
|
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.
|
||||||
|
*❔ Can be used to traverse the graph, get information about node connections...
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Private")
|
||||||
|
TMap<class UComboActionGraphNode*, class UComboActionGraphEdge*> Edges;
|
||||||
|
/**
|
||||||
|
* Pointer to the parent dialogue graph of this node.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Private", meta=(DisplayThumbnail=false))
|
||||||
|
TObjectPtr<class UComboActionGraph> Graph;
|
||||||
|
/**
|
||||||
|
* Temporary NodeIndex.
|
||||||
|
* This variable will be deleted.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Private")
|
||||||
|
int32 NodeIndex = INDEX_NONE;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* The unique identifier for this Dialogue Graph Node.
|
||||||
|
*❗ This is used to differentiate between nodes, and must be unique within the graph.
|
||||||
|
*❔ Can be used for debugging and tracing purposes.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Private")
|
||||||
|
FGuid NodeGUID;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* The world that owns this Dialogue Graph Node.
|
||||||
|
*❗ This is the world in which this Dialogue Graph Node is currently running.
|
||||||
|
*❔ Can be used for accessing world-related functionality.
|
||||||
|
*/
|
||||||
|
UPROPERTY(VisibleAnywhere, Category="Private")
|
||||||
|
TObjectPtr<UWorld> OwningWorld;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Editable
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* The array of allowed input classes for this Dialogue Node.
|
||||||
|
*❗ Only nodes with classes from this array can be connected as inputs to this node.
|
||||||
|
*❔ Can be used to restrict the types of inputs this node can accept.
|
||||||
|
*/
|
||||||
|
UPROPERTY(SaveGame, EditDefaultsOnly, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
TArray<TSubclassOf<class UComboActionGraphNode>> AllowedInputClasses;
|
||||||
|
|
||||||
|
/** Defines whether this Node will start automatically or if requires input.*/
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
uint8 bAutoStarts : 1;
|
||||||
|
/**
|
||||||
|
* The maximum number of children nodes that this node can have.
|
||||||
|
*❗ If this value is -1, then there is no limit on the number of children nodes.
|
||||||
|
*❔ Can be used to enforce a maximum number of connections for certain types of nodes.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category="Combo Input|Action")
|
||||||
|
int32 MaxChildrenNodes = -1;
|
||||||
|
/**
|
||||||
|
* Indicates whether this node inherits the decorators from its parent Graph.
|
||||||
|
*❗ If true, the decorators of the parent Graph will be inherited and applied to this node during processing.
|
||||||
|
*❔ This flag can be used to control the inheritance of decorators for nodes in the dialogue graph.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Combo Input|Action")
|
||||||
|
uint8 bInheritGraphDecorators : 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of Decorators that can help out with enhancing the Dialogue flow.
|
||||||
|
* Those Decorators are instanced and exist only as "triggers".
|
||||||
|
* Could be used to start audio, play animation or do some logic behind the curtains, like triggering Cutscene etc.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Combo Input|Action", NoClear, meta=(NoResetToDefault))
|
||||||
|
TArray<FComboActionDecorator> NodeDecorators;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Functions
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Initializes the node with the given world.
|
||||||
|
*
|
||||||
|
* @param InWorld The world to use for initialization.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, Category = "Combo Input|Action")
|
||||||
|
void InitializeNode(UWorld *InWorld);
|
||||||
|
virtual void InitializeNode_Implementation(UWorld *InWorld);
|
||||||
|
/**
|
||||||
|
* Checks if the node should automatically start when the dialogue is played.
|
||||||
|
* @return true if the node should automatically start, false otherwise.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
virtual bool DoesAutoStart() const { return bAutoStarts; }
|
||||||
|
|
||||||
|
virtual void PreProcessNode(){}
|
||||||
|
virtual void ProcessNode();
|
||||||
|
/**
|
||||||
|
* Gets the decorators for this Dialogue Graph Node.
|
||||||
|
*❔ Returns only Valid decorators!
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
TArray<FComboActionDecorator> GetNodeDecorators() const;
|
||||||
|
/**
|
||||||
|
* Returns true if the node can be started.
|
||||||
|
*❗ The implementation of this function is up to the subclass.
|
||||||
|
*❔ Can be used to validate if a node can be started before attempting to start it.
|
||||||
|
*❔ This can be further enhanced by Decorators.
|
||||||
|
* @return True if the node can be started, false otherwise.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
virtual bool CanStartNode() const;
|
||||||
|
virtual bool EvaluateDecorators() const;
|
||||||
|
/**
|
||||||
|
* Returns whether this node inherits decorators from the dialogue graph.
|
||||||
|
* If this is set to true, this node will receive all decorators assigned to the graph.
|
||||||
|
* If it's set to false, the node will only have its own decorators.
|
||||||
|
*
|
||||||
|
* @return Whether this node inherits decorators from the graph.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
bool DoesInheritDecorators() const { return bInheritGraphDecorators; }
|
||||||
|
/**
|
||||||
|
* Returns how many Children Nodes this Node allows to have.
|
||||||
|
*❔ -1 means no limits.
|
||||||
|
*
|
||||||
|
* @return MaxChildrenNodes
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
int32 GetMaxChildNodes() const { return MaxChildrenNodes; }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the index of the node within the dialogue graph.
|
||||||
|
*
|
||||||
|
* @return The index of the node.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
FORCEINLINE int32 GetNodeIndex() const { return NodeIndex; }
|
||||||
|
/**
|
||||||
|
* Sets the index of this dialogue node in the dialogue graph.
|
||||||
|
*
|
||||||
|
* @param NewIndex The new index to set.
|
||||||
|
*/
|
||||||
|
void SetNodeIndex(const int32 NewIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the GUID of the node.
|
||||||
|
*
|
||||||
|
* @return The GUID of the node.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
FORCEINLINE FGuid GetNodeGUID() const { return NodeGUID; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the owning Graph of the node.
|
||||||
|
*❗ Might be null
|
||||||
|
*
|
||||||
|
* @return The owning Graph of the node.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Combo Input|Action")
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="Combo Input|Action")
|
||||||
|
bool ValidateNodeRuntime() const;
|
||||||
|
virtual bool ValidateNodeRuntime_Implementation() const { return true; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FORCEINLINE ULevel* GetLevel() const { return GetTypedOuter<ULevel>(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a way to update Node's owning World.
|
||||||
|
* Useful for Loading sub-levels.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category="Combo Input|Action")
|
||||||
|
virtual void SetNewWorld(UWorld* NewWorld);
|
||||||
|
virtual UWorld* GetWorld() const override
|
||||||
|
{
|
||||||
|
if (OwningWorld) return OwningWorld;
|
||||||
|
|
||||||
|
// CDO objects do not belong to a world
|
||||||
|
// If the actors outer is destroyed or unreachable we are shutting down and the world should be nullptr
|
||||||
|
if (
|
||||||
|
!HasAnyFlags(RF_ClassDefaultObject) && ensureMsgf(GetOuter(), TEXT("Actor: %s has a null OuterPrivate in AActor::GetWorld()"), *GetFullName())
|
||||||
|
&& !GetOuter()->HasAnyFlags(RF_BeginDestroyed) && !GetOuter()->IsUnreachable()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (ULevel* Level = GetLevel())
|
||||||
|
{
|
||||||
|
return Level->OwningWorld;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
#if WITH_EDITORONLY_DATA
|
||||||
|
|
||||||
|
// Defines whether this Node type allows inputs
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
bool bAllowInputNodes;
|
||||||
|
|
||||||
|
// Defines whether this Node type allows outputs
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
bool bAllowOutputNodes;
|
||||||
|
|
||||||
|
// Defines whether this Node can be copied
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
bool bAllowCopy;
|
||||||
|
|
||||||
|
// Defines whether this Node can be cut
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
bool bAllowCut;
|
||||||
|
|
||||||
|
// Defines whether this Node can be pasted
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
bool bAllowPaste;
|
||||||
|
|
||||||
|
// Defines whether this Node can be deleted
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
bool bAllowDelete;
|
||||||
|
|
||||||
|
// Defines whether this Node can be manually created
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
bool bAllowManualCreate;
|
||||||
|
|
||||||
|
// Display title of the Node
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
FText NodeTitle;
|
||||||
|
|
||||||
|
// Display name of the Node menu category
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
FText ContextMenuName;
|
||||||
|
|
||||||
|
// List of compatible graph types
|
||||||
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Editor")
|
||||||
|
TSubclassOf<UObject> CompatibleGraphType;
|
||||||
|
|
||||||
|
// Defines background colour of this Node
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
FLinearColor BackgroundColor;
|
||||||
|
|
||||||
|
// Contains Node Tooltip text
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
FText NodeTooltipText;
|
||||||
|
|
||||||
|
// User friendly node type name
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Editor")
|
||||||
|
FText NodeTypeName;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tooltip text for this graph node.
|
||||||
|
*
|
||||||
|
* @return The tooltip text for this node.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Combo Input|Action", meta=(DevelopmentOnly=true))
|
||||||
|
FText GetNodeTooltipText() const;
|
||||||
|
virtual FText GetNodeTooltipText_Implementation() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Title text for this graph node.
|
||||||
|
*
|
||||||
|
* @return The Title text for this node.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Combo Input|Action", meta=(DevelopmentOnly=true))
|
||||||
|
FText GetNodeTitle() const;
|
||||||
|
virtual FText GetNodeTitle_Implementation() const { return this->NodeTitle; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Description text for this graph node.
|
||||||
|
*
|
||||||
|
* @return The Description text for this node.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Combo Input|Action", meta=(DevelopmentOnly=true))
|
||||||
|
FText GetDescription() const;
|
||||||
|
virtual FText GetDescription_Implementation() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Node Category text for this graph node.
|
||||||
|
*
|
||||||
|
* @return The Node Category text for this node.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Combo Input|Action", meta=(DevelopmentOnly=true))
|
||||||
|
FText GetNodeCategory() const;
|
||||||
|
virtual FText GetNodeCategory_Implementation() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Documentation Link for this graph node.
|
||||||
|
*
|
||||||
|
* @return The Documentation Link for this node.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Combo Input|Action", meta=(DevelopmentOnly=true))
|
||||||
|
FString GetNodeDocumentationLink() const;
|
||||||
|
virtual FString GetNodeDocumentationLink_Implementation() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Background Colour for this graph node.
|
||||||
|
*
|
||||||
|
* @return The Background Colour for this node.
|
||||||
|
*/
|
||||||
|
virtual FLinearColor GetBackgroundColor() const { return this->BackgroundColor; }
|
||||||
|
FText GetInternalName() const { return this->NodeTypeName; }
|
||||||
|
|
||||||
|
// Allows setting up the Node Title
|
||||||
|
virtual void SetNodeTitle(const FText &NewTitle) { this->NodeTitle = NewTitle; }
|
||||||
|
|
||||||
|
// Allows advanced filtering if Node can be connected from other Node
|
||||||
|
virtual bool CanCreateConnection(UComboActionGraphNode *Other, enum EEdGraphPinDirection Direction, FText& ErrorMessage);
|
||||||
|
|
||||||
|
// Validation function responsible for generating user friendly validation messages
|
||||||
|
virtual bool ValidateNode(TArray<FText> &ValidationsMessages, const bool RichFormat);
|
||||||
|
|
||||||
|
// Once Node is pasted, this function is called
|
||||||
|
virtual void OnPasted();
|
||||||
|
|
||||||
|
// Generates default Tooltip body text used for all Nodes
|
||||||
|
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Combo Input|Action", meta=(DevelopmentOnly=true))
|
||||||
|
FText GetDefaultTooltipBody() const;
|
||||||
|
virtual void OnCreatedInEditor() {};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
@ -0,0 +1,126 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "Engine/DataTable.h"
|
||||||
|
//#include "Helpers/ComboActionGraphHelpers.h"
|
||||||
|
#include "Nodes/ComboActionGraphNode.h"
|
||||||
|
#include "UObject/Object.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraphNode_ActionNodeBase.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combo Action Graph Node abstract Base class.
|
||||||
|
*
|
||||||
|
* Enhances 'ComboActionGraphNode' Base class with action data.
|
||||||
|
*/
|
||||||
|
UCLASS(Abstract, ClassGroup=("Combo Input|Action"), AutoExpandCategories=("Combo Input", "Action", "Combo Input|Action"))
|
||||||
|
class COMBOINPUT_API UComboActionGraphNode_ActionNodeBase : public UComboActionGraphNode
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UComboActionGraphNode_ActionNodeBase();
|
||||||
|
|
||||||
|
virtual void ProcessNode() override;
|
||||||
|
virtual void PreProcessNode() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Dialogue Data Table for this graph node.
|
||||||
|
* ❗ Might be null
|
||||||
|
*
|
||||||
|
* @return The Dialogue Data Table for this graph node.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
virtual UDataTable *GetDataTable() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Dialogue Data Row name.
|
||||||
|
* ❗ Might be invalid
|
||||||
|
*
|
||||||
|
* @return The Dialogue Data Row name.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Combo Input|Action")
|
||||||
|
virtual FName GetRowName() const { return RowName; }
|
||||||
|
|
||||||
|
virtual bool ValidateNodeRuntime_Implementation() const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
#if WITH_EDITORONLY_DATA
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows read-only Texts with localization of selected Dialogue Row.
|
||||||
|
*/
|
||||||
|
UPROPERTY(Transient, VisibleAnywhere, Category="Base", meta=(MultiLine=true, ShowOnlyInnerProperties))
|
||||||
|
TArray<FText> Preview;
|
||||||
|
|
||||||
|
FSimpleDelegate PreviewsUpdated;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data table containing the dialogue rows.
|
||||||
|
* ❗ Strongly suggested to use 'DialogueRow' based Data Tables
|
||||||
|
*/
|
||||||
|
UPROPERTY(SaveGame, Category="Combo Input|Action", EditAnywhere, BlueprintReadOnly, meta=(DisplayThumbnail=false, NoResetToDefault))
|
||||||
|
UDataTable *DataTable;
|
||||||
|
|
||||||
|
/** Name of row in the table that we want */
|
||||||
|
UPROPERTY(SaveGame, Category="Combo Input|Action", EditAnywhere, BlueprintReadOnly, meta=(GetOptions ="GetRowNames", NoResetToDefault, EditCondition="DataTable!=nullptr"))
|
||||||
|
FName RowName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag defining how the Participant is searched for.
|
||||||
|
* Default: False
|
||||||
|
*
|
||||||
|
* If True:
|
||||||
|
* * Participant will be found by its Gameplay Tag, compared to Dialogue Row Data.
|
||||||
|
* * ❗Only exact match is considered success
|
||||||
|
* * ❗ First found is used, so use unique Tags when working with multiple Participants (Player01, Player02, NPC.Andrew etc.)
|
||||||
|
*
|
||||||
|
* If False:
|
||||||
|
* * Participant will be found using Node Type
|
||||||
|
* * Lead Node will use NPC
|
||||||
|
* * Answer Node will use Player
|
||||||
|
* * ❗ This system will be deprecated
|
||||||
|
*
|
||||||
|
* ❗ New feature in version 1.0.5.X.
|
||||||
|
* ❔ Each unique dialogue Participant should be using different Tag, if generic, then use something like `Dialogue.NPC`
|
||||||
|
*/
|
||||||
|
UPROPERTY(SaveGame, Category="Combo Input|Action", EditAnywhere, BlueprintReadOnly, meta=(NoResetToDefault))
|
||||||
|
uint8 bUseGameplayTags : 1;
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
|
||||||
|
virtual bool ValidateNode(TArray<FText>& ValidationsMessages, const bool RichFormat) override;
|
||||||
|
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||||
|
virtual FText GetDescription_Implementation() const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TArray<FText> GetPreviews() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WITH_EDITORONLY_DATA
|
||||||
|
public:
|
||||||
|
virtual void UpdatePreviews();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
TArray<FName> GetRowNames() const
|
||||||
|
{
|
||||||
|
if (DataTable)
|
||||||
|
{
|
||||||
|
return DataTable->GetRowNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
return TArray<FName>();
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "Nodes/ComboActionGraphNode.h"
|
||||||
|
#include "UObject/Object.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraphNode_StartNode.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combo Action Start Node.
|
||||||
|
*
|
||||||
|
* This Node will be added to the graph automatically when created.
|
||||||
|
* This node cannot be created manually.
|
||||||
|
* This node cannot be deleted.
|
||||||
|
* Does not implement any logic.
|
||||||
|
*/
|
||||||
|
UCLASS(ClassGroup=("Combo Input|Action"), DisplayName="Start Node", meta=(ToolTip="Combo Action Tree: Start Node"))
|
||||||
|
class COMBOINPUT_API UComboActionGraphNode_StartNode : public UComboActionGraphNode
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
UComboActionGraphNode_StartNode();
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
virtual FText GetDescription_Implementation() const override;
|
||||||
|
|
||||||
|
virtual bool ValidateNode(TArray<FText>& ValidationsMessages, const bool RichFormat);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
@ -27,7 +27,8 @@ public class ComboInputEditor : ModuleRules
|
|||||||
"CoreUObject",
|
"CoreUObject",
|
||||||
"AssetTools",
|
"AssetTools",
|
||||||
"SlateCore",
|
"SlateCore",
|
||||||
"Projects"
|
"Projects",
|
||||||
|
"GraphEditor"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
434
Source/ComboInputEditor/Private/ComboActionGraphSchema.cpp
Normal file
434
Source/ComboInputEditor/Private/ComboActionGraphSchema.cpp
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "ComboActionGraphSchema.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraph.h"
|
||||||
|
#include "FConnectionDrawingPolicy_ComboActionGraph.h"
|
||||||
|
#include "GraphEditorActions.h"
|
||||||
|
|
||||||
|
#include "Ed/EdComboActionGraphEdge.h"
|
||||||
|
#include "Ed/EdComboActionGraphNode.h"
|
||||||
|
#include "Framework/Commands/GenericCommands.h"
|
||||||
|
#include "Nodes/ComboActionGraphEdge.h"
|
||||||
|
#include "Nodes/ComboActionGraphNode.h"
|
||||||
|
|
||||||
|
#define LOCTEXT_NAMESPACE "ComboActionGraph"
|
||||||
|
|
||||||
|
|
||||||
|
UEdGraphNode *FAssetSchemaAction_ComboActionGraphSchema_NewNode::PerformAction(UEdGraph *ParentGraph, UEdGraphPin *FromPin, const FVector2D Location, bool bSelectNewNode)
|
||||||
|
{
|
||||||
|
UEdGraphNode *ResultNode = nullptr;
|
||||||
|
|
||||||
|
if (NodeTemplate != nullptr)
|
||||||
|
{
|
||||||
|
const FScopedTransaction Transaction(LOCTEXT("ComboActionGraphEditorNewNode", "Combo Action Graph Editor: New Node"));
|
||||||
|
ParentGraph->Modify();
|
||||||
|
if (FromPin != nullptr)
|
||||||
|
FromPin->Modify();
|
||||||
|
|
||||||
|
NodeTemplate->Rename(nullptr, ParentGraph);
|
||||||
|
ParentGraph->AddNode(NodeTemplate, true, bSelectNewNode);
|
||||||
|
|
||||||
|
NodeTemplate->CreateNewGuid();
|
||||||
|
NodeTemplate->PostPlacedNewNode();
|
||||||
|
NodeTemplate->AllocateDefaultPins();
|
||||||
|
NodeTemplate->AutowireNewNode(FromPin);
|
||||||
|
|
||||||
|
NodeTemplate->NodePosX = Location.X;
|
||||||
|
NodeTemplate->NodePosY = Location.Y;
|
||||||
|
|
||||||
|
NodeTemplate->ComboActionGraphNode->SetFlags(EObjectFlags::RF_Transactional);
|
||||||
|
NodeTemplate->SetFlags(EObjectFlags::RF_Transactional);
|
||||||
|
|
||||||
|
ResultNode = NodeTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FAssetSchemaAction_ComboActionGraphSchema_NewNode::AddReferencedObjects(FReferenceCollector &Collector)
|
||||||
|
{
|
||||||
|
FEdGraphSchemaAction::AddReferencedObjects(Collector);
|
||||||
|
Collector.AddReferencedObject(NodeTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
UEdGraphNode *FAssetSchemaAction_ComboActionGraphSchema_NewEdge::PerformAction(UEdGraph *ParentGraph, UEdGraphPin *FromPin, const FVector2D Location, bool bSelectNewNode)
|
||||||
|
{
|
||||||
|
UEdGraphNode *ResultNode = nullptr;
|
||||||
|
|
||||||
|
if (NodeTemplate != nullptr)
|
||||||
|
{
|
||||||
|
const FScopedTransaction Transaction(LOCTEXT("ComboActionGraphEditorNewEdge", "Combo Action Graph Editor: New Edge"));
|
||||||
|
ParentGraph->Modify();
|
||||||
|
if (FromPin != nullptr)
|
||||||
|
FromPin->Modify();
|
||||||
|
|
||||||
|
NodeTemplate->Rename(nullptr, ParentGraph);
|
||||||
|
ParentGraph->AddNode(NodeTemplate, true, bSelectNewNode);
|
||||||
|
|
||||||
|
NodeTemplate->CreateNewGuid();
|
||||||
|
NodeTemplate->PostPlacedNewNode();
|
||||||
|
NodeTemplate->AllocateDefaultPins();
|
||||||
|
NodeTemplate->AutowireNewNode(FromPin);
|
||||||
|
|
||||||
|
NodeTemplate->NodePosX = Location.X;
|
||||||
|
NodeTemplate->NodePosY = Location.Y;
|
||||||
|
|
||||||
|
NodeTemplate->ComboActionGraphEdge->SetFlags(EObjectFlags::RF_Transactional);
|
||||||
|
NodeTemplate->SetFlags(EObjectFlags::RF_Transactional);
|
||||||
|
|
||||||
|
ResultNode = NodeTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FAssetSchemaAction_ComboActionGraphSchema_NewEdge::AddReferencedObjects(FReferenceCollector &Collector)
|
||||||
|
{
|
||||||
|
FEdGraphSchemaAction::AddReferencedObjects(Collector);
|
||||||
|
Collector.AddReferencedObject(NodeTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UComboActionGraphSchema::GetBreakLinkToSubMenuActions(UToolMenu *Menu, UEdGraphPin *InGraphPin)
|
||||||
|
{
|
||||||
|
// Make sure we have a unique name for every entry in the list
|
||||||
|
TMap<FString, uint32> LinkTitleCount;
|
||||||
|
|
||||||
|
FToolMenuSection &Section = Menu->FindOrAddSection("ComboActionGraphAssetGraphSchemaPinActions");
|
||||||
|
|
||||||
|
// Add all the links we could break from
|
||||||
|
for (TArray<class UEdGraphPin*>::TConstIterator Links(InGraphPin->LinkedTo); Links; ++Links)
|
||||||
|
{
|
||||||
|
UEdGraphPin* Pin = *Links;
|
||||||
|
FString TitleString = Pin->GetOwningNode()->GetNodeTitle(ENodeTitleType::ListView).ToString();
|
||||||
|
FText Title = FText::FromString(TitleString);
|
||||||
|
if (Pin->PinName != TEXT(""))
|
||||||
|
{
|
||||||
|
TitleString = FString::Printf(TEXT("%s (%s)"), *TitleString, *Pin->PinName.ToString());
|
||||||
|
|
||||||
|
// Add name of connection if possible
|
||||||
|
FFormatNamedArguments Args;
|
||||||
|
Args.Add(TEXT("NodeTitle"), Title);
|
||||||
|
Args.Add(TEXT("PinName"), Pin->GetDisplayName());
|
||||||
|
Title = FText::Format(LOCTEXT("BreakDescPin", "{NodeTitle} ({PinName})"), Args);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32& Count = LinkTitleCount.FindOrAdd(TitleString);
|
||||||
|
|
||||||
|
FText Description;
|
||||||
|
FFormatNamedArguments Args;
|
||||||
|
Args.Add(TEXT("NodeTitle"), Title);
|
||||||
|
Args.Add(TEXT("NumberOfNodes"), Count);
|
||||||
|
|
||||||
|
if (Count == 0)
|
||||||
|
{
|
||||||
|
Description = FText::Format(LOCTEXT("BreakDesc", "Break link to {NodeTitle}"), Args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Description = FText::Format(LOCTEXT("BreakDescMulti", "Break link to {NodeTitle} ({NumberOfNodes})"), Args);
|
||||||
|
}
|
||||||
|
++Count;
|
||||||
|
|
||||||
|
Section.AddMenuEntry(NAME_None, Description, Description, FSlateIcon(), FUIAction(
|
||||||
|
FExecuteAction::CreateUObject(this, &UComboActionGraphSchema::BreakSinglePinLink, const_cast<UEdGraphPin*>(InGraphPin), *Links)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphSchema::GetGraphContextActions(FGraphContextMenuBuilder &ContextMenuBuilder) const
|
||||||
|
{
|
||||||
|
UComboActionGraph *Graph = CastChecked<UComboActionGraph>(ContextMenuBuilder.CurrentGraph->GetOuter());
|
||||||
|
|
||||||
|
if (Graph->NodeType == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool bNoParent = (ContextMenuBuilder.FromPin == NULL);
|
||||||
|
|
||||||
|
FText AddToolTip = LOCTEXT("NewMoutneaDialogueGraphNodeTooltip", "Add Dialogue Node here");
|
||||||
|
|
||||||
|
TSet<TSubclassOf<UComboActionGraphNode>> Visited;
|
||||||
|
|
||||||
|
FText Desc = Graph->NodeType.GetDefaultObject()->ContextMenuName;
|
||||||
|
FText NodeCategory = Graph->NodeType.GetDefaultObject()->GetNodeCategory();
|
||||||
|
|
||||||
|
if (Desc.IsEmpty())
|
||||||
|
{
|
||||||
|
FString Title = Graph->NodeType->GetName();
|
||||||
|
Title.RemoveFromEnd("_C");
|
||||||
|
Desc = FText::FromString(Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Graph->NodeType->HasAnyClassFlags(CLASS_Abstract))
|
||||||
|
{
|
||||||
|
TSharedPtr<FAssetSchemaAction_ComboActionGraphSchema_NewNode> NewNodeAction(new FAssetSchemaAction_ComboActionGraphSchema_NewNode(NodeCategory, Desc, AddToolTip, 0));
|
||||||
|
NewNodeAction->NodeTemplate = NewObject<UEdComboActionGraphNode>(ContextMenuBuilder.OwnerOfTemporaries);
|
||||||
|
NewNodeAction->NodeTemplate->ComboActionGraphNode = NewObject<UComboActionGraphNode>(NewNodeAction->NodeTemplate, Graph->NodeType);
|
||||||
|
NewNodeAction->NodeTemplate->ComboActionGraphNode->Graph = Graph;
|
||||||
|
ContextMenuBuilder.AddAction(NewNodeAction);
|
||||||
|
|
||||||
|
Visited.Add(Graph->NodeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TObjectIterator<UClass> It; It; ++It)
|
||||||
|
{
|
||||||
|
if (It->IsChildOf(Graph->NodeType) && !It->HasAnyClassFlags(CLASS_Abstract) && !Visited.Contains(*It))
|
||||||
|
{
|
||||||
|
TSubclassOf<UComboActionGraphNode> NodeType = *It;
|
||||||
|
|
||||||
|
if (It->GetName().StartsWith("REINST") || It->GetName().StartsWith("SKEL"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!Graph->GetClass()->IsChildOf(NodeType.GetDefaultObject()->CompatibleGraphType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!NodeType.GetDefaultObject()->bAllowManualCreate)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Desc = NodeType.GetDefaultObject()->ContextMenuName;
|
||||||
|
AddToolTip = NodeType.GetDefaultObject()->GetDescription();
|
||||||
|
|
||||||
|
NodeCategory = NodeType.GetDefaultObject()->GetNodeCategory();
|
||||||
|
|
||||||
|
if (Desc.IsEmpty())
|
||||||
|
{
|
||||||
|
FString Title = NodeType->GetName();
|
||||||
|
Title.RemoveFromEnd("_C");
|
||||||
|
Desc = FText::FromString(Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
TSharedPtr<FAssetSchemaAction_ComboActionGraphSchema_NewNode> Action(new FAssetSchemaAction_ComboActionGraphSchema_NewNode(NodeCategory, Desc, AddToolTip, 0));
|
||||||
|
Action->NodeTemplate = NewObject<UEdComboActionGraphNode>(ContextMenuBuilder.OwnerOfTemporaries);
|
||||||
|
Action->NodeTemplate->ComboActionGraphNode = NewObject<UComboActionGraphNode>(Action->NodeTemplate, NodeType);
|
||||||
|
Action->NodeTemplate->ComboActionGraphNode->Graph = Graph;
|
||||||
|
ContextMenuBuilder.AddAction(Action);
|
||||||
|
|
||||||
|
Visited.Add(NodeType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphSchema::GetContextMenuActions(UToolMenu* Menu, UGraphNodeContextMenuContext* Context) const
|
||||||
|
{
|
||||||
|
if (Context->Pin)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
FToolMenuSection& Section = Menu->AddSection("ComboActionGraphAssetGraphSchemaNodeActions", LOCTEXT("PinActionsMenuHeader", "Pin Actions"));
|
||||||
|
// Only display the 'Break Links' option if there is a link to break!
|
||||||
|
if (Context->Pin->LinkedTo.Num() > 0)
|
||||||
|
{
|
||||||
|
Section.AddMenuEntry(FGraphEditorCommands::Get().BreakPinLinks);
|
||||||
|
|
||||||
|
// add sub menu for break link to
|
||||||
|
if (Context->Pin->LinkedTo.Num() > 1)
|
||||||
|
{
|
||||||
|
Section.AddSubMenu(
|
||||||
|
"BreakLinkTo",
|
||||||
|
LOCTEXT("BreakLinkTo", "Break Link To..."),
|
||||||
|
LOCTEXT("BreakSpecificLinks", "Break a specific link..."),
|
||||||
|
FNewToolMenuDelegate::CreateUObject((UComboActionGraphSchema *const)this, &UComboActionGraphSchema::GetBreakLinkToSubMenuActions, const_cast<UEdGraphPin*>(Context->Pin)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
((UComboActionGraphSchema *const)this)->GetBreakLinkToSubMenuActions(Menu, const_cast<UEdGraphPin*>(Context->Pin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Context->Node)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
FToolMenuSection& Section = Menu->AddSection("ComboActionGraphAssetGraphSchemaNodeActions", LOCTEXT("ClassActionsMenuHeader", "Node Actions"));
|
||||||
|
Section.AddSeparator(FName(TEXT("Main Options")));
|
||||||
|
Section.AddMenuEntry(FGenericCommands::Get().Rename);
|
||||||
|
Section.AddSeparator(FName(TEXT("Other Options")));
|
||||||
|
Section.AddMenuEntry(FGenericCommands::Get().Delete);
|
||||||
|
Section.AddMenuEntry(FGenericCommands::Get().Cut);
|
||||||
|
Section.AddMenuEntry(FGenericCommands::Get().Copy);
|
||||||
|
Section.AddMenuEntry(FGenericCommands::Get().Duplicate);
|
||||||
|
|
||||||
|
Section.AddMenuEntry(FGraphEditorCommands::Get().BreakNodeLinks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Super::GetContextMenuActions(Menu, Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
const FPinConnectionResponse UComboActionGraphSchema::CanCreateConnection(const UEdGraphPin* A, const UEdGraphPin* B) const
|
||||||
|
{
|
||||||
|
// Make sure the pins are not on the same node
|
||||||
|
if (A->GetOwningNode() == B->GetOwningNode())
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorSameNode", "Both are on the same node"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the directions
|
||||||
|
if ((A->Direction == EGPD_Input) && (B->Direction == EGPD_Input))
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorInput", "Can't connect input node to input node"));
|
||||||
|
}
|
||||||
|
else if ((A->Direction == EGPD_Output) && (B->Direction == EGPD_Output))
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorOutput", "Can't connect output node to output node"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for cycles
|
||||||
|
FComboActionNodeVisitorCycleChecker CycleChecker;
|
||||||
|
if (!CycleChecker.CheckForLoop(A->GetOwningNode(), B->GetOwningNode()))
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorCycle", "Can't create a graph cycle"));
|
||||||
|
}
|
||||||
|
if (!CycleChecker.CheckForLoop(B->GetOwningNode(), A->GetOwningNode()))
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorCycle", "Can't create a graph cycle"));
|
||||||
|
}
|
||||||
|
|
||||||
|
UEdComboActionGraphNode* EdNode_A = Cast<UEdComboActionGraphNode>(A->GetOwningNode());
|
||||||
|
UEdComboActionGraphNode* EdNode_B = Cast<UEdComboActionGraphNode>(B->GetOwningNode());
|
||||||
|
|
||||||
|
if (EdNode_A == nullptr || EdNode_B == nullptr)
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinError", "Not a valid UComboActionGraphEdNode"));
|
||||||
|
}
|
||||||
|
|
||||||
|
FText ErrorMessage;
|
||||||
|
if (A->Direction == EGPD_Input)
|
||||||
|
{
|
||||||
|
if (!EdNode_A->ComboActionGraphNode->CanCreateConnection(EdNode_B->ComboActionGraphNode, EGPD_Input, ErrorMessage))
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!EdNode_B->ComboActionGraphNode->CanCreateConnection(EdNode_A->ComboActionGraphNode, EGPD_Output, ErrorMessage))
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EdNode_A->ComboActionGraphNode->GetGraph()->bEdgeEnabled)
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_MAKE_WITH_CONVERSION_NODE, LOCTEXT("PinConnect", "Connect nodes with edge"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FPinConnectionResponse(CONNECT_RESPONSE_MAKE, LOCTEXT("PinConnect", "Connect nodes"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraphSchema::CreateAutomaticConversionNodeAndConnections(UEdGraphPin* A, UEdGraphPin* B) const
|
||||||
|
{
|
||||||
|
UEdComboActionGraphNode *NodeA = Cast<UEdComboActionGraphNode>(A->GetOwningNode());
|
||||||
|
UEdComboActionGraphNode *NodeB = Cast<UEdComboActionGraphNode>(B->GetOwningNode());
|
||||||
|
|
||||||
|
if (NodeA == nullptr || NodeB == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (NodeA->GetInputPin() == nullptr || NodeA->GetOutputPin() == nullptr || NodeB->GetInputPin() == nullptr || NodeB->GetOutputPin() == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UComboActionGraph* Graph = NodeA->ComboActionGraphNode->GetGraph();
|
||||||
|
|
||||||
|
FVector2D InitPos((NodeA->NodePosX + NodeB->NodePosX) / 2, (NodeA->NodePosY + NodeB->NodePosY) / 2);
|
||||||
|
|
||||||
|
FAssetSchemaAction_ComboActionGraphSchema_NewEdge Action;
|
||||||
|
Action.NodeTemplate = NewObject<UEdComboActionGraphEdge>(NodeA->GetGraph());
|
||||||
|
Action.NodeTemplate->SetEdge(NewObject<UComboActionGraphEdge>(Action.NodeTemplate, Graph->EdgeType));
|
||||||
|
UEdComboActionGraphEdge *EdgeNode = Cast<UEdComboActionGraphEdge>(Action.PerformAction(NodeA->GetGraph(), nullptr, InitPos, false));
|
||||||
|
|
||||||
|
if (A->Direction == EEdGraphPinDirection::EGPD_Output)
|
||||||
|
{
|
||||||
|
EdgeNode->CreateConnections(NodeA, NodeB);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EdgeNode->CreateConnections(NodeB, NodeA);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FConnectionDrawingPolicy *UComboActionGraphSchema::CreateConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float InZoomFactor, const FSlateRect& InClippingRect, FSlateWindowElementList& InDrawElements, UEdGraph* InGraphObj) const
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if (const UMounteaDialogueGraphEditorSettings* MounteaDialogueGraphEditorSettings = GetMutableDefault<UMounteaDialogueGraphEditorSettings>())
|
||||||
|
{
|
||||||
|
if (MounteaDialogueGraphEditorSettings->AllowAdvancedWiring())
|
||||||
|
{
|
||||||
|
return new FConnectionDrawingPolicy_AdvancedMounteaDialogueGraph(InBackLayerID, InFrontLayerID, InZoomFactor, InClippingRect, InDrawElements, InGraphObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return new FConnectionDrawingPolicy_ComboActionGraph(InBackLayerID, InFrontLayerID, InZoomFactor, InClippingRect, InDrawElements, InGraphObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLinearColor UComboActionGraphSchema::GetPinTypeColor(const FEdGraphPinType& PinType) const
|
||||||
|
{
|
||||||
|
return FColor::White;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphSchema::BreakNodeLinks(UEdGraphNode& TargetNode) const
|
||||||
|
{
|
||||||
|
const FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "GraphEd_BreakNodeLinks", "Break Node Links"));
|
||||||
|
|
||||||
|
Super::BreakNodeLinks(TargetNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphSchema::BreakPinLinks(UEdGraphPin& TargetPin, bool bSendsNodeNotifcation) const
|
||||||
|
{
|
||||||
|
const FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "GraphEd_BreakPinLinks", "Break Pin Links"));
|
||||||
|
|
||||||
|
Super::BreakPinLinks(TargetPin, bSendsNodeNotifcation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphSchema::BreakSinglePinLink(UEdGraphPin* SourcePin, UEdGraphPin* TargetPin) const
|
||||||
|
{
|
||||||
|
const FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "GraphEd_BreakSinglePinLink", "Break Pin Link"));
|
||||||
|
|
||||||
|
Super::BreakSinglePinLink(SourcePin, TargetPin);
|
||||||
|
}
|
||||||
|
|
||||||
|
UEdGraphPin *UComboActionGraphSchema::DropPinOnNode(UEdGraphNode* InTargetNode, const FName& InSourcePinName, const FEdGraphPinType& InSourcePinType, EEdGraphPinDirection InSourcePinDirection) const
|
||||||
|
{
|
||||||
|
UEdComboActionGraphNode* EdNode = Cast<UEdComboActionGraphNode>(InTargetNode);
|
||||||
|
switch (InSourcePinDirection)
|
||||||
|
{
|
||||||
|
case EEdGraphPinDirection::EGPD_Input:
|
||||||
|
return EdNode->GetOutputPin();
|
||||||
|
case EEdGraphPinDirection::EGPD_Output:
|
||||||
|
return EdNode->GetInputPin();
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraphSchema::SupportsDropPinOnNode(UEdGraphNode* InTargetNode, const FEdGraphPinType& InSourcePinType, EEdGraphPinDirection InSourcePinDirection, FText& OutErrorMessage) const
|
||||||
|
{
|
||||||
|
return Cast<UEdComboActionGraphNode>(InTargetNode) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UComboActionGraphSchema::IsCacheVisualizationOutOfDate(int32 InVisualizationCacheID) const
|
||||||
|
{
|
||||||
|
return CurrentCacheRefreshID != InVisualizationCacheID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 UComboActionGraphSchema::GetCurrentVisualizationCacheID() const
|
||||||
|
{
|
||||||
|
return CurrentCacheRefreshID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphSchema::ForceVisualizationCacheClear() const
|
||||||
|
{
|
||||||
|
CurrentCacheRefreshID++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UComboActionGraphSchema::CreateDefaultNodesForGraph(UEdGraph& Graph) const
|
||||||
|
{
|
||||||
|
Super::CreateDefaultNodesForGraph(Graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef LOCTEXT_NAMESPACE
|
||||||
164
Source/ComboInputEditor/Private/ComboActionGraphSchema.h
Normal file
164
Source/ComboInputEditor/Private/ComboActionGraphSchema.h
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraphSchema.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
class FComboActionNodeVisitorCycleChecker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Check whether a loop in the graph would be caused by linking the passed-in nodes */
|
||||||
|
bool CheckForLoop(UEdGraphNode *StartNode, UEdGraphNode *EndNode)
|
||||||
|
{
|
||||||
|
VisitedNodes.Add(StartNode);
|
||||||
|
|
||||||
|
if (!QuiCheckDirectConnections(StartNode, EndNode))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TraverseInputNodesToRoot(EndNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool TraverseInputNodesToRoot(UEdGraphNode *Node)
|
||||||
|
{
|
||||||
|
VisitedNodes.Add(Node);
|
||||||
|
|
||||||
|
for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex)
|
||||||
|
{
|
||||||
|
UEdGraphPin *MyPin = Node->Pins[PinIndex];
|
||||||
|
|
||||||
|
if (MyPin->Direction == EGPD_Output)
|
||||||
|
{
|
||||||
|
for (int32 LinkedPinIndex = 0; LinkedPinIndex < MyPin->LinkedTo.Num(); ++LinkedPinIndex)
|
||||||
|
{
|
||||||
|
UEdGraphPin *OtherPin = MyPin->LinkedTo[LinkedPinIndex];
|
||||||
|
if (OtherPin)
|
||||||
|
{
|
||||||
|
UEdGraphNode *OtherNode = OtherPin->GetOwningNode();
|
||||||
|
if (VisitedNodes.Contains(OtherNode))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return TraverseInputNodesToRoot(OtherNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QuiCheckDirectConnections(UEdGraphNode *A, UEdGraphNode *B)
|
||||||
|
{
|
||||||
|
for (auto Itr : B->Pins)
|
||||||
|
{
|
||||||
|
if (A->Pins.Contains(Itr))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto Itr : A->Pins)
|
||||||
|
{
|
||||||
|
if (B->Pins.Contains(Itr))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSet<UEdGraphNode *> VisitedNodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Action to add a node to the graph */
|
||||||
|
USTRUCT()
|
||||||
|
struct FAssetSchemaAction_ComboActionGraphSchema_NewNode : public FEdGraphSchemaAction
|
||||||
|
{
|
||||||
|
GENERATED_BODY();
|
||||||
|
|
||||||
|
public:
|
||||||
|
FAssetSchemaAction_ComboActionGraphSchema_NewNode() : NodeTemplate(nullptr){}
|
||||||
|
|
||||||
|
FAssetSchemaAction_ComboActionGraphSchema_NewNode(const FText &InNodeCategory, const FText &InMenuDesc, const FText &InToolTip, const int32 InGrouping)
|
||||||
|
: FEdGraphSchemaAction(InNodeCategory, InMenuDesc, InToolTip, InGrouping), NodeTemplate(nullptr){}
|
||||||
|
|
||||||
|
virtual UEdGraphNode *PerformAction(class UEdGraph *ParentGraph, UEdGraphPin *FromPin, const FVector2D Location, bool bSelectNewNode = true) override;
|
||||||
|
virtual void AddReferencedObjects(FReferenceCollector &Collector) override;
|
||||||
|
|
||||||
|
class UEdComboActionGraphNode *NodeTemplate;
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT()
|
||||||
|
struct FAssetSchemaAction_ComboActionGraphSchema_NewEdge : public FEdGraphSchemaAction
|
||||||
|
{
|
||||||
|
GENERATED_BODY();
|
||||||
|
|
||||||
|
public:
|
||||||
|
FAssetSchemaAction_ComboActionGraphSchema_NewEdge() : NodeTemplate(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
FAssetSchemaAction_ComboActionGraphSchema_NewEdge(const FText &InNodeCategory, const FText &InMenuDesc, const FText &InToolTip, const int32 InGrouping)
|
||||||
|
: FEdGraphSchemaAction(InNodeCategory, InMenuDesc, InToolTip, InGrouping), NodeTemplate(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual UEdGraphNode *PerformAction(class UEdGraph *ParentGraph, UEdGraphPin *FromPin, const FVector2D Location, bool bSelectNewNode = true) override;
|
||||||
|
virtual void AddReferencedObjects(FReferenceCollector &Collector) override;
|
||||||
|
|
||||||
|
class UEdComboActionGraphEdge *NodeTemplate;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
UCLASS(MinimalAPI)
|
||||||
|
class UComboActionGraphSchema : public UEdGraphSchema
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
void GetBreakLinkToSubMenuActions(class UToolMenu* Menu, class UEdGraphPin* InGraphPin);
|
||||||
|
|
||||||
|
virtual EGraphType GetGraphType(const UEdGraph* TestEdGraph) const override { return EGraphType::GT_StateMachine; }
|
||||||
|
|
||||||
|
virtual void GetGraphContextActions(FGraphContextMenuBuilder& ContextMenuBuilder) const override;
|
||||||
|
|
||||||
|
virtual void GetContextMenuActions(class UToolMenu* Menu, class UGraphNodeContextMenuContext* Context) const override;
|
||||||
|
|
||||||
|
virtual const FPinConnectionResponse CanCreateConnection(const UEdGraphPin* A, const UEdGraphPin* B) const override;
|
||||||
|
|
||||||
|
virtual bool CreateAutomaticConversionNodeAndConnections(UEdGraphPin* A, UEdGraphPin* B) const override;
|
||||||
|
|
||||||
|
virtual class FConnectionDrawingPolicy* CreateConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float InZoomFactor, const FSlateRect& InClippingRect, class FSlateWindowElementList& InDrawElements, class UEdGraph* InGraphObj) const override;
|
||||||
|
|
||||||
|
virtual FLinearColor GetPinTypeColor(const FEdGraphPinType& PinType) const override;
|
||||||
|
|
||||||
|
virtual void BreakNodeLinks(UEdGraphNode& TargetNode) const override;
|
||||||
|
|
||||||
|
virtual void BreakPinLinks(UEdGraphPin& TargetPin, bool bSendsNodeNotifcation) const override;
|
||||||
|
|
||||||
|
virtual void BreakSinglePinLink(UEdGraphPin* SourcePin, UEdGraphPin* TargetPin) const override;
|
||||||
|
|
||||||
|
virtual UEdGraphPin* DropPinOnNode(UEdGraphNode* InTargetNode, const FName& InSourcePinName, const FEdGraphPinType& InSourcePinType, EEdGraphPinDirection InSourcePinDirection) const override;
|
||||||
|
|
||||||
|
virtual bool SupportsDropPinOnNode(UEdGraphNode* InTargetNode, const FEdGraphPinType& InSourcePinType, EEdGraphPinDirection InSourcePinDirection, FText& OutErrorMessage) const override;
|
||||||
|
|
||||||
|
virtual bool IsCacheVisualizationOutOfDate(int32 InVisualizationCacheID) const override;
|
||||||
|
|
||||||
|
virtual int32 GetCurrentVisualizationCacheID() const override;
|
||||||
|
|
||||||
|
virtual void ForceVisualizationCacheClear() const override;
|
||||||
|
|
||||||
|
virtual void CreateDefaultNodesForGraph(UEdGraph& Graph) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static int32 CurrentCacheRefreshID;
|
||||||
|
};
|
||||||
209
Source/ComboInputEditor/Private/Ed/EdComboActionGraph.cpp
Normal file
209
Source/ComboInputEditor/Private/Ed/EdComboActionGraph.cpp
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Ed/EdComboActionGraph.h"
|
||||||
|
|
||||||
|
#include "Ed/EdComboActionGraphEdge.h"
|
||||||
|
#include "Ed/EdComboActionGraphNode.h"
|
||||||
|
#include "ComboActionGraph.h"
|
||||||
|
#include "Nodes/ComboActionGraphNode.h"
|
||||||
|
#include "Nodes/ComboActionGraphEdge.h"
|
||||||
|
//#include "Helpers/MounteaDialogueGraphEditorHelpers.h"
|
||||||
|
//#include "Helpers/MounteaDialogueGraphEditorUtilities.h"
|
||||||
|
//#include "Helpers/MounteaDialogueSystemEditorBFC.h"
|
||||||
|
|
||||||
|
DEFINE_LOG_CATEGORY(LogEdComboActionGraph);
|
||||||
|
|
||||||
|
|
||||||
|
void UEdComboActionGraph::RebuildComboActionGraph()
|
||||||
|
{
|
||||||
|
UE_LOG(LogEdComboActionGraph, Warning, TEXT("UEdComboActionGraph::RebuildComboActionGraph has been called"));
|
||||||
|
|
||||||
|
UComboActionGraph *Graph = GetComboActionGraph();
|
||||||
|
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < Nodes.Num(); ++i)
|
||||||
|
{
|
||||||
|
if (UEdComboActionGraphNode *EdNode = Cast<UEdComboActionGraphNode>(Nodes[i]))
|
||||||
|
{
|
||||||
|
if (EdNode->ComboActionGraphNode == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
UComboActionGraphNode *ComboActionGraphNode = EdNode->ComboActionGraphNode;
|
||||||
|
|
||||||
|
NodeMap.Add(ComboActionGraphNode, EdNode);
|
||||||
|
|
||||||
|
Graph->AllNodes.Add(ComboActionGraphNode);
|
||||||
|
|
||||||
|
//EdNode->SetDialogueNodeIndex( Graph->AllNodes.Find(EdNode->ComboActionGraphNode) );
|
||||||
|
|
||||||
|
for (int PinIdx = 0; PinIdx < EdNode->Pins.Num(); ++PinIdx)
|
||||||
|
{
|
||||||
|
UEdGraphPin* Pin = EdNode->Pins[PinIdx];
|
||||||
|
|
||||||
|
if (Pin->Direction != EEdGraphPinDirection::EGPD_Output)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int LinkToIdx = 0; LinkToIdx < Pin->LinkedTo.Num(); ++LinkToIdx)
|
||||||
|
{
|
||||||
|
UComboActionGraphNode *ChildNode = nullptr;
|
||||||
|
if (UEdComboActionGraphNode *EdNode_Child = Cast<UEdComboActionGraphNode>(Pin->LinkedTo[LinkToIdx]->GetOwningNode()))
|
||||||
|
{
|
||||||
|
ChildNode = EdNode_Child->ComboActionGraphNode;
|
||||||
|
}
|
||||||
|
else if (UEdComboActionGraphEdge *EdNode_Edge = Cast<UEdComboActionGraphEdge>(Pin->LinkedTo[LinkToIdx]->GetOwningNode()))
|
||||||
|
{
|
||||||
|
UEdComboActionGraphNode *Child = EdNode_Edge->GetEndNode();;
|
||||||
|
if (Child != nullptr)
|
||||||
|
{
|
||||||
|
ChildNode = Child->ComboActionGraphNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ChildNode != nullptr)
|
||||||
|
{
|
||||||
|
ComboActionGraphNode->ChildrenNodes.Add(ChildNode);
|
||||||
|
|
||||||
|
ChildNode->ParentNodes.Add(ComboActionGraphNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(LogEdComboActionGraph, Error, TEXT("[RebuildComboActionGraph] Can't find child node"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (UEdComboActionGraphEdge *EdgeNode = Cast<UEdComboActionGraphEdge>(Nodes[i]))
|
||||||
|
{
|
||||||
|
UEdComboActionGraphNode *StartNode = EdgeNode->GetStartNode();
|
||||||
|
UEdComboActionGraphNode *EndNode = EdgeNode->GetEndNode();
|
||||||
|
UComboActionGraphEdge *Edge = EdgeNode->ComboActionGraphEdge;
|
||||||
|
|
||||||
|
if (StartNode == nullptr || EndNode == nullptr || Edge == nullptr)
|
||||||
|
{
|
||||||
|
UE_LOG(LogEdComboActionGraph, Error, TEXT("[RebuildMounteaDialogueGraph] Add edge failed."));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeMap.Add(Edge, EdgeNode);
|
||||||
|
|
||||||
|
Edge->Graph = Graph;
|
||||||
|
Edge->Rename(nullptr, Graph, REN_DontCreateRedirectors | REN_DoNotDirty);
|
||||||
|
Edge->StartNode = StartNode->ComboActionGraphNode;
|
||||||
|
Edge->EndNode = EndNode->ComboActionGraphNode;
|
||||||
|
Edge->StartNode->Edges.Add(Edge->EndNode, Edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Graph->AllNodes.Num(); ++i)
|
||||||
|
{
|
||||||
|
UComboActionGraphNode *Node = Graph->AllNodes[i];
|
||||||
|
if (Node->ParentNodes.Num() == 0)
|
||||||
|
{
|
||||||
|
Graph->RootNodes.Add(Node);
|
||||||
|
|
||||||
|
SortNodes(Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node->Graph = Graph;
|
||||||
|
Node->Rename(nullptr, Graph, REN_DontCreateRedirectors | REN_DoNotDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
Graph->RootNodes.Sort([&](const UComboActionGraphNode &L, const UComboActionGraphNode &R)
|
||||||
|
{
|
||||||
|
UEdComboActionGraphNode* EdNode_LNode = NodeMap[&L];
|
||||||
|
UEdComboActionGraphNode* EdNode_RNode = NodeMap[&R];
|
||||||
|
return EdNode_LNode->NodePosX < EdNode_RNode->NodePosX;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
UComboActionGraph *UEdComboActionGraph::GetComboActionGraph() const
|
||||||
|
{
|
||||||
|
return CastChecked<UComboActionGraph>(GetOuter());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UEdComboActionGraph::Modify(bool bAlwaysMarkDirty)
|
||||||
|
{
|
||||||
|
bool Rtn = Super::Modify(bAlwaysMarkDirty);
|
||||||
|
|
||||||
|
this->GetComboActionGraph()->Modify();
|
||||||
|
|
||||||
|
for (int32 i = 0; i < Nodes.Num(); ++i)
|
||||||
|
{
|
||||||
|
Nodes[i]->Modify();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraph::PostEditUndo()
|
||||||
|
{
|
||||||
|
NotifyGraphChanged();
|
||||||
|
|
||||||
|
Super::PostEditUndo();
|
||||||
|
}
|
||||||
|
|
||||||
|
//void UEdComboActionGraph::SetDialogueEditorPtr(TWeakPtr<FAssetEditor_MounteaDialogueGraph> NewPtr)
|
||||||
|
//{
|
||||||
|
// DialogueEditorPtr = NewPtr;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//bool UEdComboActionGraph::JumpToNode(const UMounteaDialogueGraphNode* Node)
|
||||||
|
//{
|
||||||
|
// return FComboActionGraphEditorUtilities::OpenEditorAndJumpToGraphNode(DialogueEditorPtr, *NodeMap.Find(Node));
|
||||||
|
//}
|
||||||
|
|
||||||
|
void UEdComboActionGraph::Clear()
|
||||||
|
{
|
||||||
|
UComboActionGraph *Graph = this->GetComboActionGraph();
|
||||||
|
|
||||||
|
Graph->ClearGraph();
|
||||||
|
this->NodeMap.Reset();
|
||||||
|
this->EdgeMap.Reset();
|
||||||
|
|
||||||
|
for (int i = 0; i < this->Nodes.Num(); ++i)
|
||||||
|
{
|
||||||
|
if (UEdComboActionGraphNode *EdNode = Cast<UEdComboActionGraphNode>(Nodes[i]))
|
||||||
|
{
|
||||||
|
UComboActionGraphNode *MounteaDialogueGraphNode = EdNode->ComboActionGraphNode;
|
||||||
|
MounteaDialogueGraphNode->ParentNodes.Reset();
|
||||||
|
MounteaDialogueGraphNode->ChildrenNodes.Reset();
|
||||||
|
MounteaDialogueGraphNode->Edges.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraph::SortNodes(UComboActionGraphNode *RootNode)
|
||||||
|
{
|
||||||
|
int Level = 0;
|
||||||
|
TArray<UComboActionGraphNode*> CurrLevelNodes = { RootNode };
|
||||||
|
TArray<UComboActionGraphNode*> NextLevelNodes;
|
||||||
|
|
||||||
|
while (CurrLevelNodes.Num() != 0)
|
||||||
|
{
|
||||||
|
int32 LevelWidth = 0;
|
||||||
|
for (int i = 0; i < CurrLevelNodes.Num(); ++i)
|
||||||
|
{
|
||||||
|
UComboActionGraphNode *Node = CurrLevelNodes[i];
|
||||||
|
|
||||||
|
auto Comp = [&](const UComboActionGraphNode &L, const UComboActionGraphNode &R)
|
||||||
|
{
|
||||||
|
UEdComboActionGraphNode *EdNode_LNode = NodeMap[&L];
|
||||||
|
UEdComboActionGraphNode *EdNode_RNode = NodeMap[&R];
|
||||||
|
return EdNode_LNode->NodePosX < EdNode_RNode->NodePosX;
|
||||||
|
};
|
||||||
|
|
||||||
|
Node->ChildrenNodes.Sort(Comp);
|
||||||
|
Node->ParentNodes.Sort(Comp);
|
||||||
|
|
||||||
|
for (int j = 0; j < Node->ChildrenNodes.Num(); ++j)
|
||||||
|
{
|
||||||
|
NextLevelNodes.Add(Node->ChildrenNodes[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrLevelNodes = NextLevelNodes;
|
||||||
|
NextLevelNodes.Reset();
|
||||||
|
++Level;
|
||||||
|
}
|
||||||
|
}
|
||||||
49
Source/ComboInputEditor/Private/Ed/EdComboActionGraph.h
Normal file
49
Source/ComboInputEditor/Private/Ed/EdComboActionGraph.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "EdGraph/EdGraph.h"
|
||||||
|
|
||||||
|
#include "EdComboActionGraph.generated.h"
|
||||||
|
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(LogEdComboActionGraph, Log, All);
|
||||||
|
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class COMBOINPUT_API UEdComboActionGraph : public UEdGraph
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void RebuildComboActionGraph();
|
||||||
|
|
||||||
|
UComboActionGraph *GetComboActionGraph() const;
|
||||||
|
|
||||||
|
virtual bool Modify(bool bAlwaysMarkDirty) override;
|
||||||
|
virtual void PostEditUndo() override;
|
||||||
|
|
||||||
|
//TWeakPtr<FAssetEditor_ComboActionGraph> GetDialogueEditorPtr() const { return DialogueEditorPtr; }
|
||||||
|
//void SetDialogueEditorPtr(TWeakPtr<FAssetEditor_ComboActionGraph> NewPtr);
|
||||||
|
//void ResetDialogueEditorPtr() { DialogueEditorPtr.Reset(); }
|
||||||
|
|
||||||
|
//bool JumpToNode(const class UComboActionGraphNode *Node);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
UPROPERTY(Transient)
|
||||||
|
TMap<class UComboActionGraphNode*, class UEdComboActionGraphNode*> NodeMap;
|
||||||
|
|
||||||
|
UPROPERTY(Transient)
|
||||||
|
TMap<class UComboActionGraphEdge*, class UEdComboActionGraphEdge*> EdgeMap;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
void SortNodes(UComboActionGraphNode *RootNode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Pointer back to the Dialogue editor that owns us */
|
||||||
|
//TWeakPtr<FAssetEditor_ComboActionGraph> DialogueEditorPtr;
|
||||||
|
};
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "EdComboActionGraphEdge.h"
|
||||||
|
|
||||||
|
#include "EdComboActionGraphNode.h"
|
||||||
|
#include "Nodes/ComboActionGraphEdge.h"
|
||||||
|
|
||||||
|
|
||||||
|
void UEdComboActionGraphEdge::SetEdge(UComboActionGraphEdge *Edge)
|
||||||
|
{
|
||||||
|
this->ComboActionGraphEdge = Edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraphEdge::AllocateDefaultPins()
|
||||||
|
{
|
||||||
|
UEdGraphPin* Inputs = this->CreatePin(EGPD_Input, TEXT("Edge"), FName(), TEXT("In"));
|
||||||
|
Inputs->bHidden = true;
|
||||||
|
UEdGraphPin* Outputs = this->CreatePin(EGPD_Output, TEXT("Edge"), FName(), TEXT("Out"));
|
||||||
|
Outputs->bHidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FText UEdComboActionGraphEdge::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
||||||
|
{
|
||||||
|
return Super::GetNodeTitle(TitleType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraphEdge::PinConnectionListChanged(UEdGraphPin *Pin)
|
||||||
|
{
|
||||||
|
if (Pin->LinkedTo.Num() == 0)
|
||||||
|
{
|
||||||
|
// Commit suicide; transitions must always have an input and output connection
|
||||||
|
Modify();
|
||||||
|
|
||||||
|
// Our parent graph will have our graph in SubGraphs so needs to be modified to record that.
|
||||||
|
if (UEdGraph *ParentGraph = GetGraph())
|
||||||
|
{
|
||||||
|
ParentGraph->Modify();
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraphEdge::PrepareForCopying()
|
||||||
|
{
|
||||||
|
this->ComboActionGraphEdge->Rename(nullptr, this, REN_DontCreateRedirectors | REN_DoNotDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraphEdge::CreateConnections(UEdComboActionGraphNode *Start, UEdComboActionGraphNode *End)
|
||||||
|
{
|
||||||
|
Pins[0]->Modify();
|
||||||
|
Pins[0]->LinkedTo.Empty();
|
||||||
|
|
||||||
|
Start->GetOutputPin()->Modify();
|
||||||
|
Pins[0]->MakeLinkTo(Start->GetOutputPin());
|
||||||
|
|
||||||
|
// This to next
|
||||||
|
Pins[1]->Modify();
|
||||||
|
Pins[1]->LinkedTo.Empty();
|
||||||
|
|
||||||
|
End->GetInputPin()->Modify();
|
||||||
|
Pins[1]->MakeLinkTo(End->GetInputPin());
|
||||||
|
}
|
||||||
|
|
||||||
|
UEdComboActionGraphNode *UEdComboActionGraphEdge::GetStartNode()
|
||||||
|
{
|
||||||
|
if (Pins[0]->LinkedTo.Num() > 0)
|
||||||
|
{
|
||||||
|
return Cast<UEdComboActionGraphNode>(Pins[0]->LinkedTo[0]->GetOwningNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UEdComboActionGraphNode *UEdComboActionGraphEdge::GetEndNode()
|
||||||
|
{
|
||||||
|
if (Pins[1]->LinkedTo.Num() > 0)
|
||||||
|
{
|
||||||
|
return Cast<UEdComboActionGraphNode>(Pins[1]->LinkedTo[0]->GetOwningNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
45
Source/ComboInputEditor/Private/Ed/EdComboActionGraphEdge.h
Normal file
45
Source/ComboInputEditor/Private/Ed/EdComboActionGraphEdge.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "EdGraph/EdGraphNode.h"
|
||||||
|
|
||||||
|
#include "EdComboActionGraphEdge.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
UCLASS(MinimalAPI)
|
||||||
|
class UEdComboActionGraphEdge : public UEdGraphNode
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY()
|
||||||
|
class UEdGraph *Graph;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, Instanced, Category="Combo Action Graph")
|
||||||
|
class UComboActionGraphEdge *ComboActionGraphEdge;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void SetEdge(class UComboActionGraphEdge *Edge);
|
||||||
|
|
||||||
|
virtual void AllocateDefaultPins() override;
|
||||||
|
|
||||||
|
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
|
||||||
|
|
||||||
|
virtual void PinConnectionListChanged(UEdGraphPin *Pin) override;
|
||||||
|
|
||||||
|
virtual void PrepareForCopying() override;
|
||||||
|
|
||||||
|
virtual UEdGraphPin *GetInputPin() const { return Pins[0]; }
|
||||||
|
virtual UEdGraphPin *GetOutputPin() const { return Pins[1]; }
|
||||||
|
|
||||||
|
void CreateConnections(class UEdComboActionGraphNode *Start, class UEdComboActionGraphNode* End);
|
||||||
|
|
||||||
|
class UEdComboActionGraphNode *GetStartNode();
|
||||||
|
class UEdComboActionGraphNode *GetEndNode();
|
||||||
|
};
|
||||||
169
Source/ComboInputEditor/Private/Ed/EdComboActionGraphNode.cpp
Normal file
169
Source/ComboInputEditor/Private/Ed/EdComboActionGraphNode.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "EdComboActionGraphNode.h"
|
||||||
|
|
||||||
|
#include "Ed/EdComboActionGraph.h"
|
||||||
|
#include "Helpers/ComboActionEditorBFC.h"
|
||||||
|
#include "Nodes/ComboActionGraphNode.h"
|
||||||
|
#include "Settings/ComboActionGraphEditorSettings.h"
|
||||||
|
#include "Settings/FComboActionGraphEditorStyle.h"
|
||||||
|
|
||||||
|
#define LOCTEXT_NAMESPACE "UEdComboActionGraphNode"
|
||||||
|
|
||||||
|
DEFINE_LOG_CATEGORY(LogEdComboActionGraphNode);
|
||||||
|
|
||||||
|
|
||||||
|
UEdComboActionGraphNode::UEdComboActionGraphNode()
|
||||||
|
{
|
||||||
|
bCanRenameNode = true;
|
||||||
|
|
||||||
|
bAllowCopy = true;
|
||||||
|
bAllowDelete = true;
|
||||||
|
bAllowDuplicate = true;
|
||||||
|
bAllowPaste = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UEdComboActionGraph *UEdComboActionGraphNode::GetEdComboActionGraph() const
|
||||||
|
{
|
||||||
|
return Cast<UEdComboActionGraph>(this->GetGraph());
|
||||||
|
};
|
||||||
|
|
||||||
|
void UEdComboActionGraphNode::AllocateDefaultPins()
|
||||||
|
{
|
||||||
|
if (this->ComboActionGraphNode == nullptr)
|
||||||
|
{
|
||||||
|
UE_LOG(LogEdComboActionGraphNode, Error, TEXT("[AllocateDefaultPins] Cannot find Owning Graph Node!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->ComboActionGraphNode->bAllowInputNodes)
|
||||||
|
{
|
||||||
|
this->CreatePin(EGPD_Input, "MultipleNodes", FName(), TEXT("In"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->ComboActionGraphNode->bAllowOutputNodes)
|
||||||
|
{
|
||||||
|
this->CreatePin(EGPD_Output, "MultipleNodes", FName(), TEXT("Out"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FText UEdComboActionGraphNode::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
||||||
|
{
|
||||||
|
return UComboActionEditorBFC::GetNodeTitle(this->ComboActionGraphNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraphNode::PrepareForCopying()
|
||||||
|
{
|
||||||
|
this->ComboActionGraphNode->Rename(nullptr, this, REN_DontCreateRedirectors | REN_DoNotDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraphNode::AutowireNewNode(UEdGraphPin* FromPin)
|
||||||
|
{
|
||||||
|
Super::AutowireNewNode(FromPin);
|
||||||
|
|
||||||
|
if (FromPin != nullptr)
|
||||||
|
{
|
||||||
|
if (GetSchema()->TryCreateConnection(FromPin, GetInputPin()))
|
||||||
|
{
|
||||||
|
FromPin->GetOwningNode()->NodeConnectionListChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FLinearColor UEdComboActionGraphNode::GetBackgroundColor() const
|
||||||
|
{
|
||||||
|
// Getting Node colour based on the Settings if any found, otherwise use this logic
|
||||||
|
if (UComboActionGraphEditorSettings *GraphEditorSettings = GetMutableDefault<UComboActionGraphEditorSettings>())
|
||||||
|
{
|
||||||
|
FLinearColor ReturnColour;
|
||||||
|
if (GraphEditorSettings->FindNodeBackgroundColourOverride(this->ComboActionGraphNode->GetClass(), ReturnColour))
|
||||||
|
{
|
||||||
|
return ReturnColour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->ComboActionGraphNode ? this->ComboActionGraphNode->GetBackgroundColor() : FLinearColor::Black;
|
||||||
|
}
|
||||||
|
|
||||||
|
UEdGraphPin* UEdComboActionGraphNode::GetInputPin() const
|
||||||
|
{
|
||||||
|
return Pins[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
UEdGraphPin* UEdComboActionGraphNode::GetOutputPin() const
|
||||||
|
{
|
||||||
|
if (Pins.IsValidIndex(1))
|
||||||
|
{
|
||||||
|
return Pins[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pins[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UEdComboActionGraphNode::CanUserDeleteNode() const
|
||||||
|
{
|
||||||
|
if(!Super::CanUserDeleteNode())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->ComboActionGraphNode)
|
||||||
|
{
|
||||||
|
return this->ComboActionGraphNode->bAllowDelete;
|
||||||
|
}
|
||||||
|
return bAllowDelete;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UEdComboActionGraphNode::CanDuplicateNode() const
|
||||||
|
{
|
||||||
|
if(!Super::CanUserDeleteNode())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->ComboActionGraphNode)
|
||||||
|
{
|
||||||
|
return this->ComboActionGraphNode->bAllowCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bAllowCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UEdComboActionGraphNode::CanUserPasteNodes() const
|
||||||
|
{
|
||||||
|
if (this->ComboActionGraphNode)
|
||||||
|
{
|
||||||
|
return this->ComboActionGraphNode->bAllowPaste;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bAllowPaste;
|
||||||
|
}
|
||||||
|
|
||||||
|
FText UEdComboActionGraphNode::GetTooltipText() const
|
||||||
|
{
|
||||||
|
if (this->ComboActionGraphNode)
|
||||||
|
{
|
||||||
|
return this->ComboActionGraphNode->GetNodeTooltipText();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NSLOCTEXT("UEdComboActionGraphNode", "DefaultToolTip", "Mountea Dialogue Node");
|
||||||
|
}
|
||||||
|
|
||||||
|
FSlateIcon UEdComboActionGraphNode::GetIconAndTint(FLinearColor& OutColor) const
|
||||||
|
{
|
||||||
|
static const FSlateIcon Icon = FSlateIcon(FComboActionGraphEditorStyle::GetAppStyleSetName(), "MDSStyleSet.Node.Icon.small");
|
||||||
|
OutColor = this->ComboActionGraphNode->GetBackgroundColor();
|
||||||
|
return Icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraphNode::PostEditUndo()
|
||||||
|
{
|
||||||
|
Super::PostEditUndo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEdComboActionGraphNode::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||||
|
{
|
||||||
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef LOCTEXT_NAMESPACE
|
||||||
60
Source/ComboInputEditor/Private/Ed/EdComboActionGraphNode.h
Normal file
60
Source/ComboInputEditor/Private/Ed/EdComboActionGraphNode.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "SEdComboActionGraphNode.h"
|
||||||
|
#include "EdGraph/EdGraphNode.h"
|
||||||
|
|
||||||
|
#include "EdComboActionGraphNode.generated.h"
|
||||||
|
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(LogEdComboActionGraphNode, Log, All);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
UCLASS(MinimalAPI)
|
||||||
|
class UEdComboActionGraphNode : public UEdGraphNode
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UEdComboActionGraphNode();
|
||||||
|
|
||||||
|
class UEdComboActionGraph *GetEdComboActionGraph() const;
|
||||||
|
|
||||||
|
virtual void AllocateDefaultPins() override;
|
||||||
|
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
|
||||||
|
virtual void PrepareForCopying() override;
|
||||||
|
virtual void AutowireNewNode(UEdGraphPin *FromPin) override;
|
||||||
|
|
||||||
|
virtual FLinearColor GetBackgroundColor() const;
|
||||||
|
virtual UEdGraphPin *GetInputPin() const;
|
||||||
|
virtual UEdGraphPin *GetOutputPin() const;
|
||||||
|
|
||||||
|
virtual bool CanUserDeleteNode() const override;
|
||||||
|
virtual bool CanDuplicateNode() const override;
|
||||||
|
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, Instanced, Category="Combo Action Graph")
|
||||||
|
class UComboActionGraphNode *ComboActionGraphNode;
|
||||||
|
|
||||||
|
SEdComboActionGraphNode *SEdNode;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool bAllowCopy;
|
||||||
|
bool bAllowDelete;
|
||||||
|
bool bAllowDuplicate;
|
||||||
|
bool bAllowPaste;
|
||||||
|
};
|
||||||
1442
Source/ComboInputEditor/Private/Ed/SEdComboActionGraphNode.cpp
Normal file
1442
Source/ComboInputEditor/Private/Ed/SEdComboActionGraphNode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
89
Source/ComboInputEditor/Private/Ed/SEdComboActionGraphNode.h
Normal file
89
Source/ComboInputEditor/Private/Ed/SEdComboActionGraphNode.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "SGraphNode.h"
|
||||||
|
#include "Settings\ComboActionGraphEditorSettings.h"
|
||||||
|
|
||||||
|
|
||||||
|
class SEdComboActionGraphNode : public SGraphNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SLATE_BEGIN_ARGS(SEdComboActionGraphNode) {}
|
||||||
|
SLATE_END_ARGS()
|
||||||
|
|
||||||
|
void Construct(const FArguments &InArgs, class UEdComboActionGraphNode *InNode);
|
||||||
|
|
||||||
|
virtual void OnMouseEnter(const FGeometry &MyGeometry, const FPointerEvent &MouseEvent) override;
|
||||||
|
virtual void OnMouseLeave(const FPointerEvent &MouseEvent) override;
|
||||||
|
|
||||||
|
const FSlateBrush *GetIndexBrush() const;
|
||||||
|
|
||||||
|
virtual void UpdateGraphNode() override;
|
||||||
|
virtual void CreatePinWidgets() override;
|
||||||
|
virtual void AddPin(const TSharedRef<SGraphPin> &PinToAdd) override;
|
||||||
|
virtual bool IsNameReadOnly() const override;
|
||||||
|
|
||||||
|
void OnNameTextCommitted(const FText &InText, ETextCommit::Type CommitInfo);
|
||||||
|
|
||||||
|
virtual const FSlateBrush *GetNodeTypeBrush () const;
|
||||||
|
virtual const FSlateBrush *GetTextNodeTypeBrush () const;
|
||||||
|
virtual FSlateColor GetBorderBackgroundColor() const;
|
||||||
|
virtual FSlateColor GetBorderFrontColor() const;
|
||||||
|
virtual FSlateColor GetNodeTitleBackgroundColor() const;
|
||||||
|
virtual FSlateColor GetDecoratorsBackgroundColor() const;
|
||||||
|
|
||||||
|
virtual FSlateColor GetPinsDockColor() const;
|
||||||
|
|
||||||
|
virtual EVisibility GetDragOverMarkerVisibility() const;
|
||||||
|
|
||||||
|
virtual const FSlateBrush *GetNameIcon() const;
|
||||||
|
|
||||||
|
virtual const FSlateBrush *GetInheritsImageBrush() const;
|
||||||
|
virtual FSlateColor GetInheritsImageTint() const;
|
||||||
|
|
||||||
|
const FSlateBrush *GetBulletPointImageBrush() const;
|
||||||
|
|
||||||
|
virtual FText GetIndexOverlayTooltipText() const;
|
||||||
|
virtual FText GetIndexText() const;
|
||||||
|
EVisibility GetIndexSlotVisibility() const;
|
||||||
|
FVector2D GetIndexSlotOffset() const;
|
||||||
|
FVector2D GetIndexSlotSize() const;
|
||||||
|
|
||||||
|
virtual void OnIndexHoverStateChanged(bool bArg) const;
|
||||||
|
virtual FSlateColor GetOverlayWidgetBackgroundColor(bool bArg) const;
|
||||||
|
|
||||||
|
bool HasGraphDecorators() const;
|
||||||
|
bool HasNodeDecorators() const;
|
||||||
|
|
||||||
|
virtual FText GetDecoratorsText() const;
|
||||||
|
virtual FText GetNumberOfDecorators() const;
|
||||||
|
virtual FText GetDecoratorsInheritanceText() const;
|
||||||
|
|
||||||
|
EVisibility ShowImplementsOnlySlot_Unified() const;
|
||||||
|
EVisibility ShowInheritsDecoratorsSlot_Unified() const;
|
||||||
|
EVisibility ShowImplementsOnlySlot_Stack() const;
|
||||||
|
EVisibility ShowInheritsDecoratorsSlot_Stack() const;
|
||||||
|
EVisibility ShowAllDecorators() const;
|
||||||
|
EVisibility ShowDecoratorsBottomPadding() const;
|
||||||
|
|
||||||
|
FSlateColor GetImplementsRowColor() const;
|
||||||
|
FSlateColor GetBulletPointsImagePointColor() const;
|
||||||
|
|
||||||
|
virtual EComboActionDecoratorsInfoStyle GetDecoratorsStyle() const;
|
||||||
|
EVisibility GetStackVisibility() const;
|
||||||
|
EVisibility GetUnifiedVisibility() const;
|
||||||
|
|
||||||
|
FText GetTooltipText() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TSharedPtr<SBorder> NodeBody;
|
||||||
|
TSharedPtr<SHorizontalBox> OutputPinBox;
|
||||||
|
|
||||||
|
class UComboActionGraphEditorSettings *GraphEditorSettings = nullptr;
|
||||||
|
|
||||||
|
FLinearColor NodeInnerColor;
|
||||||
|
FLinearColor PinsDockColor;
|
||||||
|
};
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "SEdComboActionGraphNodeIndex.h"
|
||||||
|
|
||||||
|
#include "Settings/FComboActionGraphEditorStyle.h"
|
||||||
|
|
||||||
|
|
||||||
|
void SEdComboActionGraphNodeIndex::Construct(const FArguments &InArgs)
|
||||||
|
{
|
||||||
|
const FSlateBrush* CircleBrush = FComboActionGraphEditorStyle::GetBrush(TEXT("MDSStyleSet.Node.IndexCircle"));
|
||||||
|
ChildSlot
|
||||||
|
[
|
||||||
|
SNew(SOverlay)
|
||||||
|
+SOverlay::Slot()
|
||||||
|
.HAlign(HAlign_Fill)
|
||||||
|
.VAlign(VAlign_Fill)
|
||||||
|
[
|
||||||
|
// Add a dummy box here to make sure the widget doesnt get smaller than the brush
|
||||||
|
SNew(SBox)
|
||||||
|
.WidthOverride(CircleBrush->ImageSize.X)
|
||||||
|
.HeightOverride(CircleBrush->ImageSize.Y)
|
||||||
|
]
|
||||||
|
|
||||||
|
+SOverlay::Slot()
|
||||||
|
.HAlign(HAlign_Fill)
|
||||||
|
.VAlign(VAlign_Fill)
|
||||||
|
[
|
||||||
|
SNew(SBorder)
|
||||||
|
.BorderImage(CircleBrush)
|
||||||
|
.BorderBackgroundColor(this, &SEdComboActionGraphNodeIndex::GetBackgroundColor)
|
||||||
|
.Padding(FMargin(4.0f))
|
||||||
|
.VAlign(VAlign_Center)
|
||||||
|
.HAlign(HAlign_Center)
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Widgets/DeclarativeSyntaxSupport.h"
|
||||||
|
#include "Widgets/SCompoundWidget.h"
|
||||||
|
|
||||||
|
class SEdComboActionGraphNodeIndex : public SCompoundWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Delegate event fired when the hover state of this widget changes */
|
||||||
|
DECLARE_DELEGATE_OneParam(FOnHoverStateChanged, bool /* bHovered */);
|
||||||
|
|
||||||
|
/** Delegate used to receive the background color of the node, depending on hover state and state of other siblings */
|
||||||
|
DECLARE_DELEGATE_RetVal_OneParam(FSlateColor, FOnGetBackgroundColor, bool /* bHovered */);
|
||||||
|
|
||||||
|
SLATE_BEGIN_ARGS(SEdComboActionGraphNodeIndex) {}
|
||||||
|
SLATE_ATTRIBUTE(TSharedPtr<SWidget>, OverlayBody)
|
||||||
|
|
||||||
|
// Events
|
||||||
|
SLATE_EVENT(FOnHoverStateChanged, OnHoverStateChanged)
|
||||||
|
SLATE_EVENT(FOnGetBackgroundColor, OnGetBackgroundColor)
|
||||||
|
SLATE_END_ARGS()
|
||||||
|
|
||||||
|
void Construct(const FArguments &InArgs);
|
||||||
|
|
||||||
|
/** Get the color we use to display the rounded border */
|
||||||
|
FSlateColor GetBackgroundColor() const { return FSlateColor::UseForeground(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** The OverlayBody used for this widget*/
|
||||||
|
TSharedPtr<SWidget> OverlayBody;
|
||||||
|
};
|
||||||
@ -0,0 +1,208 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "FConnectionDrawingPolicy_ComboActionGraph.h"
|
||||||
|
|
||||||
|
#include "Ed/EdComboActionGraphEdge.h"
|
||||||
|
#include "Ed/EdComboActionGraphNode.h"
|
||||||
|
#include "Settings/ComboActionGraphEditorSettings.h"
|
||||||
|
#include "Settings/FComboActionGraphEditorStyle.h"
|
||||||
|
|
||||||
|
DEFINE_LOG_CATEGORY(LogConnectionDrawingPolicy_ComboActionGraph);
|
||||||
|
|
||||||
|
|
||||||
|
FConnectionDrawingPolicy_ComboActionGraph::FConnectionDrawingPolicy_ComboActionGraph(int32 InBackLayerID, int32 InFrontLayerID, float ZoomFactor, const FSlateRect &InClippingRect, FSlateWindowElementList &InDrawElements, UEdGraph *InGraphObj)
|
||||||
|
: FKismetConnectionDrawingPolicy(InBackLayerID, InFrontLayerID, ZoomFactor, InClippingRect, InDrawElements, InGraphObj)
|
||||||
|
, GraphObj(InGraphObj)
|
||||||
|
{
|
||||||
|
if (const UComboActionGraphEditorSettings* GraphEditorSettings = GetMutableDefault<UComboActionGraphEditorSettings>())
|
||||||
|
{
|
||||||
|
switch (GraphEditorSettings->GetArrowType())
|
||||||
|
{
|
||||||
|
case EComboActionArrowType::SimpleArrow:
|
||||||
|
ArrowImage = FComboActionGraphEditorStyle::GetBrush(TEXT("MDSStyleSet.Graph.SimpleArrow"));
|
||||||
|
break;
|
||||||
|
case EComboActionArrowType::HollowArrow:
|
||||||
|
ArrowImage = FComboActionGraphEditorStyle::GetBrush(TEXT("MDSStyleSet.Graph.HollowArrow"));
|
||||||
|
break;
|
||||||
|
case EComboActionArrowType::FancyArrow:
|
||||||
|
ArrowImage = FComboActionGraphEditorStyle::GetBrush(TEXT("MDSStyleSet.Graph.FancyArrow"));
|
||||||
|
break;
|
||||||
|
case EComboActionArrowType::Bubble:
|
||||||
|
ArrowImage = FComboActionGraphEditorStyle::GetBrush(TEXT("MDSStyleSet.Graph.Bubble"));
|
||||||
|
break;
|
||||||
|
case EComboActionArrowType::None:
|
||||||
|
default:
|
||||||
|
ArrowImage = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ArrowImage = FAppStyle::GetBrush( TEXT("GenericPlay") );
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrowRadius = ArrowImage ? ArrowImage->ImageSize * ZoomFactor * 0.5f : FVector2D(0.f);
|
||||||
|
MidpointImage = nullptr;
|
||||||
|
MidpointRadius = FVector2D::ZeroVector;
|
||||||
|
HoverDeemphasisDarkFraction = 0.8f;
|
||||||
|
|
||||||
|
BubbleImage = FAppStyle::GetBrush( TEXT("Graph.Arrow") );
|
||||||
|
}
|
||||||
|
|
||||||
|
void FConnectionDrawingPolicy_ComboActionGraph::DetermineWiringStyle(UEdGraphPin *OutputPin, UEdGraphPin *InputPin, FConnectionParams &Params)
|
||||||
|
{
|
||||||
|
Params.AssociatedPin1 = OutputPin;
|
||||||
|
Params.AssociatedPin2 = InputPin;
|
||||||
|
|
||||||
|
const UComboActionGraphEditorSettings *MounteaDialogueGraphEditorSettings = GetDefault<UComboActionGraphEditorSettings>();
|
||||||
|
if (MounteaDialogueGraphEditorSettings)
|
||||||
|
{
|
||||||
|
Params.WireThickness = MounteaDialogueGraphEditorSettings->GetWireWidth();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Params.WireThickness = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;
|
||||||
|
if (bDeemphasizeUnhoveredPins)
|
||||||
|
{
|
||||||
|
ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Params.WireThickness, /*inout*/ Params.WireColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FConnectionDrawingPolicy_ComboActionGraph::Draw(TMap<TSharedRef<SWidget>, FArrangedWidget> &InPinGeometries, FArrangedChildren &ArrangedNodes)
|
||||||
|
{
|
||||||
|
// Build an acceleration structure to quickly find geometry for the nodes
|
||||||
|
NodeWidgetMap.Empty();
|
||||||
|
for (int32 NodeIndex = 0; NodeIndex < ArrangedNodes.Num(); ++NodeIndex)
|
||||||
|
{
|
||||||
|
FArrangedWidget& CurWidget = ArrangedNodes[NodeIndex];
|
||||||
|
TSharedRef<SGraphNode> ChildNode = StaticCastSharedRef<SGraphNode>(CurWidget.Widget);
|
||||||
|
NodeWidgetMap.Add(ChildNode->GetNodeObj(), NodeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now draw
|
||||||
|
FConnectionDrawingPolicy::Draw(InPinGeometries, ArrangedNodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FConnectionDrawingPolicy_ComboActionGraph::DrawSplineWithArrow(const FGeometry &StartGeom, const FGeometry &EndGeom, const FConnectionParams &Params)
|
||||||
|
{
|
||||||
|
// Get a reasonable seed point (halfway between the boxes)
|
||||||
|
const FVector2D StartCenter = FGeometryHelper::CenterOf(StartGeom);
|
||||||
|
const FVector2D EndCenter = FGeometryHelper::CenterOf(EndGeom);
|
||||||
|
const FVector2D SeedPoint = (StartCenter + EndCenter) * 0.5f;
|
||||||
|
|
||||||
|
// Find the (approximate) closest points between the two boxes
|
||||||
|
const FVector2D StartAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(StartGeom, SeedPoint);
|
||||||
|
const FVector2D EndAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(EndGeom, SeedPoint);
|
||||||
|
|
||||||
|
this->DrawSplineWithArrow(StartAnchorPoint, EndAnchorPoint, Params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FConnectionDrawingPolicy_ComboActionGraph::DrawSplineWithArrow(const FVector2D &StartPoint, const FVector2D &EndPoint, const FConnectionParams &Params)
|
||||||
|
{
|
||||||
|
// bUserFlag1 indicates that we need to reverse the direction of connection (used by debugger)
|
||||||
|
const FVector2D &P0 = Params.bUserFlag1 ? EndPoint : StartPoint;
|
||||||
|
const FVector2D &P1 = Params.bUserFlag1 ? StartPoint : EndPoint;
|
||||||
|
|
||||||
|
UE_LOG(LogConnectionDrawingPolicy_ComboActionGraph, Verbose, TEXT("%s I %s"), *P0.ToString(), *P1.ToString());
|
||||||
|
|
||||||
|
FConnectionParams NewParams = Params;
|
||||||
|
//NewParams.bDrawBubbles = true;
|
||||||
|
|
||||||
|
if (const UComboActionGraphEditorSettings *MounteaDialogueGraphEditorSettings = GetMutableDefault<UComboActionGraphEditorSettings>())
|
||||||
|
{
|
||||||
|
NewParams.WireThickness = MounteaDialogueGraphEditorSettings->GetWireWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
Internal_DrawLineWithArrow(P0, P1, NewParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FConnectionDrawingPolicy_ComboActionGraph::DrawPreviewConnector(const FGeometry &PinGeometry, const FVector2D &StartPoint, const FVector2D &EndPoint, UEdGraphPin* Pin)
|
||||||
|
{
|
||||||
|
FConnectionParams Params;
|
||||||
|
DetermineWiringStyle(Pin, nullptr, /*inout*/ Params);
|
||||||
|
|
||||||
|
if (Pin->Direction == EEdGraphPinDirection::EGPD_Output)
|
||||||
|
{
|
||||||
|
DrawSplineWithArrow(FGeometryHelper::FindClosestPointOnGeom(PinGeometry, EndPoint), EndPoint, Params);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawSplineWithArrow(FGeometryHelper::FindClosestPointOnGeom(PinGeometry, StartPoint), StartPoint, Params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FVector2D FConnectionDrawingPolicy_ComboActionGraph::ComputeSplineTangent(const FVector2D &Start, const FVector2D &End) const
|
||||||
|
{
|
||||||
|
const FVector2D Delta = End - Start;
|
||||||
|
const FVector2D NormDelta = Delta.GetSafeNormal();
|
||||||
|
|
||||||
|
return NormDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FConnectionDrawingPolicy_ComboActionGraph::DetermineLinkGeometry(FArrangedChildren &ArrangedNodes, TSharedRef<SWidget> &OutputPinWidget, UEdGraphPin *OutputPin, UEdGraphPin *InputPin, FArrangedWidget *&StartWidgetGeometry, FArrangedWidget *&EndWidgetGeometry)
|
||||||
|
{
|
||||||
|
if (UEdComboActionGraphEdge *EdgeNode = Cast<UEdComboActionGraphEdge>(InputPin->GetOwningNode()))
|
||||||
|
{
|
||||||
|
UEdComboActionGraphNode* Start = EdgeNode->GetStartNode();
|
||||||
|
UEdComboActionGraphNode* End = EdgeNode->GetEndNode();
|
||||||
|
if (Start != nullptr && End != nullptr)
|
||||||
|
{
|
||||||
|
int32* StartNodeIndex = NodeWidgetMap.Find(Start);
|
||||||
|
int32* EndNodeIndex = NodeWidgetMap.Find(End);
|
||||||
|
if (StartNodeIndex != nullptr && EndNodeIndex != nullptr)
|
||||||
|
{
|
||||||
|
StartWidgetGeometry = &(ArrangedNodes[*StartNodeIndex]);
|
||||||
|
EndWidgetGeometry = &(ArrangedNodes[*EndNodeIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartWidgetGeometry = PinGeometries->Find(OutputPinWidget);
|
||||||
|
|
||||||
|
if (TSharedPtr<SGraphPin>* pTargetWidget = PinToPinWidgetMap.Find(InputPin))
|
||||||
|
{
|
||||||
|
TSharedRef<SGraphPin> InputWidget = (*pTargetWidget).ToSharedRef();
|
||||||
|
EndWidgetGeometry = PinGeometries->Find(InputWidget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FConnectionDrawingPolicy_ComboActionGraph::Internal_DrawLineWithArrow(const FVector2D &StartAnchorPoint, const FVector2D &EndAnchorPoint, const FConnectionParams &Params)
|
||||||
|
{
|
||||||
|
const float LineSeparationAmount = 4.5f;
|
||||||
|
|
||||||
|
const FVector2D DeltaPos = EndAnchorPoint - StartAnchorPoint;
|
||||||
|
const FVector2D UnitDelta = DeltaPos.GetSafeNormal();
|
||||||
|
const FVector2D Normal = FVector2D(DeltaPos.Y, -DeltaPos.X).GetSafeNormal();
|
||||||
|
|
||||||
|
// Come up with the final start/end points
|
||||||
|
const FVector2D DirectionBias = Normal * LineSeparationAmount;
|
||||||
|
const FVector2D LengthBias = ArrowRadius.X * UnitDelta;
|
||||||
|
const FVector2D StartPoint = StartAnchorPoint + DirectionBias + LengthBias;
|
||||||
|
const FVector2D EndPoint = EndAnchorPoint + DirectionBias - LengthBias;
|
||||||
|
|
||||||
|
// Draw a line/spline
|
||||||
|
DrawConnection(WireLayerID, StartPoint, EndPoint, Params);
|
||||||
|
|
||||||
|
// Draw the arrow
|
||||||
|
if (ArrowImage)
|
||||||
|
{
|
||||||
|
const FVector2D ArrowDrawPos = EndPoint - ArrowRadius;
|
||||||
|
const float AngleInRadians = FMath::Atan2(DeltaPos.Y, DeltaPos.X);
|
||||||
|
|
||||||
|
FSlateDrawElement::MakeRotatedBox(
|
||||||
|
DrawElementsList,
|
||||||
|
ArrowLayerID,
|
||||||
|
FPaintGeometry(ArrowDrawPos, ArrowImage->ImageSize * ZoomFactor, ZoomFactor),
|
||||||
|
ArrowImage,
|
||||||
|
ESlateDrawEffect::None,
|
||||||
|
AngleInRadians,
|
||||||
|
TOptional<FVector2D>(),
|
||||||
|
FSlateDrawElement::RelativeToElement,
|
||||||
|
Params.WireColor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "BlueprintConnectionDrawingPolicy.h"
|
||||||
|
#include "ConnectionDrawingPolicy.h"
|
||||||
|
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(LogConnectionDrawingPolicy_ComboActionGraph, Log, All);
|
||||||
|
|
||||||
|
|
||||||
|
class FConnectionDrawingPolicy_ComboActionGraph : public FKismetConnectionDrawingPolicy
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
FConnectionDrawingPolicy_ComboActionGraph(int32 InBackLayerID, int32 InFrontLayerID, float ZoomFactor, const FSlateRect& InClippingRect, FSlateWindowElementList& InDrawElements, UEdGraph* InGraphObj);
|
||||||
|
virtual ~FConnectionDrawingPolicy_ComboActionGraph() {};
|
||||||
|
|
||||||
|
// FConnectionDrawingPolicy interface
|
||||||
|
virtual void DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ FConnectionParams& Params) override;
|
||||||
|
virtual void Draw(TMap<TSharedRef<SWidget>, FArrangedWidget>& InPinGeometries, FArrangedChildren& ArrangedNodes) override;
|
||||||
|
virtual void DrawSplineWithArrow(const FGeometry& StartGeom, const FGeometry& EndGeom, const FConnectionParams& Params) override;
|
||||||
|
virtual void DrawSplineWithArrow(const FVector2D& StartPoint, const FVector2D& EndPoint, const FConnectionParams& Params) override;
|
||||||
|
virtual void DrawPreviewConnector(const FGeometry& PinGeometry, const FVector2D& StartPoint, const FVector2D& EndPoint, UEdGraphPin* Pin) override;
|
||||||
|
virtual FVector2D ComputeSplineTangent(const FVector2D& Start, const FVector2D& End) const override;
|
||||||
|
virtual void DetermineLinkGeometry(FArrangedChildren& ArrangedNodes, TSharedRef<SWidget>& OutputPinWidget, UEdGraphPin* OutputPin, UEdGraphPin* InputPin, FArrangedWidget*& StartWidgetGeometry, FArrangedWidget*& EndWidgetGeometry) override;
|
||||||
|
// End of FConnectionDrawingPolicy interface
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Internal_DrawLineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UEdGraph *GraphObj;
|
||||||
|
TMap<UEdGraphNode*, int32> NodeWidgetMap;
|
||||||
|
|
||||||
|
};
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
#include "Ed/EdComboActionGraphNode.h"
|
||||||
|
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||||
|
#include "Nodes/ComboActionGraphNode.h"
|
||||||
|
#include "Nodes/ComboActionGraphNode_ActionNodeBase.h"
|
||||||
|
#include "Settings/ComboActionGraphEditorSettings.h"
|
||||||
|
|
||||||
|
#include "ComboActionEditorBFC.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor Only helper functions.
|
||||||
|
*/
|
||||||
|
UCLASS()
|
||||||
|
class UComboActionEditorBFC : public UBlueprintFunctionLibrary
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
static FText GetNodeTitle(UComboActionGraphNode *Node)
|
||||||
|
{
|
||||||
|
if (!Node) return FText::FromString("Invalid Node");
|
||||||
|
|
||||||
|
const UComboActionGraphEditorSettings *Settings = GetDefault<UComboActionGraphEditorSettings>();
|
||||||
|
if (Settings)
|
||||||
|
{
|
||||||
|
if (Settings->ShowAutomaticNames())
|
||||||
|
{
|
||||||
|
if (const UComboActionGraphNode_ActionNodeBase *DialogueNodeBase = Cast<UComboActionGraphNode_ActionNodeBase>(Node))
|
||||||
|
{
|
||||||
|
if (DialogueNodeBase->GetDataTable())
|
||||||
|
{
|
||||||
|
FString ReturnString;
|
||||||
|
DialogueNodeBase->GetRowName().ToString(ReturnString);
|
||||||
|
|
||||||
|
return FText::FromString(ReturnString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Node->GetInternalName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Node->GetNodeTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
static EComboActionNodeTheme GetNodeTheme()
|
||||||
|
{
|
||||||
|
const UComboActionGraphEditorSettings *Settings = GetDefault<UComboActionGraphEditorSettings>();
|
||||||
|
if (Settings != nullptr)
|
||||||
|
{
|
||||||
|
return Settings->GetNodeTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
return EComboActionNodeTheme::DarkTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TriggerPreviewRefresh(TArray<UObject*> NodeObjects)
|
||||||
|
{
|
||||||
|
for (auto Itr : NodeObjects)
|
||||||
|
{
|
||||||
|
UEdComboActionGraphNode *SelectedNode = Cast<UEdComboActionGraphNode>(Itr);
|
||||||
|
if (!SelectedNode || !SelectedNode->ComboActionGraphNode)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
UComboActionGraphNode_ActionNodeBase *DialogueNodeBase = Cast<UComboActionGraphNode_ActionNodeBase>(SelectedNode->ComboActionGraphNode);
|
||||||
|
if (!DialogueNodeBase)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogueNodeBase->UpdatePreviews();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
namespace ComboActionGraphColors
|
||||||
|
{
|
||||||
|
namespace NodeBody
|
||||||
|
{
|
||||||
|
constexpr FLinearColor Default(0.1f, 0.1f, 0.1f);
|
||||||
|
constexpr FLinearColor Root(0.5f, 0.5f, 0.5f, 0.1f);
|
||||||
|
constexpr FLinearColor Error(1.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace DecoratorsBody
|
||||||
|
{
|
||||||
|
constexpr FLinearColor Default(0.1f, 0.1f, 0.1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace NodeBorder
|
||||||
|
{
|
||||||
|
constexpr FLinearColor Inactive(0.08f, 0.08f, 0.08f);
|
||||||
|
constexpr FLinearColor Root(0.2f, 0.2f, 0.2f, 0.2f);
|
||||||
|
constexpr FLinearColor Selected(1.00f, 0.08f, 0.08f);
|
||||||
|
constexpr FLinearColor ActiveDebugging(1.0f, 1.0f, 0.0f);
|
||||||
|
constexpr FLinearColor InactiveDebugging(0.4f, 0.4f, 0.0f);
|
||||||
|
constexpr FLinearColor HighlightAbortRange0(0.0f, 0.22f, 0.4f);
|
||||||
|
constexpr FLinearColor HighlightAbortRange1(0.0f, 0.4f, 0.22f);
|
||||||
|
constexpr FLinearColor Disconnected(0.f, 0.f, 0.f);
|
||||||
|
constexpr FLinearColor BrokenWithParent(1.f, 0.f, 1.f);
|
||||||
|
constexpr FLinearColor QuickFind(0.f, 0.8f, 0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Pin
|
||||||
|
{
|
||||||
|
constexpr FLinearColor Diff(0.9f, 0.2f, 0.15f);
|
||||||
|
constexpr FLinearColor Hover(1.0f, 0.7f, 0.0f);
|
||||||
|
constexpr FLinearColor Default(0.02f, 0.02f, 0.02f);
|
||||||
|
constexpr FLinearColor SingleNode(0.02f, 0.02f, 0.02f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Connection
|
||||||
|
{
|
||||||
|
constexpr FLinearColor Default(1.0f, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Action
|
||||||
|
{
|
||||||
|
constexpr FLinearColor DragMarker(1.0f, 1.0f, 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Overlay
|
||||||
|
{
|
||||||
|
constexpr FLinearColor LightTheme(1.f, 1.f, 1.f, 0.45f);
|
||||||
|
constexpr FLinearColor DarkTheme(0.f, 0.f, 0.f, 0.9f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace PinsDock
|
||||||
|
{
|
||||||
|
constexpr FLinearColor DarkTheme(0.075f, 0.075f, 0.075f, 1.f);
|
||||||
|
constexpr FLinearColor LightTheme(0.075f, 0.075f, 0.075f, 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ValidationGraph
|
||||||
|
{
|
||||||
|
constexpr FLinearColor LightTheme(0.1f, 0.1f, 0.1f, 1.f);
|
||||||
|
constexpr FLinearColor DarkTheme(0.05f, 0.05f, 0.05f, 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace IndexBorder
|
||||||
|
{
|
||||||
|
constexpr FLinearColor NormalState(0.05f, 0.05f, 0.05f, 1.f);
|
||||||
|
constexpr FLinearColor HoveredState(0.05f, 0.05f, 0.05f, 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BulletPointsColors
|
||||||
|
{
|
||||||
|
constexpr FLinearColor Normal(0.8f, 0.8f, 0.8f, 1.f);
|
||||||
|
constexpr FLinearColor Disabled(0.8f, 0.8f, 0.8f, 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace TextColors
|
||||||
|
{
|
||||||
|
constexpr FLinearColor Normal(0.8f, 0.8f, 0.8f, 1.f);
|
||||||
|
constexpr FLinearColor Disabled(0.8f, 0.8f, 0.8f, 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Previews
|
||||||
|
{
|
||||||
|
constexpr FLinearColor Normal(0.8f, 0.8f, 0.8f, 0.05f);
|
||||||
|
constexpr FLinearColor Invalid(0.8f, 0.8f, 0.8f, 0.2f);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "ComboActionGraphEditorSettings.h"
|
||||||
|
|
||||||
|
#define LOCTEXT_NAMESPACE "ComboActionGraphEditorSettings"
|
||||||
|
|
||||||
|
|
||||||
|
UComboActionGraphEditorSettings::UComboActionGraphEditorSettings()
|
||||||
|
{
|
||||||
|
NodeType = EComboActionNodeType::SoftCorners;
|
||||||
|
NodeTheme = EComboActionNodeTheme::DarkTheme;
|
||||||
|
ArrowType = EComboActionArrowType::HollowArrow;
|
||||||
|
|
||||||
|
CategoryName = TEXT("Combo Input");
|
||||||
|
SectionName = TEXT("Combo Input (Editor)");
|
||||||
|
|
||||||
|
AutoLayoutStrategy = EComboActionAutoLayoutStrategyType::Tree;
|
||||||
|
|
||||||
|
bFirstPassOnly = false;
|
||||||
|
bRandomInit = false;
|
||||||
|
OptimalDistance = 100.f;
|
||||||
|
MaxIteration = 50;
|
||||||
|
InitTemperature = 10.f;
|
||||||
|
CoolDownRate = 10.f;
|
||||||
|
|
||||||
|
WireWidth = 0.8f;
|
||||||
|
//WireStyle = EWiringStyle::EWS_Simple;
|
||||||
|
//BubbleDrawRule = EBubbleDrawRule::EBDR_OnSelected;
|
||||||
|
|
||||||
|
bAllowRenameNodes = true;
|
||||||
|
bDisplayAutomaticNames = false;
|
||||||
|
|
||||||
|
bShowDetailedInfo_InheritsDecorators = true;
|
||||||
|
bShowDetailedInfo_NumDecorators = true;
|
||||||
|
DecoratorsInfoStyle = EComboActionDecoratorsInfoStyle::Unified;
|
||||||
|
|
||||||
|
bAllowNativeDecoratorsEdit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef LOCTEXT_NAMESPACE
|
||||||
@ -0,0 +1,292 @@
|
|||||||
|
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Engine/DeveloperSettings.h"
|
||||||
|
|
||||||
|
#include "ComboActionGraphEditorSettings.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
#pragma region Enums
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EComboActionAutoLayoutStrategyType : uint8
|
||||||
|
{
|
||||||
|
Tree UMETA(DisplayName="Tree"),
|
||||||
|
ForceDirected UMETA(DisplayName="Force Directed"),
|
||||||
|
|
||||||
|
Default UMETA(Hidden)
|
||||||
|
};
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EComboActionWiringStyle : uint8
|
||||||
|
{
|
||||||
|
Vanilla UMETA(DisplayName="Vanilla"),
|
||||||
|
Simple UMETA(DisplayName="90° Angle"),
|
||||||
|
Complex UMETA(DisplayName="45° Angle"),
|
||||||
|
|
||||||
|
Default UMETA(Hidden)
|
||||||
|
};
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EComboActionBubbleDrawRule : uint8
|
||||||
|
{
|
||||||
|
Always UMETA(DisplayName="Always"),
|
||||||
|
OnSelected UMETA(DisplayName="When Selected")
|
||||||
|
};
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EComboActionNodeTheme : uint8
|
||||||
|
{
|
||||||
|
DarkTheme UMETA(DisplayName="Dark Theme"),
|
||||||
|
LightTheme UMETA(DisplayName="Light Theme")
|
||||||
|
};
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EComboActionDecoratorsInfoStyle : uint8
|
||||||
|
{
|
||||||
|
Stack UMETA(DisplayName="Stack"),
|
||||||
|
Unified UMETA(DisplayName="Unified")
|
||||||
|
};
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EComboActionNodeType : uint8
|
||||||
|
{
|
||||||
|
SoftCorners UMETA(DisplayName="Soft Corners"),
|
||||||
|
HardCorners UMETA(DisplayName="Hard Corners")
|
||||||
|
};
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EComboActionArrowType : uint8
|
||||||
|
{
|
||||||
|
SimpleArrow UMETA(DisplayName="Simple Arrow"),
|
||||||
|
HollowArrow UMETA(DisplayName="Hollow Arrow"),
|
||||||
|
FancyArrow UMETA(DisplayName="Fancy Arrow"),
|
||||||
|
Bubble UMETA(DisplayName="Bubble"),
|
||||||
|
None UMETA(DisplayName="Nothing")
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combo Action Graph global settings.
|
||||||
|
*/
|
||||||
|
UCLASS(config = MounteaSettings)
|
||||||
|
class COMBOINPUT_API UComboActionGraphEditorSettings : public UDeveloperSettings
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UComboActionGraphEditorSettings();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
#pragma region GraphNodes
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodesSettings")
|
||||||
|
EComboActionNodeType NodeType;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodesSettings")
|
||||||
|
EComboActionNodeTheme NodeTheme;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodesSettings|DecoratorsInfo")
|
||||||
|
uint8 bShowDetailedInfo_NumDecorators : 1;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodesSettings|DecoratorsInfo")
|
||||||
|
uint8 bShowDetailedInfo_InheritsDecorators : 1;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodesSettings")
|
||||||
|
EComboActionDecoratorsInfoStyle DecoratorsInfoStyle;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodesSettings")
|
||||||
|
bool bDisplayAutomaticNames;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodesSettings")
|
||||||
|
bool bAllowRenameNodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a Node Class and specify Override Colour for this Node type.
|
||||||
|
* Only non-abstract classes are allowed!
|
||||||
|
*/
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodesSettings", meta=(ShowTreeView))
|
||||||
|
TMap<TSoftClassPtr<class UComboActionGraphNode>, FLinearColor> OverrideNodeBackgroundColours;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region GraphDecorators
|
||||||
|
|
||||||
|
// Enables 'Edit' button for Native Code Decorators
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodesSettings")
|
||||||
|
bool bAllowNativeDecoratorsEdit;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region GraphWiring
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", meta=(UIMin=0.1f, ClampMin=0.1f, UIMax=1.5f, ClampMax=1.5f))
|
||||||
|
float WireWidth;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring") //, meta=(ConfigRestartRequired=true))
|
||||||
|
EComboActionArrowType ArrowType;
|
||||||
|
|
||||||
|
/* Advanced Wiring doesn't work now
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta=(ToolTip="Work in Progress!"))
|
||||||
|
bool bUseAdvancedWiring;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta=(ToolTip="Work in Progress!", EditCondition="bUseAdvancedWiring"))
|
||||||
|
EWiringStyle WireStyle;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta=(ToolTip="Work in Progress!", EditCondition="bUseAdvancedWiring"))
|
||||||
|
uint32 HorizontalOffset = 16;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta=(ToolTip="Work in Progress!", EditCondition="bUseAdvancedWiring"))
|
||||||
|
EBubbleDrawRule BubbleDrawRule;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta=(ToolTip="Work in Progress!", EditCondition="bUseAdvancedWiring"))
|
||||||
|
int32 BubbleZoomThreshold;
|
||||||
|
|
||||||
|
// Space between bubbles on the wires. Default: 20.0
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta = (ClampMin = "10.0", ToolTip="Work in Progress!", EditCondition="bUseAdvancedWiring"))
|
||||||
|
float BubbleSpace = 20.0f;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta = (ClampMin = "10.0", ToolTip="Work in Progress!", EditCondition="bUseAdvancedWiring"))
|
||||||
|
float BubbleSize = 2.0f;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta = (ClampMin = "10.0", ToolTip="Work in Progress!", EditCondition="bUseAdvancedWiring"))
|
||||||
|
float BubbleSpeed = 2.0f;
|
||||||
|
|
||||||
|
// Disable the offset for pins. Default: false
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta=(ToolTip="Work in Progress!", EditCondition="bUseAdvancedWiring"))
|
||||||
|
bool DisablePinOffset = false;
|
||||||
|
|
||||||
|
// Fix default zoomed-out wire displacement. Default: true
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "NodeWiring", AdvancedDisplay, meta=(ToolTip="Work in Progress!", EditCondition="bUseAdvancedWiring"))
|
||||||
|
bool FixZoomDisplacement = true;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region GraphArrange
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, Category = "AutoArrange")
|
||||||
|
float OptimalDistance;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, AdvancedDisplay, Category = "AutoArrange")
|
||||||
|
EComboActionAutoLayoutStrategyType AutoLayoutStrategy;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, AdvancedDisplay, Category = "AutoArrange")
|
||||||
|
int32 MaxIteration;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, AdvancedDisplay, Category = "AutoArrange")
|
||||||
|
bool bFirstPassOnly;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, AdvancedDisplay, Category = "AutoArrange")
|
||||||
|
bool bRandomInit;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, AdvancedDisplay, Category = "AutoArrange")
|
||||||
|
float InitTemperature;
|
||||||
|
|
||||||
|
UPROPERTY(config, EditDefaultsOnly, AdvancedDisplay, Category = "AutoArrange")
|
||||||
|
float CoolDownRate;
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#if WITH_EDITOR
|
||||||
|
virtual FText GetSectionText() const override
|
||||||
|
{
|
||||||
|
return NSLOCTEXT("ComboActionGraphEditorSystem", "ComboActionGraphEditorSection", "Combo Action Graph (Editor)");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual FText GetSectionDescription() const override
|
||||||
|
{
|
||||||
|
return NSLOCTEXT("ComboActionGraphEditorSystem", "ComboActionGraphEditorDescription", "Default values for Mountea Plugins (Editor).");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual FName GetContainerName() const override
|
||||||
|
{
|
||||||
|
return "Project";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
#pragma region GraphNodes_Getters
|
||||||
|
|
||||||
|
EComboActionNodeTheme GetNodeTheme() const { return NodeTheme; }
|
||||||
|
EComboActionNodeType GetNodeType() const { return NodeType; }
|
||||||
|
bool ShowDetailedInfo_NumDecorators() const { return bShowDetailedInfo_NumDecorators; }
|
||||||
|
bool ShowDetailedInfo_InheritsDecorators() const { return bShowDetailedInfo_InheritsDecorators; }
|
||||||
|
bool ShowAutomaticNames() const { return bDisplayAutomaticNames; }
|
||||||
|
EComboActionDecoratorsInfoStyle GetDecoratorsStyle() const { return DecoratorsInfoStyle; }
|
||||||
|
bool AllowRenameNodes() const { return bAllowRenameNodes; }
|
||||||
|
|
||||||
|
bool FindNodeBackgroundColourOverride(const TSoftClassPtr<class UComboActionGraphNode> NodeClass, FLinearColor& BackgroundColour)
|
||||||
|
{
|
||||||
|
if (OverrideNodeBackgroundColours.Contains(NodeClass))
|
||||||
|
{
|
||||||
|
BackgroundColour = *OverrideNodeBackgroundColours.Find(NodeClass);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region GraphDecorators_Getters
|
||||||
|
|
||||||
|
bool IsNativeDecoratorsEditAllowed() const { return bAllowNativeDecoratorsEdit; }
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
#pragma region GraphWiring_Getters
|
||||||
|
|
||||||
|
float GetWireWidth() const { return this->WireWidth; }
|
||||||
|
|
||||||
|
EComboActionArrowType GetArrowType() const { return this->ArrowType; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool AllowAdvancedWiring() const
|
||||||
|
{ return bUseAdvancedWiring; };
|
||||||
|
|
||||||
|
EWiringStyle GetWireStyle() const
|
||||||
|
{ return WireStyle; };
|
||||||
|
|
||||||
|
int32 GetHorizontalOffset() const
|
||||||
|
{ return HorizontalOffset; };
|
||||||
|
|
||||||
|
EBubbleDrawRule GetBubbleDrawRule() const
|
||||||
|
{ return BubbleDrawRule; };
|
||||||
|
|
||||||
|
int32 GetBubbleZoomThreshold() const
|
||||||
|
{ return BubbleZoomThreshold; };
|
||||||
|
|
||||||
|
float GetBubbleSpace() const
|
||||||
|
{ return BubbleSpace; };
|
||||||
|
|
||||||
|
float GetBubbleSpeed() const
|
||||||
|
{ return BubbleSpeed; };
|
||||||
|
|
||||||
|
float GetBubbleSize() const
|
||||||
|
{ return BubbleSize; };
|
||||||
|
*/
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
#pragma region GraphArrange_Getters
|
||||||
|
|
||||||
|
EComboActionAutoLayoutStrategyType GetAutoLayoutStrategy() const { return this->AutoLayoutStrategy; }
|
||||||
|
float GetOptimalDistance() const { return this->OptimalDistance; }
|
||||||
|
int32 GetMaxIteration() const { return this->MaxIteration; }
|
||||||
|
bool IsFirstPassOnly() const { return this->bFirstPassOnly; }
|
||||||
|
bool IsRandomInit() const { return this->bRandomInit; }
|
||||||
|
float GetInitTemperature() const { return this->InitTemperature; }
|
||||||
|
float GetCoolDownRate() const { return this->CoolDownRate; }
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
};
|
||||||
|
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
// Copyright Dominik Pavlicek 2023. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "FComboActionGraphEditorStyle.h"
|
||||||
|
|
||||||
|
#include "Interfaces/IPluginManager.h"
|
||||||
|
#include "Misc/Paths.h"
|
||||||
|
#include "Styling/SlateStyleRegistry.h"
|
||||||
|
|
||||||
|
#define IMAGE_BRUSH(RelativePath, ...) FSlateImageBrush(StyleSet->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)
|
||||||
|
#define BOX_BRUSH(RelativePath, ...) FSlateBoxBrush(StyleSet->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)
|
||||||
|
#define DEFAULT_FONT(...) FCoreStyle::GetDefaultFontStyle(__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
TSharedPtr<FSlateStyleSet> FComboActionGraphEditorStyle::StyleSet = nullptr;
|
||||||
|
|
||||||
|
void FComboActionGraphEditorStyle::Initialize()
|
||||||
|
{
|
||||||
|
if (!StyleSet.IsValid() )
|
||||||
|
{
|
||||||
|
Create();
|
||||||
|
FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FComboActionGraphEditorStyle::Shutdown()
|
||||||
|
{
|
||||||
|
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleSet.Get());
|
||||||
|
ensure(StyleSet.IsUnique());
|
||||||
|
StyleSet.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FComboActionGraphEditorStyle::Create()
|
||||||
|
{
|
||||||
|
const FVector2D Icon12x12(12.0f, 12.0f);
|
||||||
|
const FVector2D Icon16x16(16.0f, 16.0f);
|
||||||
|
const FVector2D Icon40x40(40.0f, 40.0f);
|
||||||
|
const FVector2D Icon64x64(64.0f, 64.0f);
|
||||||
|
const FVector2D Icon128x128(128.f, 128.f);
|
||||||
|
const FVector2D Icon200x70(200.f, 70.f);
|
||||||
|
|
||||||
|
StyleSet = MakeShareable(new FSlateStyleSet(GetAppStyleSetName()));
|
||||||
|
StyleSet->SetContentRoot(IPluginManager::Get().FindPlugin("ComboInput")->GetBaseDir() / TEXT("Resources"));
|
||||||
|
StyleSet->SetCoreContentRoot(IPluginManager::Get().FindPlugin("ComboInput")->GetBaseDir() / TEXT("Content"));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.AutoArrange.small", new IMAGE_BRUSH(TEXT("AutoArrangeIcon"), Icon16x16));
|
||||||
|
StyleSet->Set("MDSStyleSet.AutoArrange", new IMAGE_BRUSH(TEXT("AutoArrangeIcon"), Icon40x40));
|
||||||
|
StyleSet->Set("MDSStyleSet.AutoArrange.large", new IMAGE_BRUSH(TEXT("AutoArrangeIcon"), Icon64x64));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.GraphSettings.small", new IMAGE_BRUSH(TEXT("GraphSettings"), Icon16x16));
|
||||||
|
StyleSet->Set("MDSStyleSet.GraphSettings", new IMAGE_BRUSH(TEXT("GraphSettings"), Icon40x40));
|
||||||
|
StyleSet->Set("MDSStyleSet.GraphSettings.large", new IMAGE_BRUSH(TEXT("GraphSettings"), Icon64x64));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.ValidateGraph.small", new IMAGE_BRUSH(TEXT("ValidateGraph"), Icon16x16));
|
||||||
|
StyleSet->Set("MDSStyleSet.ValidateGraph", new IMAGE_BRUSH(TEXT("ValidateGraph"), Icon40x40));
|
||||||
|
StyleSet->Set("MDSStyleSet.ValidateGraph.large", new IMAGE_BRUSH(TEXT("ValidateGraph"), Icon64x64));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Graph.NodeOverlay", new BOX_BRUSH( TEXT("NodeOverlay"), FMargin(8.0f/64.0f, 3.0f/32.0f, 0, 0) ));
|
||||||
|
StyleSet->Set("MDSStyleSet.Graph.PinDocksOverlay", new BOX_BRUSH( TEXT("PinDocksOverlay"), FMargin(8.0f/64.0f, 3.0f/32.0f, 0, 0) ));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Graph.SimpleArrow", new IMAGE_BRUSH(TEXT("SimpleArrow"), Icon16x16));
|
||||||
|
StyleSet->Set("MDSStyleSet.Graph.HollowArrow", new IMAGE_BRUSH(TEXT("HollowArrow"), Icon16x16));
|
||||||
|
StyleSet->Set("MDSStyleSet.Graph.FancyArrow", new IMAGE_BRUSH(TEXT("FancyArrow"), Icon16x16));
|
||||||
|
StyleSet->Set("MDSStyleSet.Graph.Bubble", new IMAGE_BRUSH(TEXT("Bubble"), Icon16x16));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Node.SoftEdges", new BOX_BRUSH( TEXT("NodeSoftCorners") , FMargin(16.f/64.f, 25.f/64.f, 16.f/64.f, 16.f/64.f) ));
|
||||||
|
StyleSet->Set("MDSStyleSet.Node.HardEdges", new BOX_BRUSH( TEXT("NodeHardCorners") , FMargin(16.f/64.f, 25.f/64.f, 16.f/64.f, 16.f/64.f) ));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Node.TextSoftEdges", new BOX_BRUSH( TEXT("TextSoftCorners") , FMargin(16.f/64.f, 25.f/64.f, 16.f/64.f, 16.f/64.f) ));
|
||||||
|
StyleSet->Set("MDSStyleSet.Node.TextHardEdges", new BOX_BRUSH( TEXT("TextHardCorners") , FMargin(16.f/64.f, 25.f/64.f, 16.f/64.f, 16.f/64.f) ));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Node.IndexCircle", new IMAGE_BRUSH(TEXT("IndexIcon"), Icon16x16));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.OK", new IMAGE_BRUSH(TEXT("OKIcon"), Icon16x16));
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.Error", new IMAGE_BRUSH(TEXT("ErroIcon"), Icon16x16));
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.BulletPoint", new IMAGE_BRUSH(TEXT("CircleBox"), Icon16x16));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Graph.CornerImage", new IMAGE_BRUSH(TEXT("Icon128"), Icon128x128));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.Browse", new IMAGE_BRUSH(TEXT("BrowseIcon"), Icon12x12));
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.Edit", new IMAGE_BRUSH(TEXT("EditIcon"), Icon12x12));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Buttons.Documentation", new IMAGE_BRUSH(TEXT("Documentation"), Icon200x70));
|
||||||
|
StyleSet->Set("MDSStyleSet.Buttons.Documentation.small", new IMAGE_BRUSH(TEXT("DocumentationIcon"), Icon12x12));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Node.Icon.large", new IMAGE_BRUSH(TEXT("DialogueNodeIcon"), Icon64x64));
|
||||||
|
StyleSet->Set("MDSStyleSet.Node.Icon", new IMAGE_BRUSH(TEXT("DialogueNodeIcon"), Icon16x16));
|
||||||
|
StyleSet->Set("MDSStyleSet.Node.Icon.small", new IMAGE_BRUSH(TEXT("DialogueNodeIcon"), Icon12x12));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.Close", new IMAGE_BRUSH(TEXT("CloseIcon"), Icon12x12));
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.SupportDiscord", new IMAGE_BRUSH(TEXT("DiscordIcon"), Icon12x12));
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.HeartIcon", new IMAGE_BRUSH(TEXT("HeartIcon"), Icon12x12));
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.UBIcon", new IMAGE_BRUSH(TEXT("UnrealBucketIcon"), Icon12x12));
|
||||||
|
StyleSet->Set("MDSStyleSet.Icon.MoneyIcon", new IMAGE_BRUSH(TEXT("MoneyIcon"), Icon12x12));
|
||||||
|
|
||||||
|
const FButtonStyle MounteaButtonStyle = FButtonStyle()
|
||||||
|
.SetNormal(BOX_BRUSH("RoundedSelection_16x", 4.0f / 16.0f, FLinearColor(1, 1, 1, 0.1f)))
|
||||||
|
.SetHovered(BOX_BRUSH("RoundedSelection_16x", 4.0f / 16.0f, FLinearColor(1, .55f, 0, 0.2f)))
|
||||||
|
.SetPressed(BOX_BRUSH("RoundedSelection_16x", 4.0f / 16.0f, FLinearColor(1, .55f, 0, 0.4f)));
|
||||||
|
|
||||||
|
StyleSet->Set("MDSStyleSet.Buttons.Style", MounteaButtonStyle);
|
||||||
|
|
||||||
|
{
|
||||||
|
const FScrollBarStyle ScrollBar = GetWidgetStyle<FScrollBarStyle>( "ScrollBar" );
|
||||||
|
|
||||||
|
FTextBlockStyle NormalText = FTextBlockStyle()
|
||||||
|
.SetFont(DEFAULT_FONT("Regular", FCoreStyle::RegularTextSize))
|
||||||
|
.SetColorAndOpacity(FSlateColor::UseForeground())
|
||||||
|
.SetShadowOffset(FVector2D::ZeroVector)
|
||||||
|
.SetShadowColorAndOpacity(FLinearColor::Black)
|
||||||
|
.SetHighlightColor( FLinearColor( 0.02f, 0.3f, 0.0f ) )
|
||||||
|
.SetHighlightShape( BOX_BRUSH( "TextBlockHighlightShape", FMargin(3.f/8.f) ) );
|
||||||
|
|
||||||
|
FTextBlockStyle NodeTitle = FTextBlockStyle(NormalText)
|
||||||
|
.SetFont( DEFAULT_FONT( "Bold", 14 ) )
|
||||||
|
.SetColorAndOpacity( FLinearColor(230.0f/255.0f,230.0f/255.0f,230.0f/255.0f) )
|
||||||
|
.SetShadowOffset( FVector2D( 2,2 ) )
|
||||||
|
.SetShadowColorAndOpacity( FLinearColor(0.f,0.f,0.f, 0.7f) );
|
||||||
|
StyleSet->Set( "MDSStyleSet.NodeTitle", NodeTitle );
|
||||||
|
|
||||||
|
FEditableTextBoxStyle NodeTitleEditableText = FEditableTextBoxStyle()
|
||||||
|
.SetFont(NormalText.Font)
|
||||||
|
.SetBackgroundImageNormal( BOX_BRUSH( "TextBox", FMargin(4.0f/16.0f) ) )
|
||||||
|
.SetBackgroundImageHovered( BOX_BRUSH( "TextBox_Hovered", FMargin(4.0f/16.0f) ) )
|
||||||
|
.SetBackgroundImageFocused( BOX_BRUSH( "TextBox_Hovered", FMargin(4.0f/16.0f) ) )
|
||||||
|
.SetBackgroundImageReadOnly( BOX_BRUSH( "TextBox_ReadOnly", FMargin(4.0f/16.0f) ) )
|
||||||
|
.SetScrollBarStyle( ScrollBar );
|
||||||
|
StyleSet->Set( "MDSStyleSet.NodeTitleEditableText", NodeTitleEditableText );
|
||||||
|
|
||||||
|
StyleSet->Set( "MDSStyleSet.NodeTitleInlineEditableText", FInlineEditableTextBlockStyle()
|
||||||
|
.SetTextStyle(NodeTitle)
|
||||||
|
.SetEditableTextBoxStyle(NodeTitleEditableText)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef DEFAULT_FONT
|
||||||
|
#undef BOX_BRUSH
|
||||||
|
#undef IMAGE_BRUSH
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright Dominik Pavlicek 2023. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Styling/SlateStyle.h"
|
||||||
|
|
||||||
|
|
||||||
|
class FComboActionGraphEditorStyle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static void Create();
|
||||||
|
static void Initialize();
|
||||||
|
static void Shutdown();
|
||||||
|
static ISlateStyle &Get()
|
||||||
|
{
|
||||||
|
return *(StyleSet.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static const FSlateBrush *GetBrush(FName PropertyName, const ANSICHAR *Specifier = NULL)
|
||||||
|
{
|
||||||
|
return StyleSet->GetBrush(PropertyName, Specifier);
|
||||||
|
};
|
||||||
|
|
||||||
|
static const FName &GetAppStyleSetName()
|
||||||
|
{
|
||||||
|
static FName StyleSetName(TEXT("ComboActionGraphEditorStyle"));
|
||||||
|
return StyleSetName;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< class T >
|
||||||
|
static const T &GetWidgetStyle( FName PropertyName, const ANSICHAR *Specifier = NULL )
|
||||||
|
{
|
||||||
|
return StyleSet->GetWidgetStyle< T >( PropertyName, Specifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static TSharedPtr<FSlateStyleSet> StyleSet;
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user