Files
UnrealEngineUWP/Engine/Plugins/Experimental/DataInterfaceGraph/Source/DataInterfaceGraphUncookedOnly/Private/DataInterfaceGraphUncookedOnlyUtils.cpp
Thomas Sarkanen 6ebe619fe5 Initial prototype of data interfaces and data interface graphs
Data interfaces are designed to be the basis for a functional, compositional framework, allowing loose bindings (a typed return value) between functional units (data interfaces). They incorporate the following main features:
- Simple call to 'get a value' from a data interface.
- Most communication is done via the UE::DataInterface::FContext, which handles data management.
- Type-erased values (UE::DataInterface::FParam) for results, parameters and state. These can be promoted to typed values (UE::DataInterface::TParam<T>) with runtime validation.
- 'Hidden state', allocated on-demand via a context, to support functional units that require statefulness. State is allocated according to the calling context, currently a hash of the 'callstack' and call site, so subsequent calls to the same data interface can reuse state.
- Batch processing of multiple state representations at once (e.g. processing multiple characters at one), via a chunked allocation strategy.

Also includes data interface graphs - a proof-of-concept implementation using RigVM to construct scripted data interface logic. This is still very early!

Still lots to do:
- Removal of typed interfaces (e.g. IDataInterface_Float)
- Validation of hidden state approach on a wider scale
- Validation of kernel processing approach
- Chunked branching (probably via a masking strategy) so branches can be handled within chunks
- Reworked type system incorporating type promotion/conversion
- UI work to allow for mixing instanced sub-objects and asset references with using TScriptInterface<IDataInterface>
- Expansion or RigVM usage and a ton of UI/UX work to get graph editing up to scratch
- Many many more things

#preflight 625e86873e0f6f80ada98290

[CL 19806109 by Thomas Sarkanen in ue5-main branch]
2022-04-19 06:28:48 -04:00

105 lines
3.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "DataInterfaceUncookedOnlyUtils.h"
#include "DataInterfaceGraph.h"
#include "DataInterfaceGraph_EditorData.h"
#include "DataInterfaceGraph_EdGraph.h"
#include "RigVMCompiler/RigVMCompiler.h"
#include "RigVMCore/RigVM.h"
#include "Units/RigUnitContext.h"
namespace UE::DataInterfaceGraphUncookedOnly
{
void FUtils::Compile(UDataInterfaceGraph* InGraph)
{
check(InGraph);
UDataInterfaceGraph_EditorData* EditorData = GetEditorData(InGraph);
if(EditorData->bIsCompiling)
{
return;
}
TGuardValue<bool> CompilingGuard(EditorData->bIsCompiling, true);
EditorData->bErrorsDuringCompilation = false;
EditorData->RigGraphDisplaySettings.MinMicroSeconds = EditorData->RigGraphDisplaySettings.LastMinMicroSeconds = DBL_MAX;
EditorData->RigGraphDisplaySettings.MaxMicroSeconds = EditorData->RigGraphDisplaySettings.LastMaxMicroSeconds = (double)INDEX_NONE;
TGuardValue<bool> ReentrantGuardSelf(EditorData->bSuspendModelNotificationsForSelf, true);
TGuardValue<bool> ReentrantGuardOthers(EditorData->bSuspendModelNotificationsForOthers, true);
RecreateVM(InGraph);
InGraph->VMRuntimeSettings = EditorData->VMRuntimeSettings;
FRigNameCache TempNameCache;
FRigUnitContext InitContext;
InitContext.State = EControlRigState::Init;
InitContext.NameCache = &TempNameCache;
FRigUnitContext UpdateContext = InitContext;
UpdateContext.State = EControlRigState::Update;
void* InitContextPtr = &InitContext;
void* UpdateContextPtr = &UpdateContext;
TArray<FRigVMUserDataArray> UserData;
UserData.Add(FRigVMUserDataArray(&InitContextPtr, 1));
UserData.Add(FRigVMUserDataArray(&UpdateContextPtr, 1));
EditorData->CompileLog.Messages.Reset();
EditorData->CompileLog.NumErrors = EditorData->CompileLog.NumWarnings = 0;
URigVMCompiler* Compiler = URigVMCompiler::StaticClass()->GetDefaultObject<URigVMCompiler>();
Compiler->Settings = (EditorData->bCompileInDebugMode) ? FRigVMCompileSettings::Fast() : EditorData->VMCompileSettings;
URigVMController* RootController = EditorData->GetOrCreateRigVMController(EditorData->RigVMGraph);
Compiler->Compile(EditorData->RigVMGraph, RootController, InGraph->RigVM, InGraph->GetRigVMExternalVariables(), UserData, &EditorData->PinToOperandMap);
if (EditorData->bErrorsDuringCompilation)
{
if(Compiler->Settings.SurpressErrors)
{
Compiler->Settings.Reportf(EMessageSeverity::Info, InGraph,TEXT("Compilation Errors may be suppressed for Data Interface Graph: %s. See VM Compile Settings for more Details"), *InGraph->GetName());
}
}
EditorData->bVMRecompilationRequired = false;
if(InGraph->RigVM)
{
EditorData->VMCompiledEvent.Broadcast(InGraph, InGraph->RigVM);
}
#if WITH_EDITOR
// RefreshBreakpoints(EditorData);
#endif
}
void FUtils::RecreateVM(UDataInterfaceGraph* InGraph)
{
InGraph->RigVM = NewObject<URigVM>(InGraph, TEXT("VM"), RF_NoFlags);
// Cooked platforms will load these pointers from disk
if (!FPlatformProperties::RequiresCookedData())
{
// We dont support ERigVMMemoryType::Work memory as we dont operate on an instance
// InGraph->RigVM->GetMemoryByType(ERigVMMemoryType::Work, true);
InGraph->RigVM->GetMemoryByType(ERigVMMemoryType::Literal, true);
InGraph->RigVM->GetMemoryByType(ERigVMMemoryType::Debug, true);
}
InGraph->RigVM->Reset();
}
UDataInterfaceGraph_EditorData* FUtils::GetEditorData(const UDataInterfaceGraph* InDataInterfaceGraph)
{
check(InDataInterfaceGraph);
return CastChecked<UDataInterfaceGraph_EditorData>(InDataInterfaceGraph->EditorData);
}
}