StateTree Feature Request - Expose NodeIndex to FStateTreeNodeBase

As it stands, FStateTreeNodeBase have access to DataViewIndex, and InstanceIndex, however a node is lacking a reference to its own position in the UStateTree::Nodes list. This makes function like UStateTree::GetNode(const int32 NodeIndex) unusable.

Maybe the NodeIndex could be added to the nodes in this method (also conditions, and evaluators)?

bool FStateTreeCompiler::CreateTask(UStateTreeState* State, const FStateTreeEditorNode& TaskNode)
{
	if (!TaskNode.Node.IsValid())
	{
		return false;
	}
	
	// Create binding source struct descriptor.
	FStateTreeBindableStructDesc StructDesc;
	StructDesc.ID = TaskNode.ID;
	StructDesc.Name = TaskNode.Node.GetScriptStruct()->GetFName();
	StructDesc.DataSource = EStateTreeBindableStructSource::Task;

	// Check that node has valid instance initialized.
	if (!TaskNode.Instance.IsValid() && TaskNode.InstanceObject == nullptr)
	{
		Log.Reportf(EMessageSeverity::Error, StructDesc,
			TEXT("Malformed task, missing instance value."));
		return false;
	}

	// Copy the task
	IDToNode.Add(TaskNode.ID, Nodes.Num());
	FInstancedStruct& Node = Nodes.Add_GetRef(TaskNode.Node);
	InstantiateStructSubobjects(Node);
	
	FStateTreeTaskBase& Task = Node.GetMutable<FStateTreeTaskBase>();
	FStateTreeDataView InstanceDataView;

	if (TaskNode.Instance.IsValid())
	{
		// Struct Instance
		const int32 InstanceIndex = InstanceStructs.Add(TaskNode.Instance);
		InstantiateStructSubobjects(InstanceStructs[InstanceIndex]);

		// Create binding source struct descriptor.
		StructDesc.Struct = TaskNode.Instance.GetScriptStruct();
		StructDesc.Name = Task.Name;

		if (const auto Validation = UE::StateTree::Compiler::IsValidIndex16(InstanceIndex); Validation.DidFail())
		{
			Validation.Log(Log, TEXT("InstanceIndex"), StructDesc);
			return false;
		}
		Task.InstanceIndex = FStateTreeIndex16(InstanceIndex);
		Task.bInstanceIsObject = false;
		InstanceDataView = FStateTreeDataView(InstanceStructs[InstanceIndex]);
	}
	else
	{
		// Object Instance
		check(TaskNode.InstanceObject != nullptr);

		UObject* Instance = DuplicateObject(TaskNode.InstanceObject, StateTree);
		const int32 InstanceIndex = InstanceObjects.Add(Instance);

		// Create binding source struct descriptor.
		StructDesc.Struct = Instance->GetClass();
		StructDesc.Name = Task.Name;

		if (const auto Validation = UE::StateTree::Compiler::IsValidIndex16(InstanceIndex); Validation.DidFail())
		{
			Validation.Log(Log, TEXT("InstanceIndex"), StructDesc);
			return false;
		}
		Task.InstanceIndex = FStateTreeIndex16(InstanceIndex);
		Task.bInstanceIsObject = true;
		InstanceDataView = FStateTreeDataView(Instance);
	}

	if (!CompileAndValidateNode(State, StructDesc, Node,  InstanceDataView))
	{
		return false;
	}

	// Mark the instance as binding source.
	const int32 SourceStructIndex = BindingsCompiler.AddSourceStruct(StructDesc);
	
	// Check that the bindings for this struct are still all valid.
	TArray<FStateTreePropertyPathBinding> Bindings;
	if (!GetAndValidateBindings(StructDesc, InstanceDataView, Bindings))
	{
		return false;
	}

	// Compile batch copy for this struct, we pass in all the bindings, the compiler will pick up the ones for the target structs.
	int32 BatchIndex = INDEX_NONE;
	if (!BindingsCompiler.CompileBatch(StructDesc, Bindings, BatchIndex))
	{
		return false;
	}

	if (const auto Validation = UE::StateTree::Compiler::IsValidIndex16(BatchIndex); Validation.DidFail())
	{
		Validation.Log(Log, TEXT("BatchIndex"), StructDesc);
		return false;
	}
	Task.BindingsBatch = FStateTreeIndex16(BatchIndex);

	if (const auto Validation = UE::StateTree::Compiler::IsValidIndex16(SourceStructIndex); Validation.DidFail())
	{
		Validation.Log(Log, TEXT("SourceStructIndex"), StructDesc);
		return false;
	}
	Task.DataViewIndex = FStateTreeIndex16(SourceStructIndex);
	
	return true;
}

At the very least the index could be provided in the FStateTreeNodeBase::Compile(FStateTreeDataView InstanceDataView, TArray<FText>& ValidationMessages), so that people who want to it can store it in the node then.