Added initial draft of Universal Object Locator mechanism
Universal Object Locators (UOLs) are designed to support referencing objects that don't fit neatly into a basic outer->inner path representation. Examples might include transient actors, dynamically created objects, or objects that need to be referenced by an external ID or using external lookup logic. Specifically this might be an object spawned by Sequencer, a transient object on a USD stage, or a gameplay-specific object created by a game system.
A UOL comprises zero or more 'fragments': atomic pieces of data and logic that defines how to lookup or load an object based on a context. Fragment types are globally registered as part of module initialization.
UOLs are hashable, and support string conversion that conforms to RFC3986 so they can be used as URIs (though that is not a current use-case). In order to support this type of string conversion, the 'path' part of of a UOL defines the fragment types, and the query string is used to encode the payload data for each fragment. This allows us to support a more diverse set of characters as part of payload strings (ie, / : and .) which are otherwise unsupported as part of the path.
An example UOL to an anim instance might look like: uobj://actor/subobj/animinst?payload0=/Path/To/Package.LevelName:PathToActor&payload1=ComponentName
#rb david.bromberg, ludovic.chabant, Max.Chen
[CL 29714989 by andrew rodham in ue5-main branch]
2023-11-14 11:31:58 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "SubObjectLocator.h"
|
|
|
|
|
#include "UniversalObjectLocatorInitializeParams.h"
|
|
|
|
|
#include "UniversalObjectLocatorInitializeResult.h"
|
|
|
|
|
#include "UniversalObjectLocatorFragmentTypeHandle.h"
|
|
|
|
|
#include "UniversalObjectLocatorResolveParams.h"
|
|
|
|
|
#include "UniversalObjectLocatorStringParams.h"
|
|
|
|
|
|
|
|
|
|
UE::UniversalObjectLocator::TFragmentTypeHandle<FSubObjectLocator> FSubObjectLocator::FragmentType;
|
|
|
|
|
|
|
|
|
|
UE::UniversalObjectLocator::FResolveResult FSubObjectLocator::Resolve(const UE::UniversalObjectLocator::FResolveParams& Params) const
|
|
|
|
|
{
|
|
|
|
|
using namespace UE::UniversalObjectLocator;
|
|
|
|
|
|
|
|
|
|
if (UObject* NonConstContext = const_cast<UObject*>(Params.Context))
|
|
|
|
|
{
|
|
|
|
|
UObject* Result = nullptr;
|
|
|
|
|
if (!NonConstContext->ResolveSubobject(*PathWithinContext, Result, false))
|
|
|
|
|
{
|
|
|
|
|
Result = FindObject<UObject>(NonConstContext, *PathWithinContext);
|
|
|
|
|
}
|
|
|
|
|
return FResolveResultData(Result);
|
|
|
|
|
}
|
|
|
|
|
return FResolveResult();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE::UniversalObjectLocator::FInitializeResult FSubObjectLocator::Initialize(const UE::UniversalObjectLocator::FInitializeParams& InParams)
|
|
|
|
|
{
|
|
|
|
|
using namespace UE::UniversalObjectLocator;
|
|
|
|
|
|
|
|
|
|
PathWithinContext.Reset();
|
|
|
|
|
if (ensureMsgf(InParams.Context && InParams.Object->IsIn(InParams.Context),
|
|
|
|
|
TEXT("Unable to create a reference to %s from context %s since the object does not exist within the context"),
|
|
|
|
|
*InParams.Object->GetName(),
|
|
|
|
|
InParams.Context ? *InParams.Context->GetName() : TEXT("<<none>>"))
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
InParams.Object->GetPathName(InParams.Context, PathWithinContext);
|
|
|
|
|
|
|
|
|
|
return FInitializeResult::Relative(InParams.Context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FInitializeResult::Failure();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FSubObjectLocator::ToString(FStringBuilderBase& OutStringBuilder) const
|
|
|
|
|
{
|
|
|
|
|
OutStringBuilder.Append(PathWithinContext);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE::UniversalObjectLocator::FParseStringResult FSubObjectLocator::TryParseString(FStringView InString, const UE::UniversalObjectLocator::FParseStringParams& Params)
|
|
|
|
|
{
|
|
|
|
|
PathWithinContext.Reset(InString.Len());
|
|
|
|
|
PathWithinContext.Append(InString.GetData(), InString.Len());
|
|
|
|
|
return UE::UniversalObjectLocator::FParseStringResult().Success();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 FSubObjectLocator::ComputePriority(const UObject* ObjectToReference, const UObject* Context)
|
|
|
|
|
{
|
|
|
|
|
// Can only reference objects that are relative to the context
|
|
|
|
|
if (Context && ObjectToReference->IsIn(Context))
|
|
|
|
|
{
|
2023-11-28 16:44:29 -05:00
|
|
|
return 1000;
|
Added initial draft of Universal Object Locator mechanism
Universal Object Locators (UOLs) are designed to support referencing objects that don't fit neatly into a basic outer->inner path representation. Examples might include transient actors, dynamically created objects, or objects that need to be referenced by an external ID or using external lookup logic. Specifically this might be an object spawned by Sequencer, a transient object on a USD stage, or a gameplay-specific object created by a game system.
A UOL comprises zero or more 'fragments': atomic pieces of data and logic that defines how to lookup or load an object based on a context. Fragment types are globally registered as part of module initialization.
UOLs are hashable, and support string conversion that conforms to RFC3986 so they can be used as URIs (though that is not a current use-case). In order to support this type of string conversion, the 'path' part of of a UOL defines the fragment types, and the query string is used to encode the payload data for each fragment. This allows us to support a more diverse set of characters as part of payload strings (ie, / : and .) which are otherwise unsupported as part of the path.
An example UOL to an anim instance might look like: uobj://actor/subobj/animinst?payload0=/Path/To/Package.LevelName:PathToActor&payload1=ComponentName
#rb david.bromberg, ludovic.chabant, Max.Chen
[CL 29714989 by andrew rodham in ue5-main branch]
2023-11-14 11:31:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We can't use this at all
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|