Lots of work on look-at widgets
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/Luprex/lxGameMode.uasset
LFS
BIN
Content/Luprex/lxGameMode.uasset
LFS
Binary file not shown.
Binary file not shown.
BIN
Content/Widgets/WB_Console.uasset
LFS
Normal file
BIN
Content/Widgets/WB_Console.uasset
LFS
Normal file
Binary file not shown.
BIN
Content/Widgets/WB_Crosshair.uasset
LFS
Normal file
BIN
Content/Widgets/WB_Crosshair.uasset
LFS
Normal file
Binary file not shown.
BIN
Content/Widgets/WB_Hotkeys.uasset
LFS
Normal file
BIN
Content/Widgets/WB_Hotkeys.uasset
LFS
Normal file
Binary file not shown.
BIN
Content/Widgets/lxCrosshairImage.uasset
LFS
Normal file
BIN
Content/Widgets/lxCrosshairImage.uasset
LFS
Normal file
Binary file not shown.
@@ -4,6 +4,9 @@
|
|||||||
#include "AssetRegistry/AssetData.h"
|
#include "AssetRegistry/AssetData.h"
|
||||||
#include "AssetRegistry/AssetRegistryState.h"
|
#include "AssetRegistry/AssetRegistryState.h"
|
||||||
#include "LuprexGameModeBase.h"
|
#include "LuprexGameModeBase.h"
|
||||||
|
#include "Components/Widget.h"
|
||||||
|
#include "WidgetBlueprint.h"
|
||||||
|
#include "Blueprint/UserWidget.h"
|
||||||
|
|
||||||
void UlxAssetLookup::RebuildIndex()
|
void UlxAssetLookup::RebuildIndex()
|
||||||
{
|
{
|
||||||
@@ -12,6 +15,7 @@ void UlxAssetLookup::RebuildIndex()
|
|||||||
IAssetRegistry::GetChecked().WaitForCompletion();
|
IAssetRegistry::GetChecked().WaitForCompletion();
|
||||||
ScanTangibles();
|
ScanTangibles();
|
||||||
ScanStaticMeshes();
|
ScanStaticMeshes();
|
||||||
|
ScanWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxAssetLookup::ScanTangibles()
|
void UlxAssetLookup::ScanTangibles()
|
||||||
@@ -27,7 +31,7 @@ void UlxAssetLookup::ScanTangibles()
|
|||||||
UE_LOG(LogLuprexIntegration, Display, TEXT("Found %d assets in /Game/Tangibles"), FoundData.Num());
|
UE_LOG(LogLuprexIntegration, Display, TEXT("Found %d assets in /Game/Tangibles"), FoundData.Num());
|
||||||
for (const FAssetData &Data : FoundData)
|
for (const FAssetData &Data : FoundData)
|
||||||
{
|
{
|
||||||
FString Path = Data.GetObjectPathString();
|
FString Path = Data.GetObjectPathString() + TEXT("_C");
|
||||||
CachedTangibles.Add(Data.AssetName, Path);
|
CachedTangibles.Add(Data.AssetName, Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,7 +46,7 @@ void UlxAssetLookup::ScanStaticMeshes()
|
|||||||
AssetFilter.bRecursivePaths = true;
|
AssetFilter.bRecursivePaths = true;
|
||||||
IAssetRegistry::GetChecked().GetAssets(AssetFilter, FoundData);
|
IAssetRegistry::GetChecked().GetAssets(AssetFilter, FoundData);
|
||||||
|
|
||||||
UE_LOG(LogLuprexIntegration, Display, TEXT("Found %d static mesh assets"), FoundData.Num());
|
UE_LOG(LogLuprexIntegration, Display, TEXT("Found %d assets in /Game/StaticMeshes"), FoundData.Num());
|
||||||
for (const FAssetData &Data : FoundData)
|
for (const FAssetData &Data : FoundData)
|
||||||
{
|
{
|
||||||
FString Path = Data.GetObjectPathString();
|
FString Path = Data.GetObjectPathString();
|
||||||
@@ -50,10 +54,26 @@ void UlxAssetLookup::ScanStaticMeshes()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UlxAssetLookup::ScanWidgets()
|
||||||
|
{
|
||||||
|
TArray<FAssetData> FoundData;
|
||||||
|
FARFilter AssetFilter;
|
||||||
|
AssetFilter.PackagePaths.Add(FName(TEXT("/Game/Widgets")));
|
||||||
|
AssetFilter.ClassPaths.Add(UWidgetBlueprint::StaticClass()->GetClassPathName());
|
||||||
|
AssetFilter.bIncludeOnlyOnDiskAssets = true;
|
||||||
|
AssetFilter.bRecursivePaths = true;
|
||||||
|
IAssetRegistry::GetChecked().GetAssets(AssetFilter, FoundData);
|
||||||
|
|
||||||
|
UE_LOG(LogLuprexIntegration, Display, TEXT("Found %d assets in /Game/Widgets"), FoundData.Num());
|
||||||
|
for (const FAssetData &Data : FoundData)
|
||||||
|
{
|
||||||
|
FString Path = Data.GetObjectPathString() + TEXT("_C");
|
||||||
|
CachedWidgets.Add(Data.AssetName, Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FString UlxAssetLookup::TangibleLoadPath(const FName &AssetName) const
|
FString UlxAssetLookup::TangibleLoadPath(const FName &AssetName) const
|
||||||
{
|
{
|
||||||
FScopeLock lock(&Mutex);
|
|
||||||
|
|
||||||
const FString *Result = CachedTangibles.Find(AssetName);
|
const FString *Result = CachedTangibles.Find(AssetName);
|
||||||
if (Result == nullptr) return TEXT("");
|
if (Result == nullptr) return TEXT("");
|
||||||
return *Result;
|
return *Result;
|
||||||
@@ -61,13 +81,18 @@ FString UlxAssetLookup::TangibleLoadPath(const FName &AssetName) const
|
|||||||
|
|
||||||
FString UlxAssetLookup::StaticMeshLoadPath(const FName &AssetName) const
|
FString UlxAssetLookup::StaticMeshLoadPath(const FName &AssetName) const
|
||||||
{
|
{
|
||||||
FScopeLock lock(&Mutex);
|
|
||||||
|
|
||||||
const FString *Result = CachedStaticMeshes.Find(AssetName);
|
const FString *Result = CachedStaticMeshes.Find(AssetName);
|
||||||
if (Result == nullptr) return TEXT("");
|
if (Result == nullptr) return TEXT("");
|
||||||
return *Result;
|
return *Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FString UlxAssetLookup::WidgetLoadPath(const FName &AssetName) const
|
||||||
|
{
|
||||||
|
const FString *Result = CachedWidgets.Find(AssetName);
|
||||||
|
if (Result == nullptr) return TEXT("");
|
||||||
|
return *Result;
|
||||||
|
}
|
||||||
|
|
||||||
UStaticMesh *UlxAssetLookup::GetStaticMeshByName(const UObject *Context, const FString &Name)
|
UStaticMesh *UlxAssetLookup::GetStaticMeshByName(const UObject *Context, const FString &Name)
|
||||||
{
|
{
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
|
||||||
@@ -77,18 +102,16 @@ UStaticMesh *UlxAssetLookup::GetStaticMeshByName(const UObject *Context, const F
|
|||||||
UE_LOG(LogLuprexIntegration, Error, TEXT("Static mesh not on search path: %s"), *Name);
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Static mesh not on search path: %s"), *Name);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
UStaticMesh *Result = LoadObject<UStaticMesh>(nullptr, *Path);
|
||||||
FString FullPath = Path;
|
|
||||||
UStaticMesh *Result = LoadObject<UStaticMesh>(nullptr, *FullPath);
|
|
||||||
if (Result == nullptr) {
|
if (Result == nullptr) {
|
||||||
UE_LOG(LogLuprexIntegration, Error, TEXT("Cannot load static mesh: %s"), *FullPath);
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Cannot load static mesh: %s"), *Path);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
UClass *UlxAssetLookup::GetTangibleClassByName(const UObject *Context, const FString &Name) {
|
TSubclassOf<AActor> UlxAssetLookup::GetTangibleClassByName(const UObject *Context, const FString &Name) {
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
|
||||||
FString Path = mode->GetAssetLookup()->TangibleLoadPath(FName(FString("TAN_") + Name));
|
FString Path = mode->GetAssetLookup()->TangibleLoadPath(FName(FString("TAN_") + Name));
|
||||||
if (Path.IsEmpty())
|
if (Path.IsEmpty())
|
||||||
@@ -96,21 +119,61 @@ UClass *UlxAssetLookup::GetTangibleClassByName(const UObject *Context, const FSt
|
|||||||
UE_LOG(LogLuprexIntegration, Error, TEXT("Tangible not on search path: %s"), *Name);
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Tangible not on search path: %s"), *Name);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
FString FullPath = Path + TEXT("_C");
|
UClass *Result = LoadObject<UClass>(nullptr, *Path);
|
||||||
UClass *Result = LoadObject<UClass>(nullptr, *FullPath);
|
|
||||||
if (Result == nullptr) {
|
if (Result == nullptr) {
|
||||||
UE_LOG(LogLuprexIntegration, Error, TEXT("Cannot load tangible class: %s"), *FullPath);
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Cannot load tangible class: %s"), *Path);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!Result->IsChildOf(AActor::StaticClass())) {
|
if (!Result->IsChildOf(AActor::StaticClass())) {
|
||||||
UE_LOG(LogLuprexIntegration, Error, TEXT("Tangible class is not an actor: %s"), *FullPath);
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Tangible class is not an actor: %s"), *Path);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
UFunction *aqchanged = Result->FindFunctionByName(FName(TEXT("Animation Queue Changed")));
|
UFunction *aqchanged = Result->FindFunctionByName(FName(TEXT("Animation Queue Changed")));
|
||||||
if ((aqchanged == nullptr)||(aqchanged->ParmsSize != 0))
|
if ((aqchanged == nullptr)||(aqchanged->ParmsSize != 0))
|
||||||
{
|
{
|
||||||
UE_LOG(LogLuprexIntegration, Error, TEXT("Tangible does not have 'Animation Queue Changed' function: %s"), *FullPath);
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Tangible does not have 'Animation Queue Changed' function: %s"), *Path);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TSubclassOf<UUserWidget> UlxAssetLookup::GetWidgetByName(const UObject *Context, const FString &Name) {
|
||||||
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
|
||||||
|
FString Path = mode->GetAssetLookup()->WidgetLoadPath(FName(FString("WB_") + Name));
|
||||||
|
if (Path.IsEmpty())
|
||||||
|
{
|
||||||
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Widget not on search path: %s"), *Name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
UClass *Result = LoadObject<UClass>(nullptr, *Path);
|
||||||
|
if (Result == nullptr) {
|
||||||
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Cannot load widget blueprint: %s"), *Path);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!Result->IsChildOf(UUserWidget::StaticClass())) {
|
||||||
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Blueprint is not a Widget Blueprint: %s"), *Path);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSubclassOf<UlxLookAtWidget> UlxAssetLookup::GetLookAtWidgetByName(const UObject *Context, const FString &Name) {
|
||||||
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(Context);
|
||||||
|
FString Path = mode->GetAssetLookup()->WidgetLoadPath(FName(FString("WB_") + Name));
|
||||||
|
if (Path.IsEmpty())
|
||||||
|
{
|
||||||
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Widget not on search path: %s"), *Name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
UClass *Result = LoadObject<UClass>(nullptr, *Path);
|
||||||
|
if (Result == nullptr) {
|
||||||
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Cannot load widget blueprint: %s"), *Path);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!Result->IsChildOf(UlxLookAtWidget::StaticClass())) {
|
||||||
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Blueprint is not a Luprex Look-At Widget: %s"), *Path);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,17 @@
|
|||||||
#include "CommonTypes.h"
|
#include "CommonTypes.h"
|
||||||
#include "AssetLookup.generated.h"
|
#include "AssetLookup.generated.h"
|
||||||
|
|
||||||
|
class AActor;
|
||||||
|
class UUserWidget;
|
||||||
|
class UlxLookAtWidget;
|
||||||
|
class UStaticMesh;
|
||||||
|
|
||||||
UCLASS(MinimalAPI)
|
UCLASS(MinimalAPI)
|
||||||
class UlxAssetLookup : public UObject
|
class UlxAssetLookup : public UObject
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable FCriticalSection Mutex;
|
|
||||||
|
|
||||||
// Map from asset name to full loadable path.
|
// Map from asset name to full loadable path.
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
TMap<FName, FString> CachedTangibles;
|
TMap<FName, FString> CachedTangibles;
|
||||||
@@ -22,22 +25,40 @@ private:
|
|||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
TMap<FName, FString> CachedStaticMeshes;
|
TMap<FName, FString> CachedStaticMeshes;
|
||||||
|
|
||||||
public:
|
// Map from asset name to full loadable path.
|
||||||
void RebuildIndex();
|
UPROPERTY()
|
||||||
|
TMap<FName, FString> CachedWidgets;
|
||||||
|
|
||||||
|
private:
|
||||||
void ScanTangibles();
|
void ScanTangibles();
|
||||||
void ScanStaticMeshes();
|
void ScanStaticMeshes();
|
||||||
|
void ScanWidgets();
|
||||||
|
|
||||||
// Get the full path name of a
|
public:
|
||||||
|
void RebuildIndex();
|
||||||
|
|
||||||
|
// Get the full LoadObject path of a Tangible.
|
||||||
FString TangibleLoadPath(const FName &AssetName) const;
|
FString TangibleLoadPath(const FName &AssetName) const;
|
||||||
|
|
||||||
// Get a static mesh by its asset name.
|
// Get the full LoadObject path of a Static Mesh.
|
||||||
FString StaticMeshLoadPath(const FName &AssetName) const;
|
FString StaticMeshLoadPath(const FName &AssetName) const;
|
||||||
|
|
||||||
|
// Get the full LoadObject path of a Widget Blueprint.
|
||||||
|
FString WidgetLoadPath(const FName &AssetName) const;
|
||||||
|
|
||||||
// Get a static mesh by name
|
// Get a static mesh by name
|
||||||
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Miscellaneous")
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Miscellaneous")
|
||||||
static UStaticMesh *GetStaticMeshByName(const UObject *Context, const FString &Name);
|
static UStaticMesh *GetStaticMeshByName(const UObject *Context, const FString &Name);
|
||||||
|
|
||||||
// Get a static mesh by name
|
// Get a tangible class by name
|
||||||
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Miscellaneous")
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Miscellaneous")
|
||||||
static UClass *GetTangibleClassByName(const UObject *Context, const FString &Name);
|
static TSubclassOf<AActor> GetTangibleClassByName(const UObject *Context, const FString &Name);
|
||||||
|
|
||||||
|
// Get a widget blueprint by name
|
||||||
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Miscellaneous")
|
||||||
|
static TSubclassOf<UUserWidget> GetWidgetByName(const UObject *Context, const FString &Name);
|
||||||
|
|
||||||
|
// Get a look-at widget blueprint by name
|
||||||
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Miscellaneous")
|
||||||
|
static TSubclassOf<UlxLookAtWidget> GetLookAtWidgetByName(const UObject *Context, const FString &Name);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
#include "BlueprintErrors.h"
|
#include "BlueprintErrors.h"
|
||||||
#include "StringDecoder.h"
|
#include "LuaCall.h"
|
||||||
#include "Internationalization/TextFormatter.h"
|
#include "Internationalization/TextFormatter.h"
|
||||||
#include "Kismet/KismetSystemLibrary.h"
|
#include "Kismet/KismetSystemLibrary.h"
|
||||||
#include "Kismet2/KismetDebugUtilities.h"
|
#include "Kismet2/KismetDebugUtilities.h"
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public class Integration : ModuleRules
|
|||||||
"KismetWidgets",
|
"KismetWidgets",
|
||||||
"BlueprintGraph",
|
"BlueprintGraph",
|
||||||
"UMG",
|
"UMG",
|
||||||
|
"UMGEditor",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Uncomment if you are using Slate UI
|
// Uncomment if you are using Slate UI
|
||||||
|
|||||||
@@ -5,15 +5,14 @@
|
|||||||
|
|
||||||
#include "EdGraphSchema_K2.h"
|
#include "EdGraphSchema_K2.h"
|
||||||
|
|
||||||
static void FatalBlueprintError(const TCHAR *message) {
|
|
||||||
FBlueprintExceptionInfo ExceptionInfo(EBlueprintExceptionType::FatalError, FText::FromString(FString(message)));
|
|
||||||
FBlueprintCoreDelegates::ThrowScriptException(FFrame::GetThreadLocalTopStackFrame()->Object, *FFrame::GetThreadLocalTopStackFrame(), ExceptionInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CheckNotEmpty(const FlxStreamBuffer &sb) {
|
static bool NotInitialized(const FlxStreamBuffer &sb) {
|
||||||
if (sb.empty()) {
|
if (sb.empty())
|
||||||
FatalBlueprintError(TEXT("Must use LuaCallBegin before other LuaCall steps"));
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("Must use LuaCallBegin before other LuaCall steps"));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr uint64_t ParseNameAsToken(std::string_view str) {
|
static constexpr uint64_t ParseNameAsToken(std::string_view str) {
|
||||||
@@ -219,7 +218,7 @@ void UlxLuaCallLibrary::LuaCallInvoke(UObject *context, AActor *place)
|
|||||||
{
|
{
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
CheckNotEmpty(sb);
|
if (NotInitialized(sb)) return;
|
||||||
mode->LuaCallEnd(InvocationKind::LUA_INVOKE, place);
|
mode->LuaCallEnd(InvocationKind::LUA_INVOKE, place);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +227,7 @@ void UlxLuaCallLibrary::LuaCallProbe(UObject *context, AActor *place)
|
|||||||
{
|
{
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
CheckNotEmpty(sb);
|
if (NotInitialized(sb)) return;
|
||||||
mode->LuaCallEnd(InvocationKind::LUA_PROBE, place);
|
mode->LuaCallEnd(InvocationKind::LUA_PROBE, place);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +253,7 @@ UlxLuaValues *UlxLuaCallLibrary::LuaCallGetRest(UObject *context)
|
|||||||
void UlxLuaCallLibrary::LuaCallArgument_string(UObject *context, const FString &pstring) {
|
void UlxLuaCallLibrary::LuaCallArgument_string(UObject *context, const FString &pstring) {
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
CheckNotEmpty(sb);
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::STRING);
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::STRING);
|
||||||
sb.write_string(pstring);
|
sb.write_string(pstring);
|
||||||
}
|
}
|
||||||
@@ -263,12 +262,13 @@ void UlxLuaCallLibrary::LuaCallArgument_name(UObject *context, const FName &pnam
|
|||||||
FTCHARToUTF8 utf8str(pname.ToString());
|
FTCHARToUTF8 utf8str(pname.ToString());
|
||||||
std::string_view namestr(utf8str.Get(), utf8str.Length());
|
std::string_view namestr(utf8str.Get(), utf8str.Length());
|
||||||
uint64_t tokvalue = ParseNameAsToken(namestr);
|
uint64_t tokvalue = ParseNameAsToken(namestr);
|
||||||
if ((tokvalue == 0) && !namestr.empty()) {
|
if ((tokvalue == 0) && !namestr.empty())
|
||||||
FatalBlueprintError(TEXT("Names passed to lua must be short, and must contain only lowercase and digits"));
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("Names passed to lua must be short, and must contain only lowercase and digits"));
|
||||||
}
|
}
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
CheckNotEmpty(sb);
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::TOKEN);
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::TOKEN);
|
||||||
sb.write_string(namestr);
|
sb.write_string(namestr);
|
||||||
}
|
}
|
||||||
@@ -276,7 +276,7 @@ void UlxLuaCallLibrary::LuaCallArgument_name(UObject *context, const FName &pnam
|
|||||||
void UlxLuaCallLibrary::LuaCallArgument_float(UObject *context, double pfloat) {
|
void UlxLuaCallLibrary::LuaCallArgument_float(UObject *context, double pfloat) {
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
CheckNotEmpty(sb);
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
||||||
sb.write_double(pfloat);
|
sb.write_double(pfloat);
|
||||||
}
|
}
|
||||||
@@ -284,7 +284,7 @@ void UlxLuaCallLibrary::LuaCallArgument_float(UObject *context, double pfloat) {
|
|||||||
void UlxLuaCallLibrary::LuaCallArgument_int(UObject *context, int value) {
|
void UlxLuaCallLibrary::LuaCallArgument_int(UObject *context, int value) {
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
CheckNotEmpty(sb);
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
||||||
sb.write_double(value);
|
sb.write_double(value);
|
||||||
}
|
}
|
||||||
@@ -292,7 +292,7 @@ void UlxLuaCallLibrary::LuaCallArgument_int(UObject *context, int value) {
|
|||||||
void UlxLuaCallLibrary::LuaCallArgument_vector(UObject *context, const FVector &pvector) {
|
void UlxLuaCallLibrary::LuaCallArgument_vector(UObject *context, const FVector &pvector) {
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
CheckNotEmpty(sb);
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
|
||||||
sb.write_fvector(pvector);
|
sb.write_fvector(pvector);
|
||||||
}
|
}
|
||||||
@@ -300,7 +300,7 @@ void UlxLuaCallLibrary::LuaCallArgument_vector(UObject *context, const FVector &
|
|||||||
void UlxLuaCallLibrary::LuaCallArgument_vector2d(UObject *context, const FVector2D &pvector) {
|
void UlxLuaCallLibrary::LuaCallArgument_vector2d(UObject *context, const FVector2D &pvector) {
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
CheckNotEmpty(sb);
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
|
||||||
sb.write_double(pvector.X);
|
sb.write_double(pvector.X);
|
||||||
sb.write_double(pvector.Y);
|
sb.write_double(pvector.Y);
|
||||||
@@ -310,7 +310,7 @@ void UlxLuaCallLibrary::LuaCallArgument_vector2d(UObject *context, const FVector
|
|||||||
void UlxLuaCallLibrary::LuaCallArgument_boolean(UObject *context, bool pbool) {
|
void UlxLuaCallLibrary::LuaCallArgument_boolean(UObject *context, bool pbool) {
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
CheckNotEmpty(sb);
|
if (NotInitialized(sb)) return;
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::BOOLEAN);
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::BOOLEAN);
|
||||||
sb.write_bool(pbool);
|
sb.write_bool(pbool);
|
||||||
}
|
}
|
||||||
@@ -327,7 +327,11 @@ FString UlxLuaCallLibrary::LuaCallReturnValue_string(UObject *context) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
if (tag != SimpleDynamicTag::STRING) FatalBlueprintError(TEXT("expected lua to return a string"));
|
if (tag != SimpleDynamicTag::STRING)
|
||||||
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("expected lua to return a string"));
|
||||||
|
return TEXT("");
|
||||||
|
}
|
||||||
return sb.read_fstring();
|
return sb.read_fstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +339,11 @@ FName UlxLuaCallLibrary::LuaCallReturnValue_name(UObject *context) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
if (tag != SimpleDynamicTag::TOKEN) FatalBlueprintError(TEXT("expected lua to return a name"));
|
if (tag != SimpleDynamicTag::TOKEN)
|
||||||
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("expected lua to return a name"));
|
||||||
|
return FName();
|
||||||
|
}
|
||||||
return sb.read_fname();
|
return sb.read_fname();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +351,11 @@ double UlxLuaCallLibrary::LuaCallReturnValue_float(UObject *context) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
if (tag != SimpleDynamicTag::NUMBER) FatalBlueprintError(TEXT("expected lua to return a float"));
|
if (tag != SimpleDynamicTag::NUMBER)
|
||||||
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("expected lua to return a float"));
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
return sb.read_double();
|
return sb.read_double();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +363,11 @@ int UlxLuaCallLibrary::LuaCallReturnValue_int(UObject *context) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
if (tag != SimpleDynamicTag::NUMBER) FatalBlueprintError(TEXT("expected lua to return a number"));
|
if (tag != SimpleDynamicTag::NUMBER)
|
||||||
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("expected lua to return a number"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return int(sb.read_double());
|
return int(sb.read_double());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +375,11 @@ FVector UlxLuaCallLibrary::LuaCallReturnValue_vector(UObject *context) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
if (tag != SimpleDynamicTag::VECTOR) FatalBlueprintError(TEXT("expected lua to return a vector"));
|
if (tag != SimpleDynamicTag::VECTOR)
|
||||||
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("expected lua to return a vector"));
|
||||||
|
return FVector();
|
||||||
|
}
|
||||||
return sb.read_fvector();
|
return sb.read_fvector();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +387,11 @@ FVector2D UlxLuaCallLibrary::LuaCallReturnValue_vector2d(UObject *context) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
if (tag != SimpleDynamicTag::VECTOR) FatalBlueprintError(TEXT("expected lua to return a vector"));
|
if (tag != SimpleDynamicTag::VECTOR)
|
||||||
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("expected lua to return a vector"));
|
||||||
|
return FVector2D();
|
||||||
|
}
|
||||||
FVector v = sb.read_fvector();
|
FVector v = sb.read_fvector();
|
||||||
return FVector2D(v.X, v.Y);
|
return FVector2D(v.X, v.Y);
|
||||||
}
|
}
|
||||||
@@ -376,7 +400,169 @@ bool UlxLuaCallLibrary::LuaCallReturnValue_boolean(UObject *context) {
|
|||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
if (tag != SimpleDynamicTag::BOOLEAN) FatalBlueprintError(TEXT("expected lua to return a boolean"));
|
if (tag != SimpleDynamicTag::BOOLEAN)
|
||||||
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("expected lua to return a boolean"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return sb.read_bool();
|
return sb.read_bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Returning the rest of the lua return values as an array.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
void UlxLuaValues::Empty()
|
||||||
|
{
|
||||||
|
Serialized.clear();
|
||||||
|
Types.Empty();
|
||||||
|
Data.Empty();
|
||||||
|
Cursor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UlxLuaValues::Initialize(std::string_view data)
|
||||||
|
{
|
||||||
|
Empty();
|
||||||
|
Serialized = data;
|
||||||
|
const char *SerializedChar = &Serialized[0];
|
||||||
|
|
||||||
|
FlxStreamBuffer Decoder(Serialized);
|
||||||
|
|
||||||
|
while (!Decoder.empty())
|
||||||
|
{
|
||||||
|
SimpleDynamicTag Tag = Decoder.read_simple_dynamic_tag();
|
||||||
|
|
||||||
|
int64 Pos = Decoder.total_reads();
|
||||||
|
ElxLuaValueType Type;
|
||||||
|
switch (Tag)
|
||||||
|
{
|
||||||
|
case SimpleDynamicTag::BOOLEAN: Type=ElxLuaValueType::Boolean; Decoder.read_bool(); break;
|
||||||
|
case SimpleDynamicTag::NUMBER: Type=ElxLuaValueType::Float; Decoder.read_double(); break;
|
||||||
|
case SimpleDynamicTag::STRING: Type=ElxLuaValueType::String; Decoder.read_string_view(); break;
|
||||||
|
case SimpleDynamicTag::TOKEN: Type=ElxLuaValueType::Name; Decoder.read_string_view(); break;
|
||||||
|
case SimpleDynamicTag::VECTOR: Type=ElxLuaValueType::Vector; Decoder.read_fvector(); break;
|
||||||
|
default: {
|
||||||
|
Empty();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int64 Pos2 = Decoder.total_reads();
|
||||||
|
Types.Add(Type);
|
||||||
|
Data.Add(std::string_view(SerializedChar + Pos, Pos2 - Pos));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FString UlxLuaValues::DebugString() const
|
||||||
|
{
|
||||||
|
TStringBuilder<2048> Output;
|
||||||
|
Output << TEXT("{ ");
|
||||||
|
for (int i = 0; i < Types.Num(); i++)
|
||||||
|
{
|
||||||
|
if (i > 0) Output << TEXT(", ");
|
||||||
|
|
||||||
|
ElxLuaValueType Type = Types[i];
|
||||||
|
FlxStreamBuffer Decoder(Data[i]);
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case ElxLuaValueType::Boolean:
|
||||||
|
Output << Decoder.read_bool();
|
||||||
|
break;
|
||||||
|
case ElxLuaValueType::Float:
|
||||||
|
Output << FString::Printf(TEXT("%lf"), Decoder.read_double());
|
||||||
|
break;
|
||||||
|
case ElxLuaValueType::String:
|
||||||
|
Output << TEXT("\"") << Decoder.read_fstring() << TEXT("\"");
|
||||||
|
break;
|
||||||
|
case ElxLuaValueType::Name:
|
||||||
|
Output << Decoder.read_fname();
|
||||||
|
break;
|
||||||
|
case ElxLuaValueType::Vector: {
|
||||||
|
FVector Vec = Decoder.read_fvector();
|
||||||
|
Output << FString::Printf(TEXT("(%lf, %lf, %lf)"), Vec.X, Vec.Y, Vec.Z);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Output << TEXT(" }");
|
||||||
|
return Output.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UlxLuaValues::CheckType(ElxLuaValueType Type, ElxLuaValueType Desired)
|
||||||
|
{
|
||||||
|
if (Type != Desired)
|
||||||
|
{
|
||||||
|
FString TypeName = StaticEnum<ElxLuaValueType>()->GetDisplayNameTextByValue(int64(Type)).ToString();
|
||||||
|
FString DesiredName = StaticEnum<ElxLuaValueType>()->GetDisplayNameTextByValue(int64(Desired)).ToString();
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("Expected a value of type %s, but found %s instead."), *DesiredName, *TypeName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElxLuaValueType UlxLuaValues::GetType(int n) const
|
||||||
|
{
|
||||||
|
if (n < 0) return ElxLuaValueType::None;
|
||||||
|
if (n >= Types.Num()) return ElxLuaValueType::None;
|
||||||
|
return Types[Cursor];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the Nth value in the array. Array bounds-checking
|
||||||
|
// is handled by 'GetType', which returns 'None' for out-of-bounds
|
||||||
|
// accesses.
|
||||||
|
//
|
||||||
|
|
||||||
|
FString UlxLuaValues::GetString(int n) const
|
||||||
|
{
|
||||||
|
if (!CheckType(GetType(n), ElxLuaValueType::String)) return FString();
|
||||||
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
|
return Decoder.read_fstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
FName UlxLuaValues::GetName(int n) const
|
||||||
|
{
|
||||||
|
if (!CheckType(GetType(n), ElxLuaValueType::Name)) return FName();
|
||||||
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
|
return Decoder.read_fname();
|
||||||
|
}
|
||||||
|
|
||||||
|
double UlxLuaValues::GetFloat(int n) const
|
||||||
|
{
|
||||||
|
if (!CheckType(GetType(n), ElxLuaValueType::Float)) return 0.0;
|
||||||
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
|
return Decoder.read_double();
|
||||||
|
}
|
||||||
|
|
||||||
|
int UlxLuaValues::GetInt(int n) const
|
||||||
|
{
|
||||||
|
if (!CheckType(GetType(n), ElxLuaValueType::Float)) return 0;
|
||||||
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
|
return int(Decoder.read_double());
|
||||||
|
}
|
||||||
|
|
||||||
|
FVector UlxLuaValues::GetVector(int n) const
|
||||||
|
{
|
||||||
|
if (!CheckType(GetType(n), ElxLuaValueType::Vector)) return FVector();
|
||||||
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
|
return Decoder.read_fvector();
|
||||||
|
}
|
||||||
|
|
||||||
|
FVector2D UlxLuaValues::GetVector2D(int n) const
|
||||||
|
{
|
||||||
|
if (!CheckType(GetType(n), ElxLuaValueType::Vector)) return FVector2D();
|
||||||
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
|
FVector v = Decoder.read_fvector();
|
||||||
|
return FVector2D(v.X, v.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UlxLuaValues::GetBoolean(int n) const
|
||||||
|
{
|
||||||
|
if (!CheckType(GetType(n), ElxLuaValueType::Boolean)) return false;
|
||||||
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
|
return Decoder.read_bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -176,3 +176,145 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// These are the types that can actually be packed into
|
||||||
|
// a serialized buffer.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class ElxLuaValueType : uint8 {
|
||||||
|
None,
|
||||||
|
String,
|
||||||
|
Name,
|
||||||
|
Float,
|
||||||
|
Boolean,
|
||||||
|
Vector
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// This class stores an array of values that were returned by Lua.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
UCLASS(BlueprintType)
|
||||||
|
class INTEGRATION_API UlxLuaValues : public UObject
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The raw serialized data returned by Lua.
|
||||||
|
//
|
||||||
|
std::string Serialized;
|
||||||
|
|
||||||
|
// For each chunk, the type of the chunk.
|
||||||
|
//
|
||||||
|
TArray<ElxLuaValueType> Types;
|
||||||
|
|
||||||
|
// For each chunk, a pointer to the serialized data.
|
||||||
|
//
|
||||||
|
TArray<std::string_view> Data;
|
||||||
|
|
||||||
|
// The current cursor.
|
||||||
|
//
|
||||||
|
int Cursor;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Clear everything.
|
||||||
|
//
|
||||||
|
void Empty();
|
||||||
|
|
||||||
|
// Compare two types. If they aren't equal, log an error and return false.
|
||||||
|
//
|
||||||
|
static bool CheckType(ElxLuaValueType Type, ElxLuaValueType Desired);
|
||||||
|
|
||||||
|
public:
|
||||||
|
UlxLuaValues() { Cursor = 0; }
|
||||||
|
|
||||||
|
// Copies the data, and then preprocesses it to make sure
|
||||||
|
// it's all valid. If it's not valid, returns false.
|
||||||
|
//
|
||||||
|
bool Initialize(std::string_view data);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
FString DebugString() const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
int Length() const { return Types.Num(); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
int GetCursor() const { return Cursor; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
|
void SetCursor(int n) { Cursor = n; }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//
|
||||||
|
// Functions that get values from the array, random access.
|
||||||
|
//
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
ElxLuaValueType GetType(int n) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
bool IsType(int n, ElxLuaValueType Type) const { return GetType(n) == Type; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
FString GetString(int n) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
FName GetName(int n) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
double GetFloat(int n) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
int GetInt(int n) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
FVector GetVector(int n) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
FVector2D GetVector2D(int n) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
bool GetBoolean(int n) const;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functions that get values from the array using the cursor.
|
||||||
|
//
|
||||||
|
|
||||||
|
public:
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
ElxLuaValueType NextType() const { return GetType(Cursor); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
bool IsNextType(ElxLuaValueType Type) const { return IsType(Cursor, Type); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
|
FString ReadString() { return GetString(Cursor++); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
|
FName ReadName() { return GetName(Cursor++); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
|
double ReadFloat() { return GetFloat(Cursor++); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
|
int ReadInt() { return GetInt(Cursor++); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
|
FVector ReadVector() { return GetVector(Cursor++); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
|
FVector2D ReadVector2D() { return GetVector2D(Cursor++); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
|
bool ReadBoolean() { return GetBoolean(Cursor++); }
|
||||||
|
};
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "Tangible.h"
|
#include "Tangible.h"
|
||||||
#include "TangibleManager.h"
|
#include "TangibleManager.h"
|
||||||
#include "Blueprint/UserWidget.h"
|
#include "Blueprint/UserWidget.h"
|
||||||
|
#include "Kismet/GameplayStatics.h"
|
||||||
|
|
||||||
#include "CommonTypes.h"
|
#include "CommonTypes.h"
|
||||||
#include "AnimQueue.h"
|
#include "AnimQueue.h"
|
||||||
@@ -355,21 +356,46 @@ void ALuprexGameModeBase::ClearLookAtWidget(const UObject *Context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALuprexGameModeBase::SetLookAtWidget(const UObject *Context, UUserWidget *Widget, int ZOrder)
|
void ALuprexGameModeBase::SetLookAtWidget(const UObject *Context, UlxLookAtWidget *Widget)
|
||||||
{
|
{
|
||||||
ALuprexGameModeBase *Mode = FromContext(Context);
|
ALuprexGameModeBase *Mode = FromContext(Context);
|
||||||
if (Mode->LookAtWidget != Widget)
|
if (Mode->LookAtWidget != Widget)
|
||||||
{
|
{
|
||||||
ClearLookAtWidget(Context);
|
ClearLookAtWidget(Context);
|
||||||
}
|
}
|
||||||
if (Widget != nullptr)
|
if (!Widget->IsInViewport())
|
||||||
{
|
{
|
||||||
Widget->RemoveFromParent();
|
Widget->AddToViewport(100);
|
||||||
Widget->AddToViewport(ZOrder);
|
|
||||||
}
|
}
|
||||||
Mode->LookAtWidget = Widget;
|
Mode->LookAtWidget = Widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ALuprexGameModeBase::SetLookAt(const UObject *Context, const FHitResult &HitResult)
|
||||||
|
{
|
||||||
|
ALuprexGameModeBase *Mode = FromContext(Context);
|
||||||
|
Mode->CurrentLookAt = HitResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
FVector2D ALuprexGameModeBase::GetLookAtPixel(const UObject *Context)
|
||||||
|
{
|
||||||
|
ALuprexGameModeBase *Mode = FromContext(Context);
|
||||||
|
APlayerController *pc = Context->GetWorld()->GetFirstPlayerController();
|
||||||
|
if (pc == nullptr) return FVector2D();
|
||||||
|
FVector2D ScreenPosition;
|
||||||
|
UGameplayStatics::ProjectWorldToScreen(pc, Mode->CurrentLookAt.Location, ScreenPosition, false);
|
||||||
|
return ScreenPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
FVector2D ALuprexGameModeBase::GetPreviousLookAtPixel(const UObject *Context)
|
||||||
|
{
|
||||||
|
ALuprexGameModeBase *Mode = FromContext(Context);
|
||||||
|
APlayerController *pc = Context->GetWorld()->GetFirstPlayerController();
|
||||||
|
if (pc == nullptr) return FVector2D();
|
||||||
|
FVector2D ScreenPosition;
|
||||||
|
UGameplayStatics::ProjectWorldToScreen(pc, Mode->PreviousLookAt.Location, ScreenPosition, false);
|
||||||
|
return ScreenPosition;
|
||||||
|
}
|
||||||
|
|
||||||
void ALuprexGameModeBase::UpdateLookAt() {
|
void ALuprexGameModeBase::UpdateLookAt() {
|
||||||
// Rotate the variables.
|
// Rotate the variables.
|
||||||
PreviousLookAt = CurrentLookAt;
|
PreviousLookAt = CurrentLookAt;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "LuprexSockets.h"
|
#include "LuprexSockets.h"
|
||||||
#include "TriggeredTask.h"
|
#include "TriggeredTask.h"
|
||||||
#include "BlueprintErrors.h"
|
#include "BlueprintErrors.h"
|
||||||
|
#include "Blueprint/UserWidget.h"
|
||||||
#include "LuprexGameModeBase.generated.h"
|
#include "LuprexGameModeBase.generated.h"
|
||||||
|
|
||||||
// Messages that come from inside the Luprex Core.
|
// Messages that come from inside the Luprex Core.
|
||||||
@@ -20,12 +21,23 @@ DECLARE_LOG_CATEGORY_EXTERN(LogLuprex, Display, All);
|
|||||||
// Messages that pertain to our Luprex integration with Unreal.
|
// Messages that pertain to our Luprex integration with Unreal.
|
||||||
DECLARE_LOG_CATEGORY_EXTERN(LogLuprexIntegration, Display, All);
|
DECLARE_LOG_CATEGORY_EXTERN(LogLuprexIntegration, Display, All);
|
||||||
|
|
||||||
class LookAtDetector;
|
class UlxLuaValues;
|
||||||
|
|
||||||
|
|
||||||
|
UCLASS(BlueprintType)
|
||||||
|
class INTEGRATION_API UlxLookAtWidget : public UUserWidget
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Luprex|Look-At Detection")
|
||||||
|
void ReadLuaConfiguration(AActor *Place, UlxLuaValues *Config);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
UCLASS()
|
UCLASS(BlueprintType)
|
||||||
class INTEGRATION_API ALuprexGameModeBase : public AGameModeBase, public FRunnable
|
class INTEGRATION_API ALuprexGameModeBase : public AGameModeBase, public FRunnable
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
@@ -56,7 +68,7 @@ public:
|
|||||||
int64 GetPlayerId();
|
int64 GetPlayerId();
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
|
||||||
static void SetLookAt(const UObject *Context, const FHitResult &hit) { FromContext(Context)->CurrentLookAt = hit; }
|
static void SetLookAt(const UObject *Context, const FHitResult &HitResult);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
||||||
static const FHitResult &GetLookAt(const UObject *Context) { return FromContext(Context)->CurrentLookAt; }
|
static const FHitResult &GetLookAt(const UObject *Context) { return FromContext(Context)->CurrentLookAt; }
|
||||||
@@ -64,20 +76,26 @@ public:
|
|||||||
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
||||||
static const AActor *GetLookAtActor(const UObject *Context) { return FromContext(Context)->CurrentLookAt.GetActor(); }
|
static const AActor *GetLookAtActor(const UObject *Context) { return FromContext(Context)->CurrentLookAt.GetActor(); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
||||||
|
static FVector2D GetLookAtPixel(const UObject *Context);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
||||||
static const FHitResult &GetPreviousLookAt(const UObject *Context) { return FromContext(Context)->PreviousLookAt; }
|
static const FHitResult &GetPreviousLookAt(const UObject *Context) { return FromContext(Context)->PreviousLookAt; }
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
||||||
static const AActor *GetPreviousLookAtActor(const UObject *Context) { return FromContext(Context)->PreviousLookAt.GetActor(); }
|
static const AActor *GetPreviousLookAtActor(const UObject *Context) { return FromContext(Context)->PreviousLookAt.GetActor(); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
||||||
|
static FVector2D GetPreviousLookAtPixel(const UObject *Context);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
|
||||||
static bool IsLookAtChanged(const UObject *Context);
|
static bool IsLookAtChanged(const UObject *Context);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
|
||||||
static void SetLookAtWidget(const UObject *Context, UUserWidget *Widget, int ZOrder = 100);
|
static void SetLookAtWidget(const UObject *Context, UlxLookAtWidget *Widget);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
|
||||||
static UUserWidget *GetLookAtWidget(const UObject *Context) { return FromContext(Context)->LookAtWidget; }
|
static UlxLookAtWidget *GetLookAtWidget(const UObject *Context) { return FromContext(Context)->LookAtWidget; }
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
|
||||||
static void ClearLookAtWidget(const UObject *Context);
|
static void ClearLookAtWidget(const UObject *Context);
|
||||||
@@ -160,7 +178,7 @@ public:
|
|||||||
FHitResult CurrentLookAt;
|
FHitResult CurrentLookAt;
|
||||||
|
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
UUserWidget *LookAtWidget;
|
UlxLookAtWidget *LookAtWidget;
|
||||||
|
|
||||||
// The sensitivity level at which a log message triggers a debugger breakpoint.
|
// The sensitivity level at which a log message triggers a debugger breakpoint.
|
||||||
UPROPERTY(EditAnywhere, Category="Debugging Tools")
|
UPROPERTY(EditAnywhere, Category="Debugging Tools")
|
||||||
|
|||||||
@@ -1,154 +1,3 @@
|
|||||||
#include "StringDecoder.h"
|
#include "StringDecoder.h"
|
||||||
|
|
||||||
|
|
||||||
void UlxLuaValues::Empty()
|
|
||||||
{
|
|
||||||
Serialized.clear();
|
|
||||||
Types.Empty();
|
|
||||||
Data.Empty();
|
|
||||||
Cursor = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UlxLuaValues::Initialize(std::string_view data)
|
|
||||||
{
|
|
||||||
Empty();
|
|
||||||
Serialized = data;
|
|
||||||
const char *SerializedChar = &Serialized[0];
|
|
||||||
|
|
||||||
FlxStreamBuffer Decoder(Serialized);
|
|
||||||
|
|
||||||
while (!Decoder.empty())
|
|
||||||
{
|
|
||||||
SimpleDynamicTag Tag = Decoder.read_simple_dynamic_tag();
|
|
||||||
|
|
||||||
int64 Pos = Decoder.total_reads();
|
|
||||||
ElxLuaValueType Type;
|
|
||||||
switch (Tag)
|
|
||||||
{
|
|
||||||
case SimpleDynamicTag::BOOLEAN: Type=ElxLuaValueType::Boolean; Decoder.read_bool(); break;
|
|
||||||
case SimpleDynamicTag::NUMBER: Type=ElxLuaValueType::Float; Decoder.read_double(); break;
|
|
||||||
case SimpleDynamicTag::STRING: Type=ElxLuaValueType::String; Decoder.read_string_view(); break;
|
|
||||||
case SimpleDynamicTag::TOKEN: Type=ElxLuaValueType::Name; Decoder.read_string_view(); break;
|
|
||||||
case SimpleDynamicTag::VECTOR: Type=ElxLuaValueType::Vector; Decoder.read_fvector(); break;
|
|
||||||
default: {
|
|
||||||
Empty();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int64 Pos2 = Decoder.total_reads();
|
|
||||||
Types.Add(Type);
|
|
||||||
Data.Add(std::string_view(SerializedChar + Pos, Pos2 - Pos));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
FString UlxLuaValues::DebugString() const
|
|
||||||
{
|
|
||||||
TStringBuilder<2048> Output;
|
|
||||||
Output << TEXT("{ ");
|
|
||||||
for (int i = 0; i < Types.Num(); i++)
|
|
||||||
{
|
|
||||||
if (i > 0) Output << TEXT(", ");
|
|
||||||
|
|
||||||
ElxLuaValueType Type = Types[i];
|
|
||||||
FlxStreamBuffer Decoder(Data[i]);
|
|
||||||
switch (Type)
|
|
||||||
{
|
|
||||||
case ElxLuaValueType::Boolean:
|
|
||||||
Output << Decoder.read_bool();
|
|
||||||
break;
|
|
||||||
case ElxLuaValueType::Float:
|
|
||||||
Output << FString::Printf(TEXT("%lf"), Decoder.read_double());
|
|
||||||
break;
|
|
||||||
case ElxLuaValueType::String:
|
|
||||||
Output << TEXT("\"") << Decoder.read_fstring() << TEXT("\"");
|
|
||||||
break;
|
|
||||||
case ElxLuaValueType::Name:
|
|
||||||
Output << Decoder.read_fname();
|
|
||||||
break;
|
|
||||||
case ElxLuaValueType::Vector: {
|
|
||||||
FVector Vec = Decoder.read_fvector();
|
|
||||||
Output << FString::Printf(TEXT("(%lf, %lf, %lf)"), Vec.X, Vec.Y, Vec.Z);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Output << TEXT(" }");
|
|
||||||
return Output.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UlxLuaValues::CheckType(ElxLuaValueType Type, ElxLuaValueType Desired)
|
|
||||||
{
|
|
||||||
if (Type != Desired)
|
|
||||||
{
|
|
||||||
FString TypeName = StaticEnum<ElxLuaValueType>()->GetDisplayNameTextByValue(int64(Type)).ToString();
|
|
||||||
FString DesiredName = StaticEnum<ElxLuaValueType>()->GetDisplayNameTextByValue(int64(Desired)).ToString();
|
|
||||||
UE_LOG(LogBlueprint, Error, TEXT("Expected a value of type %s, but found %s instead."), *DesiredName, *TypeName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ElxLuaValueType UlxLuaValues::GetType(int n) const
|
|
||||||
{
|
|
||||||
if (n < 0) return ElxLuaValueType::None;
|
|
||||||
if (n >= Types.Num()) return ElxLuaValueType::None;
|
|
||||||
return Types[Cursor];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get the Nth value in the array. Array bounds-checking
|
|
||||||
// is handled by 'GetType', which returns 'None' for out-of-bounds
|
|
||||||
// accesses.
|
|
||||||
//
|
|
||||||
|
|
||||||
FString UlxLuaValues::GetString(int n) const
|
|
||||||
{
|
|
||||||
if (!CheckType(GetType(n), ElxLuaValueType::String)) return FString();
|
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
|
||||||
return Decoder.read_fstring();
|
|
||||||
}
|
|
||||||
|
|
||||||
FName UlxLuaValues::GetName(int n) const
|
|
||||||
{
|
|
||||||
if (!CheckType(GetType(n), ElxLuaValueType::Name)) return FName();
|
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
|
||||||
return Decoder.read_fname();
|
|
||||||
}
|
|
||||||
|
|
||||||
double UlxLuaValues::GetFloat(int n) const
|
|
||||||
{
|
|
||||||
if (!CheckType(GetType(n), ElxLuaValueType::Float)) return 0.0;
|
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
|
||||||
return Decoder.read_double();
|
|
||||||
}
|
|
||||||
|
|
||||||
int UlxLuaValues::GetInt(int n) const
|
|
||||||
{
|
|
||||||
if (!CheckType(GetType(n), ElxLuaValueType::Float)) return 0;
|
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
|
||||||
return int(Decoder.read_double());
|
|
||||||
}
|
|
||||||
|
|
||||||
FVector UlxLuaValues::GetVector(int n) const
|
|
||||||
{
|
|
||||||
if (!CheckType(GetType(n), ElxLuaValueType::Vector)) return FVector();
|
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
|
||||||
return Decoder.read_fvector();
|
|
||||||
}
|
|
||||||
|
|
||||||
FVector2D UlxLuaValues::GetVector2D(int n) const
|
|
||||||
{
|
|
||||||
if (!CheckType(GetType(n), ElxLuaValueType::Vector)) return FVector2D();
|
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
|
||||||
FVector v = Decoder.read_fvector();
|
|
||||||
return FVector2D(v.X, v.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UlxLuaValues::GetBoolean(int n) const
|
|
||||||
{
|
|
||||||
if (!CheckType(GetType(n), ElxLuaValueType::Boolean)) return false;
|
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
|
||||||
return Decoder.read_bool();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "lpx-basebuffer.hpp"
|
#include "lpx-basebuffer.hpp"
|
||||||
|
|
||||||
#include "StringDecoder.generated.h"
|
|
||||||
|
|
||||||
class FlxStreamBufferCore {
|
class FlxStreamBufferCore {
|
||||||
private:
|
private:
|
||||||
bool err_eof_on_read_;
|
bool err_eof_on_read_;
|
||||||
@@ -68,144 +66,3 @@ public:
|
|||||||
return FName(s.size(), (const UTF8CHAR *)s.data(), FNAME_Add);
|
return FName(s.size(), (const UTF8CHAR *)s.data(), FNAME_Add);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// These are the types that can actually be packed into
|
|
||||||
// a serialized buffer.
|
|
||||||
//
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
UENUM(BlueprintType)
|
|
||||||
enum class ElxLuaValueType : uint8 {
|
|
||||||
None,
|
|
||||||
String,
|
|
||||||
Name,
|
|
||||||
Float,
|
|
||||||
Boolean,
|
|
||||||
Vector
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// This class stores an array of values that were returned by Lua.
|
|
||||||
//
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
UCLASS(MinimalAPI)
|
|
||||||
class UlxLuaValues : public UObject
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
private:
|
|
||||||
// The raw serialized data returned by Lua.
|
|
||||||
//
|
|
||||||
std::string Serialized;
|
|
||||||
|
|
||||||
// For each chunk, the type of the chunk.
|
|
||||||
//
|
|
||||||
TArray<ElxLuaValueType> Types;
|
|
||||||
|
|
||||||
// For each chunk, a pointer to the serialized data.
|
|
||||||
//
|
|
||||||
TArray<std::string_view> Data;
|
|
||||||
|
|
||||||
// The current cursor.
|
|
||||||
//
|
|
||||||
int Cursor;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Clear everything.
|
|
||||||
//
|
|
||||||
void Empty();
|
|
||||||
|
|
||||||
// Compare two types. If they aren't equal, log an error and return false.
|
|
||||||
//
|
|
||||||
static bool CheckType(ElxLuaValueType Type, ElxLuaValueType Desired);
|
|
||||||
|
|
||||||
public:
|
|
||||||
UlxLuaValues() { Cursor = 0; }
|
|
||||||
|
|
||||||
// Copies the data, and then preprocesses it to make sure
|
|
||||||
// it's all valid. If it's not valid, returns false.
|
|
||||||
//
|
|
||||||
bool Initialize(std::string_view data);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
FString DebugString() const;
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
int Length() const { return Types.Num(); }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
int GetCursor() const { return Cursor; }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
|
||||||
void SetCursor(int n) { Cursor = n; }
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
//
|
|
||||||
// Functions that get values from the array, random access.
|
|
||||||
//
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
ElxLuaValueType GetType(int n) const;
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
bool IsType(int n, ElxLuaValueType Type) const { return GetType(n) == Type; }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
FString GetString(int n) const;
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
FName GetName(int n) const;
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
double GetFloat(int n) const;
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
int GetInt(int n) const;
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
FVector GetVector(int n) const;
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
FVector2D GetVector2D(int n) const;
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
bool GetBoolean(int n) const;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Functions that get values from the array using the cursor.
|
|
||||||
//
|
|
||||||
|
|
||||||
public:
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
ElxLuaValueType NextType() const { return GetType(Cursor); }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
|
||||||
bool IsNextType(ElxLuaValueType Type) const { return IsType(Cursor, Type); }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
|
||||||
FString ReadString() { return GetString(Cursor++); }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
|
||||||
FName ReadName() { return GetName(Cursor++); }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
|
||||||
double ReadFloat() { return GetFloat(Cursor++); }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
|
||||||
int ReadInt() { return GetInt(Cursor++); }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
|
||||||
FVector ReadVector() { return GetVector(Cursor++); }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
|
||||||
FVector2D ReadVector2D() { return GetVector2D(Cursor++); }
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
|
||||||
bool ReadBoolean() { return GetBoolean(Cursor++); }
|
|
||||||
};
|
|
||||||
@@ -77,6 +77,9 @@ public:
|
|||||||
// Be aware that (0.0, 0.0) is the upper-left corner of the upper-left pixel,
|
// Be aware that (0.0, 0.0) is the upper-left corner of the upper-left pixel,
|
||||||
// whereas (0.5, 0.5) is the center of the upper-left pixel.
|
// whereas (0.5, 0.5) is the center of the upper-left pixel.
|
||||||
//
|
//
|
||||||
|
// The resulting TraceStart and TraceEnd fields of the HitResult will not
|
||||||
|
// contain world positions, instead, they will contain the PixelXY.
|
||||||
|
//
|
||||||
UFUNCTION(BlueprintCallable, Category="Collision", meta=(AutoCreateRefTerm="ActorsToIgnore", Keywords="raycast"))
|
UFUNCTION(BlueprintCallable, Category="Collision", meta=(AutoCreateRefTerm="ActorsToIgnore", Keywords="raycast"))
|
||||||
static bool LineTraceThroughPixel(const APlayerController* PlayerController,
|
static bool LineTraceThroughPixel(const APlayerController* PlayerController,
|
||||||
FVector2D PixelXY, double MaxDistanceFromCamera,
|
FVector2D PixelXY, double MaxDistanceFromCamera,
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ eng::string World::probe_lua_expr(int64_t actor_id, std::string_view lua) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::probe_lua_call(int64_t place_id, int64_t actor_id, std::string_view datapack, StreamBuffer *retvals) {
|
void World::probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view datapack, StreamBuffer *retvals) {
|
||||||
assert(stack_is_clear());
|
assert(stack_is_clear());
|
||||||
lua_State *L = state();
|
lua_State *L = state();
|
||||||
|
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ public:
|
|||||||
// Print statements are discarded. The lua function may return a vector
|
// Print statements are discarded. The lua function may return a vector
|
||||||
// of values. If so, the values are packed into a StreamBuffer.
|
// of values. If so, the values are packed into a StreamBuffer.
|
||||||
//
|
//
|
||||||
void probe_lua_call(int64_t place_id, int64_t actor_id, std::string_view datapack, StreamBuffer *retvals);
|
void probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view datapack, StreamBuffer *retvals);
|
||||||
|
|
||||||
// Invoke an Invocation object.
|
// Invoke an Invocation object.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -18,11 +18,17 @@ function engio.move(action, xyz, facing)
|
|||||||
tangible.animate(actor, nil, {action=action, xyz=xyz, facing=facing})
|
tangible.animate(actor, nil, {action=action, xyz=xyz, facing=facing})
|
||||||
end
|
end
|
||||||
|
|
||||||
function engio.printhi(a1, a2, a3, a4, a5)
|
function cube.getlookat()
|
||||||
pprint("Hi there", a1, a2, a3, a4, a5)
|
return { "Hotkeys", "X", "I Am a Cube" }
|
||||||
end
|
end
|
||||||
|
|
||||||
function engio.retmany()
|
function sphere.getlookat()
|
||||||
return 7, vec(8,9,10), "Yo", "Banana", 13.2, vec(2,3,4), "Hi"
|
return { "Hotkeys", "X", "I Am a Sphere" }
|
||||||
|
end
|
||||||
|
|
||||||
|
function engio.getlookat()
|
||||||
|
local place = tangible.place()
|
||||||
|
local class = tangible.getclass(place)
|
||||||
|
return class.getlookat()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user