From a987754b38d0a9525410a29837a8a2b2a0541846 Mon Sep 17 00:00:00 2001 From: jyelon Date: Tue, 17 Feb 2026 15:49:52 -0500 Subject: [PATCH] Can now switch the skeletal mesh on a character --- .claude/settings.local.json | 7 ++- .../Mannequins/Meshes/SKM_Manny.uasset | 3 - .../Mannequins/Meshes/SKM_Quinn.uasset | 3 - Content/SkeletalMeshes/SKM_Manny.uasset | 3 + Content/SkeletalMeshes/SKM_Quinn.uasset | 3 + Content/Tangibles/TAN_Character.uasset | 4 +- Content/Tangibles/TAN_StaticMesh.uasset | 4 +- Docs/Error-Handling-in-Blueprints.md | 52 ++++++++++++++++ Docs/Print-Statement-Handling.md | 3 + Source/Integration/AnimQueue.cpp | 62 +++++++++---------- Source/Integration/AnimQueue.h | 56 ++++++----------- Source/Integration/AssetLookup.cpp | 48 +++++++------- Source/Integration/AssetLookup.h | 22 +++---- Source/Integration/ConsoleOutput.h | 9 --- Source/Integration/LuprexGameModeBase.h | 1 + luprex/lua/login.lua | 2 +- 16 files changed, 157 insertions(+), 125 deletions(-) delete mode 100644 Content/Characters/Mannequins/Meshes/SKM_Manny.uasset delete mode 100644 Content/Characters/Mannequins/Meshes/SKM_Quinn.uasset create mode 100644 Content/SkeletalMeshes/SKM_Manny.uasset create mode 100644 Content/SkeletalMeshes/SKM_Quinn.uasset create mode 100644 Docs/Error-Handling-in-Blueprints.md diff --git a/.claude/settings.local.json b/.claude/settings.local.json index ff4165c3..cdcd3d8f 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -3,7 +3,12 @@ "allow": [ "WebFetch(domain:dev.epicgames.com)", "WebFetch(domain:github.com)", - "Bash(grep:*)" + "Bash(grep:*)", + "WebSearch", + "Bash(clangd:*)", + "Bash(clangd-16:*)", + "Bash(ssh jyelon-office \"clangd --version 2>/dev/null || clangd-16 --version 2>/dev/null || clangd-18 --version 2>/dev/null || ls /usr/bin/clangd*\")", + "Bash(git check-ignore:*)" ], "deny": [ "Bash(git commit *)", diff --git a/Content/Characters/Mannequins/Meshes/SKM_Manny.uasset b/Content/Characters/Mannequins/Meshes/SKM_Manny.uasset deleted file mode 100644 index 9f1f7d25..00000000 --- a/Content/Characters/Mannequins/Meshes/SKM_Manny.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f1df1a6b3db170cd80f14c40653fbc9a692af00f7abd575872d9cd8a707e05c6 -size 34534883 diff --git a/Content/Characters/Mannequins/Meshes/SKM_Quinn.uasset b/Content/Characters/Mannequins/Meshes/SKM_Quinn.uasset deleted file mode 100644 index 113ac4e3..00000000 --- a/Content/Characters/Mannequins/Meshes/SKM_Quinn.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e0fdd468262ff66fd30eb55f7bac167063959e5d9dbfa36abf853a5d77616a59 -size 36495654 diff --git a/Content/SkeletalMeshes/SKM_Manny.uasset b/Content/SkeletalMeshes/SKM_Manny.uasset new file mode 100644 index 00000000..19e20a8e --- /dev/null +++ b/Content/SkeletalMeshes/SKM_Manny.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7422d8fcca75f00052b6ac373c3e01c8949e473f063b8168a93943c94fe4fdd9 +size 28740774 diff --git a/Content/SkeletalMeshes/SKM_Quinn.uasset b/Content/SkeletalMeshes/SKM_Quinn.uasset new file mode 100644 index 00000000..ca70fa1b --- /dev/null +++ b/Content/SkeletalMeshes/SKM_Quinn.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f37827d82c8f401dcf09770ad759c26b3262b10fb0b9063c5d7bee03eb35a78 +size 29920576 diff --git a/Content/Tangibles/TAN_Character.uasset b/Content/Tangibles/TAN_Character.uasset index 04bc708c..f81d9978 100644 --- a/Content/Tangibles/TAN_Character.uasset +++ b/Content/Tangibles/TAN_Character.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb03a154075d2c3ec064b3575f29b626b07033c11ac69370a20bd9eedd977241 -size 353650 +oid sha256:2abb2748d894962e38ab916b3a44223695e0c6e73922ea5b0ec5eab178d09e94 +size 372022 diff --git a/Content/Tangibles/TAN_StaticMesh.uasset b/Content/Tangibles/TAN_StaticMesh.uasset index 88358ae9..55ac32c5 100644 --- a/Content/Tangibles/TAN_StaticMesh.uasset +++ b/Content/Tangibles/TAN_StaticMesh.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97fe013189aa595f83478cfde4d54b68795dd2f4edaccaa7f10e427b71c73b11 -size 166413 +oid sha256:a5e1c913cfa2a383d85db1ed87ce12bd06267d3686446c54ca2c8cec4a2c0cbb +size 165020 diff --git a/Docs/Error-Handling-in-Blueprints.md b/Docs/Error-Handling-in-Blueprints.md new file mode 100644 index 00000000..eaee59aa --- /dev/null +++ b/Docs/Error-Handling-in-Blueprints.md @@ -0,0 +1,52 @@ +# Error Handling in Blueprints + +## Format Log Message Node + +We have implemented "Format Message", which is an improved version of Unreal's +"Format Text". Unlike "Format Text", it has built-in support to print +vectors, rotations, enums, and quite a few other types. + +We have also implemented "Format Log Message", which is like Format Message +except that the output goes to the unreal logs. It might help to familiarize +yourself with Unreal's built-in logging function, UE_LOG. Format Log Message +is meant to be the Blueprint front end to UE_LOG. + +Format Message and Format Log Message both require a format string, which +will typically look something like this: + + "Hello, {Name}, the weather today will be {Weather}" + +When you set a format string such as the one above, the Format Message node +will add pins for the placeholders - in the example above, the pins +Name and Weather would be added. These are wildcard pins that you can +connect any printable value to. + +To make a new type printable, look at FormatDataLibrary.h + +Format Log Message accepts a severity level, this is directly based on +the severity levels supported by UE_LOG. It adds *ThrottledDisplay* and +*ThrottledLog*, which do the same thing as *Display* and *Log*, except +that output is limited to one message per second. + +## The Blueprint Debugger Pauses on Error Messages + +The blueprint debugger will pause whenever you log an error message. This is functionality we have added to Unreal. +You can control the severity at which it pauses: in the GameMode, there is a dropdown for the severity level. +You can also effectively turn it off by telling to only pause on fatal errors. + +There is a quirk: the debugger pauses before the error gets put into the logs. So when you're in the +blueprint debugger, +the only place the error will appear is in the lower-right corner of the screen, where debugger messages are +reported. You won't see the error in the unreal output log. If you single-step, the error will appear +in the output log as well. + +To understand how this is implemented, it helps to understand that log messages in unreal go to a bunch of +different output devices: the unreal editor output window, the visual studio output window, a log file, and +several more places. To dispatch messages to all these different destinations, Unreal has an output device +list that you can add an output device to. + +To implement this break-on-error-message functionality, we implemented a pseudo-output-device. +The pseudo device doesn't actually send +the error message anywhere, it just triggers the debugger. For more information about implementation, +see BreakToDebugger.h + diff --git a/Docs/Print-Statement-Handling.md b/Docs/Print-Statement-Handling.md index 3c59d5b4..161d8972 100644 --- a/Docs/Print-Statement-Handling.md +++ b/Docs/Print-Statement-Handling.md @@ -143,3 +143,6 @@ it adds those string to the UlxConsoleOutput. The UlxConsoleOutput turns those individual lines into one big string. From there, the LuprexGameMode copies the entire string into the body of a UMG text widget. + +## A Possible new lua print function + diff --git a/Source/Integration/AnimQueue.cpp b/Source/Integration/AnimQueue.cpp index fcc97280..cd0ad754 100644 --- a/Source/Integration/AnimQueue.cpp +++ b/Source/Integration/AnimQueue.cpp @@ -627,45 +627,43 @@ void UlxAnimationStepLibrary::AnimationStepApplyMaterials(const FlxAnimationStep } } -void UlxAnimationStepLibrary::AnimationStepApplyMesh(const FlxAnimationStep& step, bool FallbackToBP, AActor* actor) { - if (actor == nullptr) return; +void UlxAnimationStepLibrary::AnimationStepApplyStaticMesh(const FlxAnimationStep& step, bool FallbackToBP, + UStaticMeshComponent* MeshComp, UStaticMesh* Fallback) { + if (MeshComp == nullptr) return; - // Step 1: Look for a "mesh" or "bp" string field in the animation step. - // FString MeshName = AnimationStepGetString(step, TEXT("mesh")); if (MeshName.IsEmpty() && FallbackToBP) { MeshName = AnimationStepGetString(step, TEXT("bp")); } - if (MeshName.IsEmpty()) return; - // Step 2: Find the actor's mesh component. There must be exactly one. - // - TInlineComponentArray MeshComponents; - actor->GetComponents(MeshComponents); - if (MeshComponents.Num() != 1) { - UE_LOG(LogLuprexIntegration, Error, TEXT("AnimationStepApplyMesh: Actor %s has %d mesh components, expected exactly 1"), *actor->GetName(), MeshComponents.Num()); - return; + UStaticMesh* NewMesh = nullptr; + if (!MeshName.IsEmpty()) { + UlxAssetLookup::LoadStaticMeshAsset(NewMesh, MeshComp, MeshName); } - UMeshComponent* MeshComp = MeshComponents[0]; - - // Step 3: Apply the mesh based on the component type. - // - if (UStaticMeshComponent* StaticComp = Cast(MeshComp)) { - UStaticMesh* NewMesh = nullptr; - UlxAssetLookup::LoadStaticMeshAsset(NewMesh, actor, MeshName, false); - if (NewMesh == nullptr) return; - if (StaticComp->GetStaticMesh() != NewMesh) { - StaticComp->SetStaticMesh(NewMesh); - } - } else if (USkeletalMeshComponent* SkelComp = Cast(MeshComp)) { - USkeletalMesh* NewMesh = nullptr; - UlxAssetLookup::LoadSkeletalMeshAsset(NewMesh, actor, MeshName, true); - if (NewMesh == nullptr) return; - if (SkelComp->GetSkeletalMeshAsset() != NewMesh) { - SkelComp->SetSkeletalMeshAsset(NewMesh); - } - } else { - UE_LOG(LogLuprexIntegration, Error, TEXT("AnimationStepApplyMesh: Actor %s has unsupported mesh component type"), *actor->GetName()); + if (NewMesh == nullptr) NewMesh = Fallback; + if (NewMesh == nullptr) return; + if (MeshComp->GetStaticMesh() != NewMesh) { + MeshComp->SetStaticMesh(NewMesh); + } +} + +void UlxAnimationStepLibrary::AnimationStepApplySkeletalMesh(const FlxAnimationStep& step, bool FallbackToBP, + USkeletalMeshComponent* MeshComp, USkeletalMesh* Fallback) { + if (MeshComp == nullptr) return; + + FString MeshName = AnimationStepGetString(step, TEXT("mesh")); + if (MeshName.IsEmpty() && FallbackToBP) { + MeshName = AnimationStepGetString(step, TEXT("bp")); + } + + USkeletalMesh* NewMesh = nullptr; + if (!MeshName.IsEmpty()) { + UlxAssetLookup::LoadSkeletalMeshAsset(NewMesh, MeshComp, MeshName); + } + if (NewMesh == nullptr) NewMesh = Fallback; + if (NewMesh == nullptr) return; + if (MeshComp->GetSkeletalMeshAsset() != NewMesh) { + MeshComp->SetSkeletalMeshAsset(NewMesh); } } diff --git a/Source/Integration/AnimQueue.h b/Source/Integration/AnimQueue.h index bc1f7bdc..e1514a26 100644 --- a/Source/Integration/AnimQueue.h +++ b/Source/Integration/AnimQueue.h @@ -125,55 +125,40 @@ public: UFUNCTION(BlueprintPure, meta = (BlueprintAutocast), Category = "Luprex|Animation Step") static int64 AnimationStepID(const FlxAnimationStep& step) { return step.Hash; } -<<<<<<< HEAD // Using mat_xxxx values from the animation step, update the actor's // material parameters. Doing this may involve creating or replacing // dynamic material instances for the actor. -======= - // Scan an animation step for key-value pairs of the - // form mat_XXXX={x,y,z}. For each match, create a - // dynamic material instance on the actor's mesh - // components and set the vector parameter XXXX. - // Materials are restored to their base (non-dynamic) - // state before applying, so parameters from previous - // calls do not persist. ->>>>>>> 9b1dd00a45a7b17c3546f8574d00e5ec78f17c75 // UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "actor"), Category = "Luprex|Animation Step") static void AnimationStepApplyMaterials(const FlxAnimationStep& step, AActor* actor); -<<<<<<< HEAD - // Look for a mesh=name key-value pair in the animation step. - // If found, load the named mesh and apply it to the actor's - // mesh component. The actor must have exactly one mesh component. - // If FallbackToBP is true, and mesh=name is not present, looks - // for a bp=name pair instead. -======= - // Look for a mesh=name key-value pair. If found, load - // the named mesh and apply it to the actor's mesh - // component. The actor must have exactly one mesh - // component. ->>>>>>> 9b1dd00a45a7b17c3546f8574d00e5ec78f17c75 + // Loads a new static mesh, using the animation step to choose it. + // If the chosen mesh is already installed, no changes are made. + // Looks for 'mesh=name' first; if not found and FallbackToBP is + // true, looks for 'bp=name'. If no mesh is successfully loaded, + // uses the Fallback mesh. Failed loads are logged once. // - UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "actor"), Category = "Luprex|Animation Step") - static void AnimationStepApplyMesh(const FlxAnimationStep& step, bool FallbackToBP, AActor* actor); + UFUNCTION(BlueprintCallable, Category = "Luprex|Animation Step") + static void AnimationStepApplyStaticMesh(const FlxAnimationStep& step, bool FallbackToBP, + UStaticMeshComponent* MeshComp, UStaticMesh* Fallback = nullptr); + + // Loads a new skeletal mesh, using the animation step to choose it. + // If the chosen mesh is already installed, no changes are made. + // Looks for 'mesh=name' first; if not found and FallbackToBP is + // true, looks for 'bp=name'. If no mesh is successfully loaded, + // uses the Fallback mesh. Failed loads are logged once. + // + UFUNCTION(BlueprintCallable, Category = "Luprex|Animation Step") + static void AnimationStepApplySkeletalMesh(const FlxAnimationStep& step, bool FallbackToBP, + USkeletalMeshComponent* MeshComp, USkeletalMesh* Fallback = nullptr); }; //////////////////////////////////////////////////////////// // -<<<<<<< HEAD // An animation step that doesn't actually store the step, // it just contains a pointer to the string. // -//////////////////////////////////////////////// -======= -// FlxAnimationStepView -// -// A lightweight, non-owning view of an animation -// step (hash + body as a string_view). -// //////////////////////////////////////////////////////////// ->>>>>>> 9b1dd00a45a7b17c3546f8574d00e5ec78f17c75 struct FlxAnimationStepView { int64 Hash; @@ -266,13 +251,8 @@ private: FlxStreamBuffer Decoder; public: -<<<<<<< HEAD - // Initialize the FlxAnimationStepDecoder. - // -======= // Initialize from an encoded step body. // ->>>>>>> 9b1dd00a45a7b17c3546f8574d00e5ec78f17c75 FlxAnimationStepDecoder(std::string_view body) : Decoder(body) {} // Return true if the parser has reached EOF. diff --git a/Source/Integration/AssetLookup.cpp b/Source/Integration/AssetLookup.cpp index 0df3a7b7..c18a5ea0 100644 --- a/Source/Integration/AssetLookup.cpp +++ b/Source/Integration/AssetLookup.cpp @@ -20,7 +20,7 @@ void UlxAssetLookup::RebuildIndex() IAssetRegistry::GetChecked().WaitForCompletion(); AssetPaths.Empty(); AddAssets(TEXT("/Game/StaticMeshes"), UStaticMesh::StaticClass(), TEXT("SM_")); - AddAssets(TEXT("/Game/SkeletalMeshes"), USkeletalMesh::StaticClass(), TEXT("SK_")); + AddAssets(TEXT("/Game/SkeletalMeshes"), USkeletalMesh::StaticClass(), TEXT("SKM_")); AddAssets(TEXT("/Game/AnimSequences"), UAnimSequence::StaticClass(), TEXT("SEQ_")); AddAssets(TEXT("/Game/Tangibles"), UBlueprint::StaticClass(), TEXT("TAN_")); AddAssets(TEXT("/Game/Widgets"), UWidgetBlueprint::StaticClass(), TEXT("WB_")); @@ -52,16 +52,22 @@ void UlxAssetLookup::AddAssets(const TCHAR *Path, UClass *Class, const TCHAR *Na FoundData.Num(), *Class->GetName(), Path); } -UObject *UlxAssetLookup::LoadAsset(const UObject *Context, UClass *Class, UClass *ChildOf, const FString &Name, bool ErrorIfNotFound) +void UlxAssetLookup::ReportFailedLoad(const FString &ClassName, const FString &Name, const FString &Reason) +{ + static TSet Reported; + FString Key = ClassName + TEXT(":") + Name + TEXT(":") + Reason; + if (Reported.Contains(Key)) return; + Reported.Add(Key); + UE_LOG(LogLuprexIntegration, Display, TEXT("Loading %s %s: %s"), *ClassName, *Name, *Reason); +} + +UObject *UlxAssetLookup::LoadAsset(const UObject *Context, UClass *Class, UClass *ChildOf, const FString &Name) { const UlxAssetLookup *Lookup = ALuprexGameModeBase::FromContext(Context)->GetAssetLookup(); const FString *Path = Lookup->AssetPaths.Find(MakeTuple(Class->GetName(), FName(Name))); if (Path == nullptr) { - if (ErrorIfNotFound) - { - UE_LOG(LogLuprexIntegration, Error, TEXT("Loading %s %s: asset not found"), *Class->GetName(), *Name); - } + ReportFailedLoad(Class->GetName(), Name, TEXT("asset not found")); return nullptr; } @@ -77,7 +83,7 @@ UObject *UlxAssetLookup::LoadAsset(const UObject *Context, UClass *Class, UClass if (Result == nullptr) { - UE_LOG(LogLuprexIntegration, Error, TEXT("Loading %s %s: unknown load failure"), *Class->GetName(), *Name); + ReportFailedLoad(Class->GetName(), Name, TEXT("unknown load failure")); return nullptr; } @@ -86,7 +92,7 @@ UObject *UlxAssetLookup::LoadAsset(const UObject *Context, UClass *Class, UClass UClass *ResClass = (UClass *)Result; if (!ResClass->IsChildOf(ChildOf)) { - UE_LOG(LogLuprexIntegration, Error, TEXT("Loading %s %s: blueprint not a child of %s"), *Class->GetName(), *Name, *ChildOf->GetName()); + ReportFailedLoad(Class->GetName(), Name, FString::Printf(TEXT("blueprint not a child of %s"), *ChildOf->GetName())); return nullptr; } } @@ -95,50 +101,50 @@ UObject *UlxAssetLookup::LoadAsset(const UObject *Context, UClass *Class, UClass } ElxValidOrNotValid UlxAssetLookup::LoadStaticMeshAsset( - UStaticMesh *&Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) + UStaticMesh *&Result, const UObject *Context, const FString &Name) { - Result = (UStaticMesh *)LoadAsset(Context, UStaticMesh::StaticClass(), nullptr, Name, ErrorIfNotFound); + Result = (UStaticMesh *)LoadAsset(Context, UStaticMesh::StaticClass(), nullptr, Name); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadSkeletalMeshAsset( - USkeletalMesh *&Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) + USkeletalMesh *&Result, const UObject *Context, const FString &Name) { - Result = (USkeletalMesh *)LoadAsset(Context, USkeletalMesh::StaticClass(), nullptr, Name, ErrorIfNotFound); + Result = (USkeletalMesh *)LoadAsset(Context, USkeletalMesh::StaticClass(), nullptr, Name); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadAnimSequenceAsset( - UAnimSequence *&Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) + UAnimSequence *&Result, const UObject *Context, const FString &Name) { - Result = (UAnimSequence *)LoadAsset(Context, UAnimSequence::StaticClass(), nullptr, Name, ErrorIfNotFound); + Result = (UAnimSequence *)LoadAsset(Context, UAnimSequence::StaticClass(), nullptr, Name); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadTangibleBlueprintAsset( - TSubclassOf &Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) + TSubclassOf &Result, const UObject *Context, const FString &Name) { - Result = (UClass*)LoadAsset(Context, UBlueprint::StaticClass(), AActor::StaticClass(), Name, ErrorIfNotFound); + Result = (UClass*)LoadAsset(Context, UBlueprint::StaticClass(), AActor::StaticClass(), Name); if (Result == nullptr) return NotValid; UFunction *aqchanged = Result->FindFunctionByName(FName(TEXT("Animation Queue Changed"))); if ((aqchanged == nullptr)||(aqchanged->ParmsSize != 0)) { - UE_LOG(LogLuprexIntegration, Error, TEXT("Loading Blueprint %s: Tangible does not have 'Animation Queue Changed' function"), *Name); + ReportFailedLoad(TEXT("Blueprint"), Name, TEXT("tangible does not have 'Animation Queue Changed' function")); Result = nullptr; return NotValid; } return Valid; } ElxValidOrNotValid UlxAssetLookup::LoadUserWidgetAsset( - TSubclassOf &Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) + TSubclassOf &Result, const UObject *Context, const FString &Name) { - Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UUserWidget::StaticClass(), Name, ErrorIfNotFound); + Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UUserWidget::StaticClass(), Name); return Result ? Valid : NotValid; } ElxValidOrNotValid UlxAssetLookup::LoadLuaWidgetAsset( - TSubclassOf &Result, const UObject *Context, const FString &Name, bool ErrorIfNotFound) + TSubclassOf &Result, const UObject *Context, const FString &Name) { - Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UlxLuaWidget::StaticClass(), Name, ErrorIfNotFound); + Result = (UClass *)LoadAsset(Context, UWidgetBlueprint::StaticClass(), UlxLuaWidget::StaticClass(), Name); return Result ? Valid : NotValid; } diff --git a/Source/Integration/AssetLookup.h b/Source/Integration/AssetLookup.h index 79514e1a..88e3dadf 100644 --- a/Source/Integration/AssetLookup.h +++ b/Source/Integration/AssetLookup.h @@ -43,7 +43,9 @@ private: void AddAssets(const TCHAR *Path, UClass *Class, const TCHAR *NamePrefix); - static UObject *LoadAsset(const UObject *Context, UClass *Class, UClass *ChildOf, const FString &Name, bool ErrorIfNotFound); + static void ReportFailedLoad(const FString &ClassName, const FString &Name, const FString &Reason); + + static UObject *LoadAsset(const UObject *Context, UClass *Class, UClass *ChildOf, const FString &Name); public: void RebuildIndex(); @@ -52,41 +54,35 @@ public: // UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context", ExpandEnumAsExecs="ReturnValue"), Category = "Luprex|Asset Loading") static ElxValidOrNotValid LoadStaticMeshAsset( - UStaticMesh *&Result, - const UObject *Context, const FString &Name, bool ErrorIfNotFound = false); + UStaticMesh *&Result, const UObject *Context, const FString &Name); // Get a skeletal mesh by name. // UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context", ExpandEnumAsExecs="ReturnValue"), Category = "Luprex|Asset Loading") static ElxValidOrNotValid LoadSkeletalMeshAsset( - USkeletalMesh *&Result, - const UObject *Context, const FString &Name, bool ErrorIfNotFound = false); + USkeletalMesh *&Result, const UObject *Context, const FString &Name); // Get an animation sequence by name. // UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context", ExpandEnumAsExecs="ReturnValue"), Category = "Luprex|Asset Loading") static ElxValidOrNotValid LoadAnimSequenceAsset( - UAnimSequence *&Result, - const UObject *Context, const FString &Name, bool ErrorIfNotFound = false); + UAnimSequence *&Result, const UObject *Context, const FString &Name); // Get a tangible class by name. // UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context", ExpandEnumAsExecs="ReturnValue"), Category = "Luprex|Asset Loading") static ElxValidOrNotValid LoadTangibleBlueprintAsset( - TSubclassOf &Result, - const UObject *Context, const FString &Name, bool ErrorIfNotFound = false); + TSubclassOf &Result, const UObject *Context, const FString &Name); // Get a widget blueprint by name. // UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context", ExpandEnumAsExecs="ReturnValue"), Category = "Luprex|Asset Loading") static ElxValidOrNotValid LoadUserWidgetAsset( - TSubclassOf &Result, - const UObject *Context, const FString &Name, bool ErrorIfNotFound = false); + TSubclassOf &Result, const UObject *Context, const FString &Name); // Get a look-at widget blueprint by name. // UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context", ExpandEnumAsExecs="ReturnValue"), Category = "Luprex|Asset Loading") static ElxValidOrNotValid LoadLuaWidgetAsset( - TSubclassOf &Result, - const UObject *Context, const FString &Name, bool ErrorIfNotFound = false); + TSubclassOf &Result, const UObject *Context, const FString &Name); }; diff --git a/Source/Integration/ConsoleOutput.h b/Source/Integration/ConsoleOutput.h index fe984b29..a89b6706 100644 --- a/Source/Integration/ConsoleOutput.h +++ b/Source/Integration/ConsoleOutput.h @@ -15,18 +15,12 @@ #pragma once #include "Containers/UnrealString.h" - #include "ConsoleOutput.generated.h" -<<<<<<< HEAD -////////////////////////////////////////////////////////////// -======= //////////////////////////////////////////////////////////// ->>>>>>> 9b1dd00a45a7b17c3546f8574d00e5ec78f17c75 // // UlxConsoleOutput // -<<<<<<< HEAD // When the lua code executes a print statement, the text // eventually gets passed to the GameMode blueprint: see // Docs/Print-Statement-Handling.md for more information. @@ -52,10 +46,7 @@ // If the GameMode wants to use some other framework to // implement the virtual console, that's perfectly fine. // -////////////////////////////////////////////////////////////// -======= //////////////////////////////////////////////////////////// ->>>>>>> 9b1dd00a45a7b17c3546f8574d00e5ec78f17c75 UCLASS(BlueprintType) class UlxConsoleOutput : public UObject diff --git a/Source/Integration/LuprexGameModeBase.h b/Source/Integration/LuprexGameModeBase.h index 9375cc4f..db7dfd80 100644 --- a/Source/Integration/LuprexGameModeBase.h +++ b/Source/Integration/LuprexGameModeBase.h @@ -3,6 +3,7 @@ #pragma once #include "CoreMinimal.h" +#include "Engine/HitResult.h" #include "GameFramework/GameModeBase.h" #include "lpx-enginewrapper.hpp" #include "StringDecoder.h" diff --git a/luprex/lua/login.lua b/luprex/lua/login.lua index dc0c28c7..8a0f3216 100644 --- a/luprex/lua/login.lua +++ b/luprex/lua/login.lua @@ -10,7 +10,7 @@ function login.init() global.set("nextplayer", player + 1) dprint("login.init initializing player ", player) actor.player = player - tangible.animinit{tan=actor, anim={bp="character", plane="earth", xyz={player * 100, 0, 90}}} + tangible.animinit{tan=actor, anim={bp="character", mesh="manny", plane="earth", xyz={player * 100, 0, 90}}} end -- This gets called on the admin user. You can call login.init in here if you want.