deleted workshop files
This commit is contained in:
parent
4f72859cd0
commit
6307ec1337
|
@ -1,21 +0,0 @@
|
|||
#include "PerWorldServiceLocator.h"
|
||||
|
||||
#include "Engine/Engine.h"
|
||||
|
||||
FServiceLocator* UPerWorldServiceLocator::Get(UObject* WorldContextObject)
|
||||
{
|
||||
UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull);
|
||||
if(!World)
|
||||
return nullptr;
|
||||
|
||||
UPerWorldServiceLocator* PerWorldServiceLocator = World->GetSubsystem<UPerWorldServiceLocator>();
|
||||
if(!PerWorldServiceLocator)
|
||||
return nullptr;
|
||||
|
||||
return &PerWorldServiceLocator->GetServiceLocator();
|
||||
}
|
||||
|
||||
FServiceLocator& UPerWorldServiceLocator::GetServiceLocator()
|
||||
{
|
||||
return ServiceLocator;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ServiceLocator.h"
|
||||
#include "Subsystems/WorldSubsystem.h"
|
||||
|
||||
#include "PerWorldServiceLocator.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class LYRAGAME_API UPerWorldServiceLocator : public UWorldSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
static FServiceLocator* Get(UObject* WorldContextObject);
|
||||
|
||||
FServiceLocator& GetServiceLocator();
|
||||
|
||||
protected:
|
||||
FServiceLocator ServiceLocator;
|
||||
};
|
|
@ -1,104 +0,0 @@
|
|||
#include "RootedObject.h"
|
||||
|
||||
|
||||
#if WITH_DEV_AUTOMATION_TESTS
|
||||
|
||||
template<typename AssigneeType, typename ValueType>
|
||||
struct TIsAssignableFrom
|
||||
{
|
||||
struct TrueType {};
|
||||
|
||||
template<typename T>
|
||||
static T DeclVal(); // intentionally not implemented
|
||||
|
||||
enum
|
||||
{
|
||||
Value = TIsSame<decltype(DeclVal<AssigneeType>() = DeclVal<ValueType>(), DeclVal<TrueType>()), TrueType>::Value
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(TIsConstructible<TRootedObject<UObject>>::Value, "TRootedObject should be default constructible");
|
||||
|
||||
static_assert(TIsConstructible<TRootedObject<UObject>, TRootedObject<UObject>&&>::Value, "TRootedObject should be move constructible");
|
||||
static_assert(TIsAssignableFrom<TRootedObject<UObject>, TRootedObject<UObject>&&>::Value, "TRootedObject should be move assignable");
|
||||
|
||||
static_assert(TIsAssignableFrom<UObject*&, TRootedObject<UObject>>::Value, "TRootedObject should implicitly castable to its inner type");
|
||||
|
||||
BEGIN_DEFINE_SPEC(TRootedObjectSpec, "Workshop.RootedObject", EAutomationTestFlags::ProductFilter | EAutomationTestFlags::ApplicationContextMask)
|
||||
UObject* TheInnerObject;
|
||||
END_DEFINE_SPEC(TRootedObjectSpec)
|
||||
|
||||
void TRootedObjectSpec::Define()
|
||||
{
|
||||
BeforeEach([this]()
|
||||
{
|
||||
TheInnerObject = NewObject<USceneComponent>();
|
||||
});
|
||||
|
||||
Describe("Construct", [this]()
|
||||
{
|
||||
It("Should add the rooted object to the root", [this]()
|
||||
{
|
||||
TRootedObject<UObject> RootedObject(TheInnerObject);
|
||||
TestTrue("TheInnerObject->IsRooted()", TheInnerObject->IsRooted());
|
||||
});
|
||||
|
||||
It("Should move correctly", [this]()
|
||||
{
|
||||
TRootedObject<UObject> RootedObject(TheInnerObject);
|
||||
TRootedObject<UObject> OtherRootedObject;
|
||||
|
||||
OtherRootedObject = MoveTemp(RootedObject);
|
||||
|
||||
TestTrue("TheInnerObject->IsRooted()", TheInnerObject->IsRooted());
|
||||
TestFalse("RootedObject.IsValid()", RootedObject.IsValid());
|
||||
TestTrue("OtherRootedObject.IsValid()", OtherRootedObject.IsValid());
|
||||
});
|
||||
});
|
||||
|
||||
Describe("Destruct", [this]()
|
||||
{
|
||||
It("Should remove the rooted object from the root", [this]()
|
||||
{
|
||||
{
|
||||
TRootedObject<UObject> RootedObject(TheInnerObject);
|
||||
TestTrue("TheInnerObject->IsRooted()", TheInnerObject->IsRooted());
|
||||
}
|
||||
TestFalse("TheInnerObject->IsRooted()", TheInnerObject->IsRooted());
|
||||
});
|
||||
});
|
||||
|
||||
Describe("RetrieveObject", [this]()
|
||||
{
|
||||
It("Should invalidate the rooted object", [this]()
|
||||
{
|
||||
TRootedObject<UObject> RootedObject(TheInnerObject);
|
||||
RootedObject.RetrieveObject();
|
||||
TestFalse("RootedObject.IsValid()", RootedObject.IsValid());
|
||||
});
|
||||
|
||||
It("Should return the inner object", [this]()
|
||||
{
|
||||
TRootedObject<UObject> RootedObject(TheInnerObject);
|
||||
UObject* RetrievedObject = RootedObject.RetrieveObject();
|
||||
TestEqual("RootedObject.IsValid()", TheInnerObject, RetrievedObject);
|
||||
});
|
||||
|
||||
It("Should remove the inner object from root", [this]()
|
||||
{
|
||||
TRootedObject<UObject> RootedObject(TheInnerObject);
|
||||
UObject* RetrievedObject = RootedObject.RetrieveObject();
|
||||
TestFalse("RetrievedObject->IsRooted()", RetrievedObject->IsRooted());
|
||||
});
|
||||
|
||||
It("Implicit Retrieve is same as explicit retrieve", [this]()
|
||||
{
|
||||
TRootedObject<UObject> RootedObject(TheInnerObject);
|
||||
UObject* RetrievedObject = RootedObject;
|
||||
TestEqual("RootedObject.IsValid()", TheInnerObject, RetrievedObject);
|
||||
TestFalse("RetrievedObject->IsRooted()", RetrievedObject->IsRooted());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,64 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
template <class UObjectType>
|
||||
class TRootedObject
|
||||
{
|
||||
public:
|
||||
using SelfType = TRootedObject<UObjectType>;
|
||||
|
||||
static_assert(TIsDerivedFrom<UObjectType, UObject>::Value, "This class only works with UObjects");
|
||||
|
||||
TRootedObject() = default;
|
||||
|
||||
explicit TRootedObject(UObjectType* Object)
|
||||
: OwnedObject(Object)
|
||||
{
|
||||
OwnedObject->AddToRoot();
|
||||
}
|
||||
|
||||
TRootedObject(const SelfType& Other) = delete;
|
||||
SelfType& operator=(const SelfType& Other) = delete;
|
||||
|
||||
|
||||
TRootedObject(SelfType&& Other)
|
||||
{
|
||||
*this = Other;
|
||||
}
|
||||
|
||||
SelfType& operator=(SelfType&& Other)
|
||||
{
|
||||
Swap(OwnedObject, Other.OwnedObject);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~TRootedObject()
|
||||
{
|
||||
if (::IsValid(OwnedObject))
|
||||
{
|
||||
OwnedObject->RemoveFromRoot();
|
||||
}
|
||||
}
|
||||
|
||||
operator UObjectType*()
|
||||
{
|
||||
return RetrieveObject();
|
||||
}
|
||||
|
||||
UObjectType* RetrieveObject()
|
||||
{
|
||||
UObjectType* Temp = OwnedObject;
|
||||
OwnedObject = nullptr;
|
||||
Temp->RemoveFromRoot();
|
||||
return Temp;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return ::IsValid(OwnedObject);
|
||||
}
|
||||
|
||||
private:
|
||||
UObjectType* OwnedObject = nullptr;
|
||||
};
|
|
@ -1,87 +0,0 @@
|
|||
// Aesir Interactive GmbH, (c) 2019
|
||||
|
||||
#include "ServiceLocator.h"
|
||||
|
||||
|
||||
|
||||
#if WITH_DEV_AUTOMATION_TESTS
|
||||
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "Components/SceneComponent.h"
|
||||
|
||||
static_assert(TModels<CHasStaticUClass, UActorComponent>::Value, "Actor component should have a static uclass");
|
||||
static_assert(TModels<CHasStaticUClass, UObject>::Value);
|
||||
static_assert(!TModels<CHasStaticUClass, IInterface_AssetUserData>::Value);
|
||||
|
||||
static_assert(TModels<CHasInterfaceUClass, IInterface_AssetUserData>::Value);
|
||||
static_assert(TIsUInterface<IInterface_AssetUserData>::Value);
|
||||
static_assert(TModels<CHasInterfaceUClass,UActorComponent>::Value);
|
||||
static_assert(!TModels<CHasInterfaceUClass, UObject>::Value);
|
||||
static_assert(!TIsUInterface<UActorComponent>::Value);
|
||||
static_assert(!TIsUInterface<UObject>::Value);
|
||||
|
||||
|
||||
class FServiceUser
|
||||
{
|
||||
public:
|
||||
USceneComponent* SceneComponent = nullptr;
|
||||
UActorComponent* ActorComponent = nullptr;
|
||||
};
|
||||
|
||||
BEGIN_DEFINE_SPEC(TServiceLocatorSpec, "Workshop.ServiceLocator", EAutomationTestFlags::ProductFilter | EAutomationTestFlags::ApplicationContextMask)
|
||||
FServiceUser ServiceUser;
|
||||
FServiceLocator ServiceLocator;
|
||||
USceneComponent* SceneComponent = nullptr;
|
||||
UActorComponent* ActorComponent = nullptr;
|
||||
END_DEFINE_SPEC(TServiceLocatorSpec)
|
||||
|
||||
|
||||
void TServiceLocatorSpec::Define()
|
||||
{
|
||||
BeforeEach([this]()
|
||||
{
|
||||
SceneComponent = NewObject<USceneComponent>();
|
||||
ActorComponent = NewObject<UActorComponent>();
|
||||
});
|
||||
|
||||
Describe("ProvideService", [this]()
|
||||
{
|
||||
It("Should work for UObjects", [this]()
|
||||
{
|
||||
TestNull("GetService<UActorComponent>()", ServiceLocator.GetService<UActorComponent>());
|
||||
ServiceLocator.ProvideService<UActorComponent>(ActorComponent);
|
||||
|
||||
TestEqual("GetService<UActorComponent>()", ServiceLocator.GetService<UActorComponent>(), ActorComponent);
|
||||
});
|
||||
|
||||
It("Should work for UInterfaces", [this]()
|
||||
{
|
||||
TestNull("GetService<UActorComponent>()", ServiceLocator.GetService<IInterface_AssetUserData>().GetInterface());
|
||||
ServiceLocator.ProvideService<IInterface_AssetUserData>(ActorComponent);
|
||||
|
||||
TestEqual("GetService<UInterface_AssetUserData>()",
|
||||
ServiceLocator.GetService<IInterface_AssetUserData>().GetInterface(),
|
||||
static_cast<IInterface_AssetUserData*>(ActorComponent));
|
||||
});
|
||||
});
|
||||
|
||||
Describe("GetServices", [this]()
|
||||
{
|
||||
BeforeEach([this]()
|
||||
{
|
||||
ServiceLocator.ProvideService<UActorComponent>(ActorComponent);
|
||||
ServiceLocator.ProvideService<USceneComponent>(SceneComponent);
|
||||
ServiceLocator.ProvideService<IInterface_AssetUserData>(ActorComponent);
|
||||
});
|
||||
It("Should get all the services", [this]()
|
||||
{
|
||||
auto [InjectedActorComponent, InjectedSceneComponent, InjectedInterface] = ServiceLocator.GetServices<UActorComponent, USceneComponent, IInterface_AssetUserData>();
|
||||
TestEqual(TEXT("InjectedActorComponent"), InjectedActorComponent, ActorComponent);
|
||||
TestEqual(TEXT("InjectedSceneComponent"), InjectedSceneComponent, SceneComponent);
|
||||
TestEqual(TEXT("InjectedInterface"), InjectedInterface.GetInterface(), static_cast<IInterface_AssetUserData*>(ActorComponent));
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,204 +0,0 @@
|
|||
// Aesir Interactive GmbH, (c) 2019
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Templates/Casts.h"
|
||||
|
||||
|
||||
/*
|
||||
namespace TIsUBaseInterfacePrivate
|
||||
{
|
||||
template<class InterfaceClass>
|
||||
struct TIsUBaseInterfaceImpl;
|
||||
template<>
|
||||
struct TIsUBaseInterfaceImpl<bool> { enum { Value = false };};
|
||||
template<>
|
||||
struct TIsUBaseInterfaceImpl<UClass*> { enum { Value = true };};
|
||||
}
|
||||
template<class InterfaceClass>
|
||||
struct TIsUBaseInterface { enum { Value = TIsUBaseInterfacePrivate::TIsUBaseInterfaceImpl<decltype(&InterfaceClass::StaticClass, true)>::Value}; };
|
||||
*/
|
||||
|
||||
struct CHasStaticUClass
|
||||
{
|
||||
template<class ObjectClass>
|
||||
auto Requires() -> decltype(
|
||||
ObjectClass::StaticClass()
|
||||
);
|
||||
};
|
||||
|
||||
struct CHasInterfaceUClass
|
||||
{
|
||||
template<class InterfaceClass>
|
||||
auto Requires() -> decltype(
|
||||
InterfaceClass::UClassType::StaticClass()
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
template<class InterfaceClass>
|
||||
struct TIsUInterface
|
||||
{
|
||||
enum
|
||||
{
|
||||
Value = !TModels<CHasStaticUClass, InterfaceClass>::Value && TModels<CHasInterfaceUClass, InterfaceClass>::Value
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* General purpose service locator that is available from the world settings
|
||||
*/
|
||||
class LYRAGAME_API FServiceLocator
|
||||
{
|
||||
public:
|
||||
DECLARE_EVENT_OneParam(FServiceLocator, FServiceRegisteredEvent, FServiceLocator&);
|
||||
|
||||
/**
|
||||
* @return the registered service cast to ServiceClass or nullptr if the service is not registered or the cast failed
|
||||
*/
|
||||
template <class ServiceClass>
|
||||
bool IsServiceProvided() const
|
||||
{
|
||||
const UClass* ServiceUClass = GetServiceUClass<ServiceClass>();
|
||||
return Services.Contains(ServiceUClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the registered service cast to ServiceClass or nullptr if the service is not registered or the cast failed
|
||||
*/
|
||||
template <class ServiceType>
|
||||
typename TEnableIf<!TIsIInterface<ServiceType>::Value, ServiceType*>::Type
|
||||
GetService() const
|
||||
{
|
||||
const UClass* ServiceUClass = GetServiceUClass<ServiceType>();
|
||||
UObject* const* ServiceInstance = Services.Find(ServiceUClass);
|
||||
if (!ServiceInstance)
|
||||
return nullptr;
|
||||
|
||||
return Cast<ServiceType>(*ServiceInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the registered service as TScriptInterface or nullptr if the service is not registered or the cast failed
|
||||
*/
|
||||
template<class ServiceInterface>
|
||||
typename TEnableIf<TIsIInterface<ServiceInterface>::Value, TScriptInterface<ServiceInterface>>::Type
|
||||
GetService() const
|
||||
{
|
||||
const UClass* ServiceUClass = GetServiceUClass<ServiceInterface>();
|
||||
UObject* const* ServiceInstance = Services.Find(ServiceUClass);
|
||||
if (!ServiceInstance)
|
||||
return nullptr;
|
||||
|
||||
return TScriptInterface<ServiceInterface>(&**ServiceInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the registered service cast to ServiceClass. Crashes if the service is not available.
|
||||
*/
|
||||
template <class ServiceClass>
|
||||
typename TEnableIf<!TIsIInterface<ServiceClass>::Value, ServiceClass*>::Type
|
||||
GetServiceChecked() const
|
||||
{
|
||||
const UClass* ServiceUClass = GetServiceUClass<ServiceClass>();
|
||||
|
||||
UObject *const* ServiceObject = Services.Find(ServiceUClass);
|
||||
checkf(ServiceObject, TEXT("No object was found for service %s"), *ServiceUClass->GetName());
|
||||
UObject *const ServiceCast = Cast<ServiceClass>(*ServiceObject);
|
||||
checkf(IsValid(ServiceCast), TEXT("Object %s is not of type %s"), *((*ServiceObject)->GetName()), *ServiceUClass->GetName());
|
||||
return Cast<ServiceClass>(*ServiceObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the registered service cast to ServiceClass. Crashes if the service is not available.
|
||||
*/
|
||||
template<class ServiceInterface>
|
||||
typename TEnableIf<TIsIInterface<ServiceInterface>::Value, TScriptInterface<ServiceInterface>>::Type
|
||||
GetServiceChecked() const
|
||||
{
|
||||
const UClass* ServiceUClass = GetServiceUClass<ServiceInterface>();
|
||||
|
||||
UObject *const* ServiceObject = Services.Find(ServiceUClass);
|
||||
checkf(ServiceObject, TEXT("No object was found for service %s"), *ServiceUClass->GetName());
|
||||
checkf(Cast<ServiceInterface>(ServiceObject), TEXT("Object %s does not implement %s"), *(*ServiceObject)->GetName(), *ServiceUClass->GetName());
|
||||
return TScriptInterface<ServiceInterface>(*ServiceObject);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Registers the given object interface with the service locator.
|
||||
* Will refuse to work if the type is not actually derived from the interface.
|
||||
* Note: you should always explicitly provide the template list to make sure you register the service as the intended type
|
||||
* @return void
|
||||
*/
|
||||
template <class ServiceInterface, class ChildType>
|
||||
typename TEnableIf<TIsDerivedFrom<ChildType, ServiceInterface>::Value, void>::Type
|
||||
ProvideService(ChildType* ServiceInstance)
|
||||
{
|
||||
const UClass* ServiceUClass = GetServiceUClass<ServiceInterface>();
|
||||
Services.Emplace(ServiceUClass, ServiceInstance);
|
||||
NotifyServiceProvided(ServiceUClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the given object with the service locator
|
||||
* Note: you should always explicitly provide the template list to make sure you unregister the service as the intended type
|
||||
*/
|
||||
template<class ServiceClass>
|
||||
void WithdrawService(ServiceClass* ServiceInstance)
|
||||
{
|
||||
const UClass* ServiceClassObject = GetServiceUClass<ServiceClass>();
|
||||
ensureMsgf(GetService<ServiceClass>() == ServiceInstance, TEXT("The service you are trying to unregister is not the one that has been provided!"));
|
||||
Services.Remove(ServiceClassObject);
|
||||
}
|
||||
|
||||
/** Waits for the service class to be registered or calls the callback immediately if the service is already registerd */
|
||||
template<class ServiceClass>
|
||||
void WaitForService(FServiceRegisteredEvent::FDelegate Callback)
|
||||
{
|
||||
const UClass* ServiceUClass = GetServiceUClass<ServiceClass>();
|
||||
ServiceRegisteredCallbacks.FindOrAdd(ServiceUClass).Add(Callback);
|
||||
}
|
||||
|
||||
template<class ServiceType>
|
||||
struct ServiceTypeMapper
|
||||
{
|
||||
using MappedType = decltype(DeclVal<FServiceLocator>().GetService<ServiceType>());
|
||||
};
|
||||
|
||||
template<typename...ServiceTypes>
|
||||
auto GetServices() -> decltype(auto)
|
||||
{
|
||||
return MakeTuple<typename ServiceTypeMapper<ServiceTypes>::MappedType...>(GetService<ServiceTypes>()...);
|
||||
}
|
||||
|
||||
private:
|
||||
void NotifyServiceProvided(const UClass* ServiceUClass)
|
||||
{
|
||||
FServiceRegisteredEvent& ServiceRegisteredEvent = ServiceRegisteredCallbacks.FindOrAdd(ServiceUClass);
|
||||
ServiceRegisteredEvent.Broadcast(*this);
|
||||
ServiceRegisteredEvent.Clear();
|
||||
}
|
||||
|
||||
/** This statically gets the UClass from any given IInterface-Type */
|
||||
template <typename ServiceInterface>
|
||||
static typename TEnableIf<TIsUInterface<ServiceInterface>::Value,const UClass*>::Type
|
||||
GetServiceUClass()
|
||||
{
|
||||
return ServiceInterface::UClassType::StaticClass();
|
||||
}
|
||||
|
||||
/** This statically gets the UClass from any given UObject-Type */
|
||||
template <typename ServiceClass>
|
||||
static typename TEnableIf<TModels<CHasStaticUClass, ServiceClass>::Value,const UClass*>::Type
|
||||
GetServiceUClass()
|
||||
{
|
||||
return ServiceClass::StaticClass();
|
||||
}
|
||||
|
||||
TMap<const UClass*, FServiceRegisteredEvent> ServiceRegisteredCallbacks;
|
||||
|
||||
TMap<const UClass*, UObject*> Services;
|
||||
};
|
Loading…
Reference in New Issue