256 lines
5.3 KiB
C++
256 lines
5.3 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Templates/Casts.h"
|
|
#include "UObject/UObjectBaseUtility.h"
|
|
|
|
/*
|
|
* A stack describing the model object which led to this invocation.
|
|
* Objects on the stack can be URigVMGraph or URigVMNode.
|
|
*/
|
|
class RIGVMDEVELOPER_API FRigVMCallstack
|
|
{
|
|
public:
|
|
|
|
// Returns the path
|
|
FString GetCallPath(bool bIncludeLast = true) const;
|
|
|
|
// Returns the number of entries on this callstack
|
|
int32 Num() const;
|
|
|
|
// Returns the last object in the callstack
|
|
const UObject* Last() const;
|
|
|
|
// Returns the element at a given index
|
|
const UObject* operator[](int32 InIndex) const;
|
|
|
|
// Returns true if the stack contains a given entry
|
|
bool Contains(const UObject* InEntry) const;
|
|
|
|
friend uint32 GetTypeHash(const FRigVMCallstack& Callstack)
|
|
{
|
|
return Callstack.GetEntryTypeHash(Callstack.Num() - 1);
|
|
}
|
|
|
|
bool operator ==(const FRigVMCallstack& Other) const
|
|
{
|
|
if (Num() == Other.Num())
|
|
{
|
|
for (int32 Index = 0; Index < Num(); Index++)
|
|
{
|
|
if (operator[](Index) != Other[Index])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool operator !=(const FRigVMCallstack& Other) const
|
|
{
|
|
return !(*this == Other);
|
|
}
|
|
|
|
bool operator <(const FRigVMCallstack& Other) const
|
|
{
|
|
if (Num() < Other.Num())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (Num() > Other.Num())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (Num() == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return operator[](0) < Other[0];
|
|
}
|
|
|
|
bool operator >(const FRigVMCallstack& Other) const
|
|
{
|
|
if (Num() > Other.Num())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (Num() < Other.Num())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (Num() == 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return operator[](0) > Other[0];
|
|
}
|
|
|
|
TArray<TWeakObjectPtr<UObject>> GetStack() const { return Stack; }
|
|
|
|
FRigVMCallstack GetCallStackUpTo(int32 InIndex) const;
|
|
|
|
private:
|
|
|
|
uint32 GetEntryTypeHash(int32 Index) const
|
|
{
|
|
if (Index < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
if (Index == 0)
|
|
{
|
|
return GetTypeHash(Stack[Index]);
|
|
}
|
|
return HashCombine(GetEntryTypeHash(Index - 1), GetTypeHash(Stack[Index]));
|
|
}
|
|
|
|
TArray<TWeakObjectPtr<UObject>> Stack;
|
|
|
|
friend class FRigVMParserAST;
|
|
friend class FRigVMCallstackGuard;
|
|
friend class FRigVMASTProxy;
|
|
friend class URigVMCompiler;
|
|
};
|
|
|
|
/*
|
|
* A proxy which describes an occurence of a subject within
|
|
* a graph. The subject can be a pin, a node, a link, etc.
|
|
* The context is the callstack under which is occured.
|
|
*/
|
|
class RIGVMDEVELOPER_API FRigVMASTProxy
|
|
{
|
|
public:
|
|
|
|
FRigVMASTProxy()
|
|
{
|
|
#if UE_BUILD_DEBUG
|
|
DebugName = FString();
|
|
#endif
|
|
Callstack.Stack.Push(nullptr);
|
|
}
|
|
|
|
FRigVMASTProxy(const FRigVMASTProxy& InOther)
|
|
{
|
|
Callstack.Stack = InOther.Callstack.Stack;
|
|
#if UE_BUILD_DEBUG
|
|
DebugName = Callstack.GetCallPath();
|
|
#endif
|
|
}
|
|
|
|
FRigVMASTProxy& operator=(const FRigVMASTProxy& InOther)
|
|
{
|
|
if (this != &InOther)
|
|
{
|
|
Callstack.Stack = InOther.Callstack.Stack;
|
|
#if UE_BUILD_DEBUG
|
|
DebugName = Callstack.GetCallPath();
|
|
#endif
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
static FRigVMASTProxy MakeFromUObject(UObject* InSubject);
|
|
static FRigVMASTProxy MakeFromCallPath(const FString& InCallPath, UObject* InRootObject);
|
|
static FRigVMASTProxy MakeFromCallstack(const FRigVMCallstack& InCallstack);
|
|
static FRigVMASTProxy MakeFromCallstack(const TArray<TWeakObjectPtr<UObject>>* InCallstack);
|
|
|
|
FRigVMASTProxy GetSibling(UObject* InSubject) const
|
|
{
|
|
FRigVMASTProxy Sibling = *this;
|
|
Sibling.Callstack.Stack.Last() = InSubject;
|
|
#if UE_BUILD_DEBUG
|
|
Sibling.DebugName = Sibling.Callstack.GetCallPath();
|
|
#endif
|
|
return Sibling;
|
|
}
|
|
|
|
FRigVMASTProxy GetParent() const
|
|
{
|
|
ensure(Callstack.Num() > 1);
|
|
|
|
FRigVMASTProxy Parent = *this;
|
|
Parent.Callstack.Stack.Pop();
|
|
#if UE_BUILD_DEBUG
|
|
Parent.DebugName = Parent.Callstack.GetCallPath();
|
|
#endif
|
|
return Parent;
|
|
}
|
|
|
|
FRigVMASTProxy GetChild(UObject* InSubject) const
|
|
{
|
|
FRigVMASTProxy Child = *this;
|
|
|
|
if(!Child.IsValid())
|
|
{
|
|
Child.Callstack.Stack.Reset();
|
|
}
|
|
|
|
Child.Callstack.Stack.Push(InSubject);
|
|
#if UE_BUILD_DEBUG
|
|
Child.DebugName = Child.Callstack.GetCallPath();
|
|
#endif
|
|
return Child;
|
|
}
|
|
|
|
const FRigVMCallstack& GetCallstack() const { return Callstack; }
|
|
|
|
UObject* GetSubject() const { return Callstack.Stack.Last().IsValid() ? Callstack.Stack.Last().Get() : nullptr; }
|
|
|
|
template<class T>
|
|
T* GetSubject() const { return Cast<T>(GetSubject()); }
|
|
|
|
template<class T>
|
|
T* GetSubjectChecked() const { return CastChecked<T>(GetSubject()); }
|
|
|
|
bool IsValid() const { return Callstack.Num() > 0 && GetSubject() != nullptr; }
|
|
|
|
template<class T>
|
|
bool IsA() const { return GetSubject() ? GetSubject()->IsA<T>() : false; }
|
|
|
|
friend uint32 GetTypeHash(const FRigVMASTProxy& Proxy)
|
|
{
|
|
return GetTypeHash(Proxy.GetCallstack());
|
|
}
|
|
|
|
bool operator ==(const FRigVMASTProxy& Other) const
|
|
{
|
|
return GetCallstack() == Other.GetCallstack();
|
|
}
|
|
|
|
bool operator !=(const FRigVMASTProxy& Other) const
|
|
{
|
|
return GetCallstack() != Other.GetCallstack();
|
|
}
|
|
|
|
bool operator <(const FRigVMASTProxy& Other) const
|
|
{
|
|
return GetCallstack() < Other.GetCallstack();
|
|
}
|
|
|
|
bool operator >(const FRigVMASTProxy& Other) const
|
|
{
|
|
return GetCallstack() > Other.GetCallstack();
|
|
}
|
|
|
|
private:
|
|
|
|
#if UE_BUILD_DEBUG
|
|
FString DebugName;
|
|
#endif
|
|
|
|
FRigVMCallstack Callstack;
|
|
};
|
|
|
|
typedef TPair<FRigVMASTProxy, FRigVMASTProxy> FRigVMPinProxyPair;
|
|
typedef TMap<FRigVMASTProxy, FString> FRigVMPinDefaultValueOverride;
|