Lots of work on several unrelated things.
This commit is contained in:
BIN
Content/Luprex/lxGameMode.uasset
LFS
BIN
Content/Luprex/lxGameMode.uasset
LFS
Binary file not shown.
BIN
Content/TanActor.uasset
LFS
BIN
Content/TanActor.uasset
LFS
Binary file not shown.
BIN
Content/Tangibles/TanCharacter.uasset
LFS
Normal file
BIN
Content/Tangibles/TanCharacter.uasset
LFS
Normal file
Binary file not shown.
BIN
Content/Tangibles/TanStaticMesh.uasset
LFS
Normal file
BIN
Content/Tangibles/TanStaticMesh.uasset
LFS
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
#include "BlueprintErrors.h"
|
#include "BlueprintErrors.h"
|
||||||
|
#include "StringDecoder.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"
|
||||||
@@ -209,6 +210,15 @@ FFormatArgumentData UlxFormatDataLibrary::FormatArgumentDataTransform(const FTra
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FFormatArgumentData UlxFormatDataLibrary::FormatArgumentDataLuaValues(const UlxLuaValues *Value, const FString &Name)
|
||||||
|
{
|
||||||
|
FFormatArgumentData Result;
|
||||||
|
Result.ArgumentValueType = EFormatArgumentType::Text;
|
||||||
|
Result.ArgumentName = Name;
|
||||||
|
Result.ArgumentValue = FText::FromString(Value->DebugString());
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
FFormatArgumentData UlxBlueprintErrorLibrary::FormatArgumentDataBlank(const FString &Name)
|
FFormatArgumentData UlxBlueprintErrorLibrary::FormatArgumentDataBlank(const FString &Name)
|
||||||
{
|
{
|
||||||
FFormatArgumentData Result;
|
FFormatArgumentData Result;
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "BlueprintErrors.generated.h"
|
#include "BlueprintErrors.generated.h"
|
||||||
|
|
||||||
|
class UlxLuaValues;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* enum class ElxLogVerbosity, below, contains all the same error severity levels
|
* enum class ElxLogVerbosity, below, contains all the same error severity levels
|
||||||
* as ELogVerbosity, but in a form that the blueprint editor can manipulate.
|
* as ELogVerbosity, but in a form that the blueprint editor can manipulate.
|
||||||
@@ -213,6 +215,9 @@ public:
|
|||||||
|
|
||||||
UFUNCTION(BlueprintPure, meta = (BlueprintInternalUseOnly = "true"), Category = "Luprex|Utility")
|
UFUNCTION(BlueprintPure, meta = (BlueprintInternalUseOnly = "true"), Category = "Luprex|Utility")
|
||||||
static FFormatArgumentData FormatArgumentDataTransform(const FTransform &Value, const FString &Name);
|
static FFormatArgumentData FormatArgumentDataTransform(const FTransform &Value, const FString &Name);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, meta = (BlueprintInternalUseOnly = "true"), Category = "Luprex|Utility")
|
||||||
|
static FFormatArgumentData FormatArgumentDataLuaValues(const UlxLuaValues *Value, const FString &Name);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Debug Blueprint Errors output device.
|
/* Debug Blueprint Errors output device.
|
||||||
|
|||||||
65
Source/Integration/ConsoleOutput.cpp
Normal file
65
Source/Integration/ConsoleOutput.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include "ConsoleOutput.h"
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ConsoleOutput
|
||||||
|
//
|
||||||
|
// Storing the text that goes in the unreal console.
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
void FlxConsoleOutput::Truncate() {
|
||||||
|
int lines = 50;
|
||||||
|
int csize = Content.Len();
|
||||||
|
int total = 0;
|
||||||
|
for (int i = csize - 1; i >= 0; i--) {
|
||||||
|
if (Content[i] == '\n') {
|
||||||
|
total += 1;
|
||||||
|
if (total == lines) {
|
||||||
|
Content = Content.RightChop(i + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlxConsoleOutput::MaybeAppendNewline() {
|
||||||
|
int csize = Content.Len();
|
||||||
|
if ((csize > 0) && (Content[csize - 1] != '\n')) {
|
||||||
|
Content += TEXT("\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlxConsoleOutput::MaybeAppendText(const FString& text) {
|
||||||
|
if (!text.IsEmpty()) {
|
||||||
|
Content += text;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlxConsoleOutput::Append(const FString& text) {
|
||||||
|
bool modified = MaybeAppendText(text);
|
||||||
|
if (modified) {
|
||||||
|
Dirty = true;
|
||||||
|
Truncate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlxConsoleOutput::AppendLine(const FString& text) {
|
||||||
|
bool modified = MaybeAppendNewline();
|
||||||
|
modified |= MaybeAppendText(text);
|
||||||
|
modified |= MaybeAppendNewline();
|
||||||
|
if (modified) {
|
||||||
|
Dirty = true;
|
||||||
|
Truncate();
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Source/Integration/ConsoleOutput.h
Normal file
52
Source/Integration/ConsoleOutput.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ConsoleOutput
|
||||||
|
//
|
||||||
|
// This class stores the text that's in the unreal console.
|
||||||
|
// It stores it as one great big string, which contains
|
||||||
|
// newlines to denote line breaks.
|
||||||
|
//
|
||||||
|
// This class also contains a 'dirty' bit. Each time somebody
|
||||||
|
// appends a line of text to the console, the dirty bit is
|
||||||
|
// automatically set. The bit can be checked using 'IsDirty'
|
||||||
|
// and cleared using 'ClearDirty'. This makes it so that
|
||||||
|
// you don't have to update the unreal widget unless the
|
||||||
|
// text has actually changed.
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FlxConsoleOutput {
|
||||||
|
private:
|
||||||
|
FString Content;
|
||||||
|
bool Dirty;
|
||||||
|
|
||||||
|
// Truncate the console to a reasonable number of
|
||||||
|
// lines. The length is hardwired.
|
||||||
|
void Truncate();
|
||||||
|
|
||||||
|
// Add a newline if there isn't one. Returns true if it changed anything.
|
||||||
|
bool MaybeAppendNewline();
|
||||||
|
|
||||||
|
// Append text. Returns true if it changed anything.
|
||||||
|
bool MaybeAppendText(const FString& text);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Append a line of text to the console.
|
||||||
|
void Append(const FString& text);
|
||||||
|
|
||||||
|
// Append a line of text to the console on a line by itself.
|
||||||
|
void AppendLine(const FString& text);
|
||||||
|
|
||||||
|
// Get the console text as a string.
|
||||||
|
const FString& Get() const { return Content; }
|
||||||
|
|
||||||
|
// Return if the dirty flag is set.
|
||||||
|
bool IsDirty() const { return Dirty; }
|
||||||
|
|
||||||
|
// Clear the dirty flag.
|
||||||
|
void ClearDirty() { Dirty = false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
#include "DebugPrint.h"
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
|
|
||||||
using DPrintCallback = DebugPrintControl::DPrintCallback;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// DPrintState
|
|
||||||
//
|
|
||||||
// The global state of the DPrint routine. There is only
|
|
||||||
// ever one of these, and it is owned by DPrintAccess below.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct DPrintState {
|
|
||||||
// True if buffering is enabled.
|
|
||||||
bool Collect;
|
|
||||||
|
|
||||||
// The array of buffered messages.
|
|
||||||
TArray<FString> Messages;
|
|
||||||
|
|
||||||
// The array of callback functions.
|
|
||||||
TArray<DPrintCallback> Callbacks;
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// DPrintAccess
|
|
||||||
//
|
|
||||||
// This class grants you safe access to the global state
|
|
||||||
// of the DPrint routine. Constructing an object of
|
|
||||||
// class DPrintAccess will lock the global mutex and make
|
|
||||||
// sure that the DPrintState is initialized. Then it will
|
|
||||||
// give you unrestricted access to the DPrintState through
|
|
||||||
// operator right arrow.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class DPrintAccess {
|
|
||||||
private:
|
|
||||||
// The Mutex that protects the global state.
|
|
||||||
static FCriticalSection Mutex;
|
|
||||||
|
|
||||||
// The Global State. A pointer, to avoid static init issues.
|
|
||||||
static DPrintState* State;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Constructor. Locks mutex and initializes state if necessary.
|
|
||||||
DPrintAccess() {
|
|
||||||
Mutex.Lock();
|
|
||||||
if (State == nullptr) {
|
|
||||||
State = new DPrintState;
|
|
||||||
State->Collect = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor. Releases mutex.
|
|
||||||
~DPrintAccess() {
|
|
||||||
Mutex.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Access the DPrintState.
|
|
||||||
DPrintState* operator ->() {
|
|
||||||
return State;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
FCriticalSection DPrintAccess::Mutex;
|
|
||||||
DPrintState* DPrintAccess::State;
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Namespace DebugPrint.
|
|
||||||
//
|
|
||||||
// This contains all the various versions of the DPrint routine.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
namespace DebugPrint {
|
|
||||||
|
|
||||||
// DPrint. Invoke all the callbacks, and store the message.
|
|
||||||
void DPrint(const FString& fs) {
|
|
||||||
DPrintAccess state;
|
|
||||||
for (DPrintCallback cb : state->Callbacks) {
|
|
||||||
cb(fs);
|
|
||||||
}
|
|
||||||
if (state->Collect) {
|
|
||||||
state->Messages.Emplace(fs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alternative interface to the dispatcher.
|
|
||||||
void DPrint(const char* msg) {
|
|
||||||
DPrint(FString(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alternative interface to the dispatcher.
|
|
||||||
void DPrint(const char* msg, size_t len) {
|
|
||||||
DPrint(FString(len, (const UTF8CHAR*)msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace DebugPrint
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Namespace DebugPrintControl.
|
|
||||||
//
|
|
||||||
// Configuration and control for the DPrint routine.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
namespace DebugPrintControl {
|
|
||||||
|
|
||||||
// Register a callback. Check for duplication.
|
|
||||||
void RegisterCallback(DPrintCallback cb) {
|
|
||||||
DPrintAccess state;
|
|
||||||
for (DPrintCallback old : state->Callbacks) {
|
|
||||||
if (cb == old) return;
|
|
||||||
}
|
|
||||||
state->Callbacks.Add(cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the collection bit in the global state.
|
|
||||||
void EnableCollection() {
|
|
||||||
DPrintAccess state;
|
|
||||||
state->Collect = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the array of collected messages, if any.
|
|
||||||
TArray<FString> GetStored() {
|
|
||||||
DPrintAccess state;
|
|
||||||
TArray<FString> result = std::move(state->Messages);
|
|
||||||
state->Messages.Empty();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// ConsoleOutput
|
|
||||||
//
|
|
||||||
// Storing the text that goes in the unreal console.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
void FlxConsoleOutput::Truncate() {
|
|
||||||
int lines = 50;
|
|
||||||
int csize = Content.Len();
|
|
||||||
int total = 0;
|
|
||||||
for (int i = csize - 1; i >= 0; i--) {
|
|
||||||
if (Content[i] == '\n') {
|
|
||||||
total += 1;
|
|
||||||
if (total == lines) {
|
|
||||||
Content = Content.RightChop(i + 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FlxConsoleOutput::MaybeAppendNewline() {
|
|
||||||
int csize = Content.Len();
|
|
||||||
if ((csize > 0) && (Content[csize - 1] != '\n')) {
|
|
||||||
Content += TEXT("\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FlxConsoleOutput::MaybeAppendText(const FString& text) {
|
|
||||||
if (!text.IsEmpty()) {
|
|
||||||
Content += text;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlxConsoleOutput::Append(const FString& text) {
|
|
||||||
bool modified = MaybeAppendText(text);
|
|
||||||
if (modified) {
|
|
||||||
Dirty = true;
|
|
||||||
Truncate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlxConsoleOutput::AppendLine(const FString& text) {
|
|
||||||
bool modified = MaybeAppendNewline();
|
|
||||||
modified |= MaybeAppendText(text);
|
|
||||||
modified |= MaybeAppendNewline();
|
|
||||||
if (modified) {
|
|
||||||
Dirty = true;
|
|
||||||
Truncate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Namespace DebugPrint
|
|
||||||
//
|
|
||||||
// This namespace contains the function "DPrint",
|
|
||||||
// which is short for debugging print. This
|
|
||||||
// is what you should use if you want to print
|
|
||||||
// a debugging message.
|
|
||||||
//
|
|
||||||
// Messages printed using "DPrint" will
|
|
||||||
// be routed to several destinations. These
|
|
||||||
// might include a logfile, the unreal console,
|
|
||||||
// and the visual studio debugging log.
|
|
||||||
//
|
|
||||||
// In order for "DPrint" to work, you have to
|
|
||||||
// configure them once, at program initialization
|
|
||||||
// time. This is done using the functions in
|
|
||||||
// namespace DebugPrintConfig, below.
|
|
||||||
//
|
|
||||||
// We promise that namespace DebugPrint will
|
|
||||||
// only ever contain one function, 'DPrint.'
|
|
||||||
// that way, it's safe for you to put
|
|
||||||
// 'using namespace DebugPrint' in your code.
|
|
||||||
//
|
|
||||||
// All DPrint-related functionality is
|
|
||||||
// thread-safe. A single 'DPrint' is meant to
|
|
||||||
// be output atomically.
|
|
||||||
//
|
|
||||||
// It is fine for the content of the DPrint
|
|
||||||
// string to contain newlines.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
namespace DebugPrint {
|
|
||||||
// Print text into the debug log.
|
|
||||||
void DPrint(const FString& fs);
|
|
||||||
|
|
||||||
// Print text into the debug log.
|
|
||||||
void DPrint(const char* msg);
|
|
||||||
|
|
||||||
// Print text into the debug log.
|
|
||||||
void DPrint(const char* msg, size_t len);
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// namespace DebugPrintControl
|
|
||||||
//
|
|
||||||
// This namespace contains the functions
|
|
||||||
// necessary to initialize "DPrint", and
|
|
||||||
// route its output to several destinations.
|
|
||||||
//
|
|
||||||
// "DPrint" is a callback-based design.
|
|
||||||
// Initialization might consist of: register a
|
|
||||||
// callback that sends a string to a logfile,
|
|
||||||
// register another callback that sends a string
|
|
||||||
// to visual studio's debug console, and register
|
|
||||||
// a third one that sends a string to the
|
|
||||||
// unreal console. Each time somebody calls
|
|
||||||
// 'DPrint', all three callbacks will get invoked.
|
|
||||||
//
|
|
||||||
// There is also a 'collect' option where you
|
|
||||||
// can ask "DPrint" to save the messages in a
|
|
||||||
// buffer, which you can then collect at
|
|
||||||
// your leisure. You can use buffering and
|
|
||||||
// callbacks at the same time. Note that
|
|
||||||
// buffering is inherently less than ideal for
|
|
||||||
// messages that warn of imminent program aborts.
|
|
||||||
// So it is recommended that you use at least one
|
|
||||||
// callback that sends its output without delay.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
namespace DebugPrintControl {
|
|
||||||
// The prototype for a callback function.
|
|
||||||
//
|
|
||||||
using DPrintCallback = void (*)(const FString& fs);
|
|
||||||
|
|
||||||
// Register a callback.
|
|
||||||
//
|
|
||||||
// Registering a callback that is already
|
|
||||||
// registered is a no-op.
|
|
||||||
//
|
|
||||||
void RegisterCallback(DPrintCallback f);
|
|
||||||
|
|
||||||
// Enable collection in a buffer.
|
|
||||||
//
|
|
||||||
// If collection is already enabled, this is a no-op.
|
|
||||||
//
|
|
||||||
void EnableCollection();
|
|
||||||
|
|
||||||
// Collect all the stored messages, and clear the storage.
|
|
||||||
//
|
|
||||||
TArray<FString> GetStored();
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// ConsoleOutput
|
|
||||||
//
|
|
||||||
// This class stores the text that's in the unreal console.
|
|
||||||
// It stores it as one great big string, which contains
|
|
||||||
// newlines to denote line breaks.
|
|
||||||
//
|
|
||||||
// This class also contains a 'dirty' bit. Each time somebody
|
|
||||||
// appends a line of text to the console, the dirty bit is
|
|
||||||
// automatically set. The bit can be checked using 'IsDirty'
|
|
||||||
// and cleared using 'ClearDirty'. This makes it so that
|
|
||||||
// you don't have to update the unreal widget unless the
|
|
||||||
// text has actually changed.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class FlxConsoleOutput {
|
|
||||||
private:
|
|
||||||
FString Content;
|
|
||||||
bool Dirty;
|
|
||||||
|
|
||||||
// Truncate the console to a reasonable number of
|
|
||||||
// lines. The length is hardwired.
|
|
||||||
void Truncate();
|
|
||||||
|
|
||||||
// Add a newline if there isn't one. Returns true if it changed anything.
|
|
||||||
bool MaybeAppendNewline();
|
|
||||||
|
|
||||||
// Append text. Returns true if it changed anything.
|
|
||||||
bool MaybeAppendText(const FString& text);
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Append a line of text to the console.
|
|
||||||
void Append(const FString& text);
|
|
||||||
|
|
||||||
// Append a line of text to the console on a line by itself.
|
|
||||||
void AppendLine(const FString& text);
|
|
||||||
|
|
||||||
// Get the console text as a string.
|
|
||||||
const FString& Get() const { return Content; }
|
|
||||||
|
|
||||||
// Return if the dirty flag is set.
|
|
||||||
bool IsDirty() const { return Dirty; }
|
|
||||||
|
|
||||||
// Clear the dirty flag.
|
|
||||||
void ClearDirty() { Dirty = false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,25 +1,32 @@
|
|||||||
|
|
||||||
#include "LockedWrapper.h"
|
#include "LockedWrapper.h"
|
||||||
#include "DebugPrint.h"
|
#include "LuprexGameModeBase.h"
|
||||||
#include "lpx-drvutil.hpp"
|
#include "lpx-drvutil.hpp"
|
||||||
#include "lpx-paths.hpp"
|
#include "lpx-paths.hpp"
|
||||||
|
|
||||||
using namespace CommonTypes;
|
using namespace CommonTypes;
|
||||||
|
|
||||||
|
|
||||||
|
void FlxLockedWrapper::DPrintHook(const char *Msg, size_t Size)
|
||||||
|
{
|
||||||
|
FString FMessage(Size, (const UTF8CHAR *)Msg);
|
||||||
|
UE_LOG(LogLuprex, Error, TEXT("%s"), *FMessage);
|
||||||
|
}
|
||||||
|
|
||||||
void FlxLockedWrapper::InitWrapper() {
|
void FlxLockedWrapper::InitWrapper() {
|
||||||
if (Lockable.Wrapper.play_initialize != nullptr) {
|
if (Lockable.Wrapper.play_initialize != nullptr) {
|
||||||
// Already initialized.
|
// Already initialized.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FString dll((const UTF8CHAR*)LUPREX_DLL_PATH);
|
FString dll((const UTF8CHAR*)LUPREX_DLL_PATH);
|
||||||
DebugPrint::DPrint(dll);
|
UE_LOG(LogLuprex, Verbose, TEXT("Luprex DLL Path: %s"), *dll);
|
||||||
void* DLL = FPlatformProcess::GetDllHandle(*dll);
|
void* DLL = FPlatformProcess::GetDllHandle(*dll);
|
||||||
if (DLL != nullptr) {
|
if (DLL != nullptr) {
|
||||||
using InitFn = void (*)(EngineWrapper*);
|
using InitFn = void (*)(EngineWrapper*);
|
||||||
InitFn init = (InitFn)FPlatformProcess::GetDllExport(DLL, TEXT("init_engine_wrapper"));
|
InitFn init = (InitFn)FPlatformProcess::GetDllExport(DLL, TEXT("init_engine_wrapper"));
|
||||||
if (init != nullptr) {
|
if (init != nullptr) {
|
||||||
init(&Lockable.Wrapper);
|
init(&Lockable.Wrapper);
|
||||||
Lockable.Wrapper.hook_dprint(DebugPrint::DPrint);
|
Lockable.Wrapper.hook_dprint(DPrintHook);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,16 +34,9 @@ void FlxLockedWrapper::InitWrapper() {
|
|||||||
FString FlxLockedWrapper::FetchStdout() {
|
FString FlxLockedWrapper::FetchStdout() {
|
||||||
uint32_t ndata; const char* data;
|
uint32_t ndata; const char* data;
|
||||||
Lockable.Wrapper.get_outgoing(Get(), 0, &ndata, &data);
|
Lockable.Wrapper.get_outgoing(Get(), 0, &ndata, &data);
|
||||||
|
FString result(ndata, (const UTF8CHAR *)data);
|
||||||
if (ndata == 0) {
|
Lockable.Wrapper.play_sent_outgoing(Get(), 0, ndata);
|
||||||
return FString();
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view src(data, ndata);
|
|
||||||
int consumed;
|
|
||||||
std::u16string cps = drvutil::utf8_to_ucs2(src, &consumed);
|
|
||||||
Lockable.Wrapper.play_sent_outgoing(Get(), 0, consumed);
|
|
||||||
return FString(cps.size(), (const UCS2CHAR*)(&cps[0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 FlxLockedWrapper::GetActor() {
|
int64 FlxLockedWrapper::GetActor() {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "lpx-enginewrapper.hpp"
|
#include "lpx-enginewrapper.hpp"
|
||||||
#include "CommonTypes.h"
|
#include "CommonTypes.h"
|
||||||
|
|
||||||
|
|
||||||
// Class FlxLockableWrapper
|
// Class FlxLockableWrapper
|
||||||
//
|
//
|
||||||
// Contains the EngineWrapper and a Mutex to lock it.
|
// Contains the EngineWrapper and a Mutex to lock it.
|
||||||
@@ -31,11 +32,17 @@ class FlxLockedWrapper {
|
|||||||
private:
|
private:
|
||||||
FlxLockableWrapper& Lockable;
|
FlxLockableWrapper& Lockable;
|
||||||
|
|
||||||
|
// This function is called by luprex to output debugging
|
||||||
|
// messages. It is a thin wrapper around UE_LOG.
|
||||||
|
//
|
||||||
|
static void DPrintHook(const char *Msg, size_t Size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Import these types into our Namespace.
|
// Import these types into our Namespace.
|
||||||
using IdArray = CommonTypes::IdArray;
|
using IdArray = CommonTypes::IdArray;
|
||||||
using IdView = CommonTypes::IdView;
|
using IdView = CommonTypes::IdView;
|
||||||
using StringViewVec = CommonTypes::StringViewVec;
|
using StringViewVec = CommonTypes::StringViewVec;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// The constructor of the FlxLockedWrapper claims the mutex.
|
// The constructor of the FlxLockedWrapper claims the mutex.
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
#include "LuaCall.h"
|
#include "LuaCall.h"
|
||||||
#include "LuprexGameModeBase.h"
|
#include "LuprexGameModeBase.h"
|
||||||
|
#include "StringDecoder.h"
|
||||||
|
|
||||||
#include "EdGraphSchema_K2.h"
|
#include "EdGraphSchema_K2.h"
|
||||||
|
|
||||||
static void FatalBlueprintError(const TCHAR *message) {
|
static void FatalBlueprintError(const TCHAR *message) {
|
||||||
@@ -203,7 +205,8 @@ FString UlxLuaCallLibrary::AllFunctionsWithPrefix(const TCHAR *Prefix)
|
|||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, const FString &fname) {
|
void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, const FString &fname)
|
||||||
|
{
|
||||||
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
mode->LuaCallBegin();
|
mode->LuaCallBegin();
|
||||||
@@ -212,7 +215,8 @@ void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallInvoke(UObject *context, AActor *place) {
|
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);
|
CheckNotEmpty(sb);
|
||||||
@@ -220,31 +224,26 @@ void UlxLuaCallLibrary::LuaCallInvoke(UObject *context, AActor *place) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallProbe(UObject *context, AActor *place) {
|
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);
|
CheckNotEmpty(sb);
|
||||||
mode->LuaCallEnd(InvocationKind::LUA_PROBE, place);
|
mode->LuaCallEnd(InvocationKind::LUA_PROBE, place);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UlxLuaValues *UlxLuaCallLibrary::LuaCallGetRest(UObject *context)
|
||||||
|
{
|
||||||
// ELpxSimpleDynamicTag UlxLuaCallLibrary::LuaCallNextResultType(UObject *context) {
|
ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
||||||
// ALuprexGameModeBase *mode = ALuprexGameModeBase::FromContext(context);
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
// FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
UlxLuaValues *Values = NewObject<UlxLuaValues>(context);
|
||||||
// if (sb.empty()) return ELpxSimpleDynamicTag::None;
|
if (!Values->Initialize(sb.view()))
|
||||||
// int64_t total_reads = sb.total_reads();
|
{
|
||||||
// SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
UE_LOG(LogBlueprint, Error, TEXT("Lua call returned corrupt data"));
|
||||||
// sb.unread_to(total_reads);
|
return nullptr;
|
||||||
// switch (tag) {
|
}
|
||||||
// case SimpleDynamicTag::STRING: return ELpxSimpleDynamicTag::String;
|
return Values;
|
||||||
// case SimpleDynamicTag::TOKEN: return ELpxSimpleDynamicTag::Name;
|
}
|
||||||
// case SimpleDynamicTag::NUMBER: return ELpxSimpleDynamicTag::Float;
|
|
||||||
// case SimpleDynamicTag::VECTOR: return ELpxSimpleDynamicTag::Vector;
|
|
||||||
// case SimpleDynamicTag::BOOLEAN: return ELpxSimpleDynamicTag::Boolean;
|
|
||||||
// default: return ELpxSimpleDynamicTag::None;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "EdGraph/EdGraphPin.h"
|
#include "EdGraph/EdGraphPin.h"
|
||||||
|
|
||||||
#include "LuaCall.generated.h"
|
#include "LuaCall.generated.h"
|
||||||
|
|
||||||
|
class UlxLuaValues;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@@ -119,6 +121,9 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context", BlueprintInternalUseOnly = "true"), Category = "Luprex|Call Lua Function")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context", BlueprintInternalUseOnly = "true"), Category = "Luprex|Call Lua Function")
|
||||||
static void LuaCallProbe(UObject *context, AActor *Place);
|
static void LuaCallProbe(UObject *context, AActor *Place);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context", BlueprintInternalUseOnly = "true"), Category = "Luprex|Call Lua Function")
|
||||||
|
static UlxLuaValues *LuaCallGetRest(UObject *context);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Functions that pack arguments into the call buffer.
|
// Functions that pack arguments into the call buffer.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "LuaCallNode.h"
|
#include "LuaCallNode.h"
|
||||||
|
#include "StringDecoder.h"
|
||||||
|
|
||||||
#include "BlueprintActionDatabaseRegistrar.h"
|
#include "BlueprintActionDatabaseRegistrar.h"
|
||||||
#include "BlueprintNodeSpawner.h"
|
#include "BlueprintNodeSpawner.h"
|
||||||
@@ -40,59 +41,41 @@
|
|||||||
|
|
||||||
#define LOCTEXT_NAMESPACE "LuaCall"
|
#define LOCTEXT_NAMESPACE "LuaCall"
|
||||||
|
|
||||||
|
#define LuaCallLibraryFunction(name) (UlxLuaCallLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxLuaCallLibrary, name)))
|
||||||
|
|
||||||
// All argument pins will have internal Names that start with "A:"
|
// All argument pins will have internal Names that start with "A:"
|
||||||
|
|
||||||
static bool IsArgumentPin(const UEdGraphPin *Pin) {
|
const FName UK2Node_LuaCall::FunctionPinName(TEXT("Lua Function Prototype"));
|
||||||
|
const FName UK2Node_LuaCall::InvokeOrProbePinName(TEXT("Invoke or Probe"));
|
||||||
|
const FName UK2Node_LuaCall::PlacePinName(TEXT("Place Tangible"));
|
||||||
|
const FName UK2Node_LuaCall::ExtraResultsPinName(TEXT("Extra Results"));
|
||||||
|
|
||||||
|
bool UK2Node_LuaCall::IsPrefix(const UEdGraphPin *Pin, char Prefix)
|
||||||
|
{
|
||||||
TCHAR pname[FName::StringBufferSize];
|
TCHAR pname[FName::StringBufferSize];
|
||||||
Pin->PinName.ToString(pname);
|
Pin->PinName.ToString(pname);
|
||||||
return pname[0] == 'A' && pname[1] == ':';
|
return pname[0] == Prefix && pname[1] == ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
static FName ArgumentNameAddPrefix(const FString &name) {
|
FName UK2Node_LuaCall::AddPrefix(const FString &Name, char Prefix)
|
||||||
FString Prefixed = FString("A:") + name;
|
{
|
||||||
|
TCHAR PrefixChars[3];
|
||||||
|
PrefixChars[0] = Prefix;
|
||||||
|
PrefixChars[1] = ':';
|
||||||
|
PrefixChars[2] = 0;
|
||||||
|
FString Prefixed = PrefixChars + Name;
|
||||||
return FName(*Prefixed);
|
return FName(*Prefixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FString ArgumentNameRemovePrefix(const FName &name) {
|
FString UK2Node_LuaCall::RemovePrefix(FName Name, char Prefix)
|
||||||
return name.ToString().Mid(2, FName::StringBufferSize);
|
{
|
||||||
}
|
|
||||||
|
|
||||||
// All return value pins will have internal Names that start with "R:"
|
|
||||||
|
|
||||||
static bool IsReturnValuePin(const UEdGraphPin *Pin) {
|
|
||||||
TCHAR pname[FName::StringBufferSize];
|
TCHAR pname[FName::StringBufferSize];
|
||||||
Pin->PinName.ToString(pname);
|
Name.ToString(pname);
|
||||||
return pname[0] == 'R' && pname[1] == ':';
|
check(pname[0] == Prefix);
|
||||||
|
check(pname[1] == ':');
|
||||||
|
return FString(pname + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FName ReturnValueNameAddPrefix(const FString &name) {
|
|
||||||
FString Prefixed = FString("R:") + name;
|
|
||||||
return FName(*Prefixed);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FString ReturnValueNameRemovePrefix(const FName &name) {
|
|
||||||
return name.ToString().Mid(2, FName::StringBufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Builtin pins will have names with no prefixes.
|
|
||||||
|
|
||||||
static const FName FunctionPinName(TEXT("Lua Function Prototype"));
|
|
||||||
static bool IsFunctionPin(const UEdGraphPin *Pin) {
|
|
||||||
return (Pin->PinName == FunctionPinName);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const FName InvokeOrProbePinName(TEXT("Invoke or Probe"));
|
|
||||||
static bool IsInvokeOrProbePin(const UEdGraphPin *Pin) {
|
|
||||||
return (Pin->PinName == InvokeOrProbePinName);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const FName PlacePinName(TEXT("Place Tangible"));
|
|
||||||
static bool IsPlacePin(const UEdGraphPin *Pin) {
|
|
||||||
return (Pin->PinName == PlacePinName);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LuaCallLibraryFunction(name) (UlxLuaCallLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxLuaCallLibrary, name)))
|
|
||||||
|
|
||||||
static FEdGraphPinType GetPinType(const FProperty *Property)
|
static FEdGraphPinType GetPinType(const FProperty *Property)
|
||||||
{
|
{
|
||||||
FEdGraphPinType PinType;
|
FEdGraphPinType PinType;
|
||||||
@@ -107,7 +90,6 @@ static FEdGraphPinType GetPinType(const FProperty *Property)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
UK2Node_LuaCall::UK2Node_LuaCall(const FObjectInitializer& ObjectInitializer)
|
UK2Node_LuaCall::UK2Node_LuaCall(const FObjectInitializer& ObjectInitializer)
|
||||||
: Super(ObjectInitializer)
|
: Super(ObjectInitializer)
|
||||||
{
|
{
|
||||||
@@ -154,29 +136,6 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
|||||||
LuaFunctionPrototype = TEXT("class.func(int arg1, int arg2) : int ret1, int ret2");
|
LuaFunctionPrototype = TEXT("class.func(int arg1, int arg2) : int ret1, int ret2");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FindPin(UEdGraphSchema_K2::PN_Execute) == nullptr) {
|
|
||||||
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FindPin(UEdGraphSchema_K2::PN_Then) == nullptr) {
|
|
||||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FindPin(FunctionPinName, EGPD_Input) == nullptr) {
|
|
||||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_String, FunctionPinName);
|
|
||||||
P->DefaultValue = LuaFunctionPrototype;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FindPin(InvokeOrProbePinName, EGPD_Input) == nullptr) {
|
|
||||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Byte, StaticEnum<ElxInvokeOrProbe>(), InvokeOrProbePinName);
|
|
||||||
P->DefaultValue = TEXT("Probe");
|
|
||||||
P->AutogeneratedDefaultValue = P->DefaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FindPin(PlacePinName, EGPD_Input) == nullptr) {
|
|
||||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, AActor::StaticClass(), PlacePinName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the lua function prototype.
|
// Parse the lua function prototype.
|
||||||
FlxParsedProto ParsedProto(LuaFunctionPrototype);
|
FlxParsedProto ParsedProto(LuaFunctionPrototype);
|
||||||
if (!ParsedProto.ErrorMessage.IsEmpty())
|
if (!ParsedProto.ErrorMessage.IsEmpty())
|
||||||
@@ -186,26 +145,60 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
|||||||
ErrorMsg = FString::Printf(TEXT("Syntax error in lua function prototype: %s"), *ParsedProto.ErrorMessage);
|
ErrorMsg = FString::Printf(TEXT("Syntax error in lua function prototype: %s"), *ParsedProto.ErrorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer all Existing argument and return value pins to the Old Pins Maps.
|
// Transfer all pins to the old pins map and clear the pin list.
|
||||||
TMap<FName, UEdGraphPin *> OldArgumentPins;
|
TMap<FName, UEdGraphPin *> OldPins;
|
||||||
TMap<FName, UEdGraphPin *> OldReturnValuePins;
|
|
||||||
for (auto It = Pins.CreateIterator(); It; ++It)
|
for (auto It = Pins.CreateIterator(); It; ++It)
|
||||||
{
|
{
|
||||||
UEdGraphPin* CheckPin = *It;
|
UEdGraphPin* CheckPin = *It;
|
||||||
if (IsArgumentPin(CheckPin)) {
|
OldPins.Add(CheckPin->PinName, CheckPin);
|
||||||
OldArgumentPins.Add(CheckPin->PinName, CheckPin);
|
}
|
||||||
It.RemoveCurrent();
|
Pins.Empty();
|
||||||
}
|
|
||||||
if (IsReturnValuePin(CheckPin)) {
|
// KeepPin is a function that moves a pin from the old pins
|
||||||
OldReturnValuePins.Add(CheckPin->PinName, CheckPin);
|
// map back onto the pins list.
|
||||||
It.RemoveCurrent();
|
auto KeepPin = [&](FName Name, FEdGraphPinType Type = FEdGraphPinType()) -> bool
|
||||||
|
{
|
||||||
|
UEdGraphPin **OldPin = OldPins.Find(Name);
|
||||||
|
if ((OldPin != nullptr) && (((*OldPin)->PinType == Type) || (Type.PinCategory == FName())))
|
||||||
|
{
|
||||||
|
Pins.Emplace(*OldPin);
|
||||||
|
OldPins.Remove(Name);
|
||||||
}
|
}
|
||||||
|
return OldPin != nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!KeepPin(UEdGraphSchema_K2::PN_Execute))
|
||||||
|
{
|
||||||
|
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!KeepPin(UEdGraphSchema_K2::PN_Then))
|
||||||
|
{
|
||||||
|
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!KeepPin(FunctionPinName))
|
||||||
|
{
|
||||||
|
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_String, FunctionPinName);
|
||||||
|
P->DefaultValue = LuaFunctionPrototype;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!KeepPin(InvokeOrProbePinName))
|
||||||
|
{
|
||||||
|
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Byte, StaticEnum<ElxInvokeOrProbe>(), InvokeOrProbePinName);
|
||||||
|
P->DefaultValue = TEXT("Probe");
|
||||||
|
P->AutogeneratedDefaultValue = P->DefaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!KeepPin(PlacePinName))
|
||||||
|
{
|
||||||
|
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, AActor::StaticClass(), PlacePinName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Argument pins in the correct order, reusing old pins where possible.
|
// Create Argument pins in the correct order, reusing old pins where possible.
|
||||||
for (const FlxParsedProto::Pin & Pin : ParsedProto.Arguments)
|
for (const FlxParsedProto::Pin & Pin : ParsedProto.Arguments)
|
||||||
{
|
{
|
||||||
FName PrefixedName = ArgumentNameAddPrefix(Pin.Name);
|
FName PrefixedName = AddPrefix(Pin.Name, 'A');
|
||||||
UFunction *Accessor = UlxLuaCallLibrary::GetArgumentPacker(Pin.Type);
|
UFunction *Accessor = UlxLuaCallLibrary::GetArgumentPacker(Pin.Type);
|
||||||
if (Accessor == nullptr) {
|
if (Accessor == nullptr) {
|
||||||
bHasCompilerMessage = true;
|
bHasCompilerMessage = true;
|
||||||
@@ -214,11 +207,8 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FEdGraphPinType PinType = GetPinType(Accessor->FindPropertyByName(TEXT("Value")));
|
FEdGraphPinType PinType = GetPinType(Accessor->FindPropertyByName(TEXT("Value")));
|
||||||
UEdGraphPin **OldPin = OldArgumentPins.Find(PrefixedName);
|
if (!KeepPin(PrefixedName, PinType))
|
||||||
if ((OldPin != nullptr) && ((*OldPin)->PinType == PinType)) {
|
{
|
||||||
Pins.Emplace(*OldPin);
|
|
||||||
OldArgumentPins.Remove(PrefixedName);
|
|
||||||
} else {
|
|
||||||
CreatePin(EGPD_Input, PinType, PrefixedName);
|
CreatePin(EGPD_Input, PinType, PrefixedName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,7 +216,7 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
|||||||
// Create ReturnValue pins in the correct order, reusing old pins where possible.
|
// Create ReturnValue pins in the correct order, reusing old pins where possible.
|
||||||
for (const FlxParsedProto::Pin & Pin : ParsedProto.ReturnValues)
|
for (const FlxParsedProto::Pin & Pin : ParsedProto.ReturnValues)
|
||||||
{
|
{
|
||||||
FName PrefixedName = ReturnValueNameAddPrefix(Pin.Name);
|
FName PrefixedName = AddPrefix(Pin.Name, 'R');
|
||||||
UFunction *Accessor = UlxLuaCallLibrary::GetReturnValueUnpacker(Pin.Type);
|
UFunction *Accessor = UlxLuaCallLibrary::GetReturnValueUnpacker(Pin.Type);
|
||||||
if (Accessor == nullptr) {
|
if (Accessor == nullptr) {
|
||||||
bHasCompilerMessage = true;
|
bHasCompilerMessage = true;
|
||||||
@@ -235,28 +225,27 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FEdGraphPinType PinType = GetPinType(Accessor->GetReturnProperty());
|
FEdGraphPinType PinType = GetPinType(Accessor->GetReturnProperty());
|
||||||
UEdGraphPin **OldPin = OldReturnValuePins.Find(PrefixedName);
|
if (!KeepPin(PrefixedName, PinType))
|
||||||
if ((OldPin != nullptr) && ((*OldPin)->PinType == PinType)) {
|
{
|
||||||
Pins.Emplace(*OldPin);
|
|
||||||
OldReturnValuePins.Remove(PrefixedName);
|
|
||||||
} else {
|
|
||||||
CreatePin(EGPD_Output, PinType, PrefixedName);
|
CreatePin(EGPD_Output, PinType, PrefixedName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ParsedProto.ExtraReturnValues)
|
||||||
|
{
|
||||||
|
if (!KeepPin(ExtraResultsPinName))
|
||||||
|
{
|
||||||
|
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Object, UlxLuaValues::StaticClass(), ExtraResultsPinName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete any unused pins.
|
// Delete any unused pins.
|
||||||
for (auto &iter : OldArgumentPins)
|
for (auto &iter : OldPins)
|
||||||
{
|
{
|
||||||
iter.Value->Modify();
|
iter.Value->Modify();
|
||||||
iter.Value->MarkAsGarbage();
|
iter.Value->MarkAsGarbage();
|
||||||
}
|
}
|
||||||
for (auto &iter : OldReturnValuePins)
|
OldPins.Empty();
|
||||||
{
|
|
||||||
iter.Value->Modify();
|
|
||||||
iter.Value->MarkAsGarbage();
|
|
||||||
}
|
|
||||||
OldArgumentPins.Empty();
|
|
||||||
OldReturnValuePins.Empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -274,7 +263,7 @@ FText UK2Node_LuaCall::GetPinDisplayName(const UEdGraphPin* Pin) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Many pins can go unlabeled if they have default values.
|
// Many pins can go unlabeled if they have default values.
|
||||||
if (IsFunctionPin(Pin) || IsInvokeOrProbePin(Pin))
|
if ((Pin->PinName == FunctionPinName) || (Pin->PinName == InvokeOrProbePinName))
|
||||||
{
|
{
|
||||||
if (Pin->LinkedTo.Num() == 0)
|
if (Pin->LinkedTo.Num() == 0)
|
||||||
{
|
{
|
||||||
@@ -283,13 +272,15 @@ FText UK2Node_LuaCall::GetPinDisplayName(const UEdGraphPin* Pin) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For argument pins, we must strip off the Argument Pin Prefix.
|
// For argument pins, we must strip off the Argument Pin Prefix.
|
||||||
if (IsArgumentPin(Pin)) {
|
if (IsPrefix(Pin, 'A'))
|
||||||
return FText::FromString(ArgumentNameRemovePrefix(Pin->PinName));
|
{
|
||||||
|
return FText::FromString(RemovePrefix(Pin->PinName, 'A'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// For return value pins, we must strip off the Return Value Pin Prefix.
|
// For return value pins, we must strip off the Return Value Pin Prefix.
|
||||||
if (IsReturnValuePin(Pin)) {
|
if (IsPrefix(Pin, 'R'))
|
||||||
return FText::FromString(ReturnValueNameRemovePrefix(Pin->PinName));
|
{
|
||||||
|
return FText::FromString(RemovePrefix(Pin->PinName, 'R'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, just return the Pin Name the normal way.
|
// Otherwise, just return the Pin Name the normal way.
|
||||||
@@ -309,7 +300,7 @@ void UK2Node_LuaCall::PinConnectionListChanged(UEdGraphPin* Pin)
|
|||||||
|
|
||||||
void UK2Node_LuaCall::PinDefaultValueChanged(UEdGraphPin* Pin)
|
void UK2Node_LuaCall::PinDefaultValueChanged(UEdGraphPin* Pin)
|
||||||
{
|
{
|
||||||
if(IsFunctionPin(Pin))
|
if(Pin->PinName == FunctionPinName)
|
||||||
{
|
{
|
||||||
LuaFunctionPrototype = Pin->DefaultValue;
|
LuaFunctionPrototype = Pin->DefaultValue;
|
||||||
CreateCorrectPins();
|
CreateCorrectPins();
|
||||||
@@ -356,7 +347,7 @@ void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext,
|
|||||||
// Add Packing operations for all argument pins.
|
// Add Packing operations for all argument pins.
|
||||||
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.Arguments)
|
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.Arguments)
|
||||||
{
|
{
|
||||||
UEdGraphPin *Pin = FindPinChecked(ArgumentNameAddPrefix(PinInfo.Name));
|
UEdGraphPin *Pin = FindPinChecked(AddPrefix(PinInfo.Name, 'A'));
|
||||||
UFunction *PackingFunc = UlxLuaCallLibrary::GetArgumentPacker(PinInfo.Type);
|
UFunction *PackingFunc = UlxLuaCallLibrary::GetArgumentPacker(PinInfo.Type);
|
||||||
if (PackingFunc == nullptr)
|
if (PackingFunc == nullptr)
|
||||||
{
|
{
|
||||||
@@ -378,10 +369,10 @@ void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext,
|
|||||||
PrevNode->GetThenPin()->MakeLinkTo(ActionNode->GetExecPin());
|
PrevNode->GetThenPin()->MakeLinkTo(ActionNode->GetExecPin());
|
||||||
PrevNode = ActionNode;
|
PrevNode = ActionNode;
|
||||||
|
|
||||||
// Add Unpacking operations for all argument pins.
|
// Add Unpacking operations for all return value pins.
|
||||||
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.ReturnValues)
|
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.ReturnValues)
|
||||||
{
|
{
|
||||||
UEdGraphPin *Pin = FindPinChecked(ReturnValueNameAddPrefix(PinInfo.Name));
|
UEdGraphPin *Pin = FindPinChecked(AddPrefix(PinInfo.Name, 'R'));
|
||||||
UFunction *UnpackingFunc = UlxLuaCallLibrary::GetReturnValueUnpacker(PinInfo.Type);
|
UFunction *UnpackingFunc = UlxLuaCallLibrary::GetReturnValueUnpacker(PinInfo.Type);
|
||||||
if (UnpackingFunc == nullptr)
|
if (UnpackingFunc == nullptr)
|
||||||
{
|
{
|
||||||
@@ -395,16 +386,26 @@ void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext,
|
|||||||
PrevNode = UnpackNode;
|
PrevNode = UnpackNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we didn't have return values for an invoke.
|
// If there is an extra results pin, hook it up.
|
||||||
if (IsInvoke && (ParsedProto.ReturnValues.Num() > 0))
|
if (ParsedProto.ExtraReturnValues)
|
||||||
{
|
{
|
||||||
CompilerContext.MessageLog.Error(TEXT("Lua Call in Invoke mode does not support return values"));
|
UEdGraphPin *Pin = FindPinChecked(ExtraResultsPinName);
|
||||||
|
UK2Node_CallFunction *UnpackNode = MakeCallFunctionNode(LuaCallLibraryFunction(LuaCallGetRest));
|
||||||
|
CompilerContext.MovePinLinksToIntermediate(*Pin, *UnpackNode->FindPinChecked(UEdGraphSchema_K2::PN_ReturnValue));
|
||||||
|
PrevNode->GetThenPin()->MakeLinkTo(UnpackNode->GetExecPin());
|
||||||
|
PrevNode = UnpackNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link up the Exec pins.
|
// Link up the Exec pins.
|
||||||
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BeginNode->GetExecPin());
|
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BeginNode->GetExecPin());
|
||||||
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *PrevNode->GetThenPin());
|
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *PrevNode->GetThenPin());
|
||||||
|
|
||||||
|
// Make sure we didn't have return values for an invoke.
|
||||||
|
if (IsInvoke && ((ParsedProto.ReturnValues.Num() > 0) || (ParsedProto.ExtraReturnValues)))
|
||||||
|
{
|
||||||
|
CompilerContext.MessageLog.Error(TEXT("Lua Call in Invoke mode does not support return values"));
|
||||||
|
}
|
||||||
|
|
||||||
BreakAllNodeLinks();
|
BreakAllNodeLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,14 +458,14 @@ UK2Node::ERedirectType UK2Node_LuaCall::DoPinsMatchForReconstruction(const UEdGr
|
|||||||
bool UK2Node_LuaCall::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason) const
|
bool UK2Node_LuaCall::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason) const
|
||||||
{
|
{
|
||||||
// The function pin cannot be connected.
|
// The function pin cannot be connected.
|
||||||
if (IsFunctionPin(MyPin))
|
if (MyPin->PinName == FunctionPinName)
|
||||||
{
|
{
|
||||||
OutReason = LOCTEXT("Error_FunctionPrototypeMustBeHardwired", "Lua function prototype must be a hardwired constant.").ToString();
|
OutReason = LOCTEXT("Error_FunctionPrototypeMustBeHardwired", "Lua function prototype must be a hardwired constant.").ToString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The invoke-or-probe pin cannot be connected.
|
// The invoke-or-probe pin cannot be connected.
|
||||||
if (IsInvokeOrProbePin(MyPin))
|
if (MyPin->PinName == InvokeOrProbePinName)
|
||||||
{
|
{
|
||||||
OutReason = LOCTEXT("Error_InvokeOrProbeMustBeHardwired", "Invoke vs Probe must be a hardwired constant.").ToString();
|
OutReason = LOCTEXT("Error_InvokeOrProbeMustBeHardwired", "Invoke vs Probe must be a hardwired constant.").ToString();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -69,9 +69,21 @@ class UK2Node_LuaCall : public UK2Node
|
|||||||
//~ End UK2Node Interface.
|
//~ End UK2Node Interface.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** Create all necessary pins. */
|
/** Create all necessary pins. */
|
||||||
void CreateCorrectPins();
|
void CreateCorrectPins();
|
||||||
|
|
||||||
|
/** Pin Names for the three built-in Pins **/
|
||||||
|
static const FName FunctionPinName;
|
||||||
|
static const FName InvokeOrProbePinName;
|
||||||
|
static const FName PlacePinName;
|
||||||
|
static const FName ExtraResultsPinName;
|
||||||
|
|
||||||
|
/** Utility functions for manipulating pin names with prefixes **/
|
||||||
|
static bool IsPrefix(const UEdGraphPin *Pin, char Prefix);
|
||||||
|
static FName AddPrefix(const FString &String, char Prefix);
|
||||||
|
static FString RemovePrefix(FName Name, char Prefix);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** The lua function prototype, which must be saved as a property **/
|
/** The lua function prototype, which must be saved as a property **/
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include "LuprexGameModeBase.h"
|
#include "LuprexGameModeBase.h"
|
||||||
#include "lpx-drvutil.hpp"
|
#include "lpx-drvutil.hpp"
|
||||||
#include "lpx-paths.hpp"
|
#include "lpx-paths.hpp"
|
||||||
#include "DebugPrint.h"
|
#include "ConsoleOutput.h"
|
||||||
#include "Tangible.h"
|
#include "Tangible.h"
|
||||||
#include "TangibleManager.h"
|
#include "TangibleManager.h"
|
||||||
#include "CommonTypes.h"
|
#include "CommonTypes.h"
|
||||||
@@ -11,9 +11,11 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
using namespace DebugPrint;
|
|
||||||
using namespace CommonTypes;
|
using namespace CommonTypes;
|
||||||
|
|
||||||
|
DEFINE_LOG_CATEGORY(LogLuprex);
|
||||||
|
DEFINE_LOG_CATEGORY(LogLuprexIntegration);
|
||||||
|
|
||||||
ALuprexGameModeBase::ALuprexGameModeBase()
|
ALuprexGameModeBase::ALuprexGameModeBase()
|
||||||
{
|
{
|
||||||
TangibleManager = NewObject<UlxTangibleManager>();
|
TangibleManager = NewObject<UlxTangibleManager>();
|
||||||
@@ -24,7 +26,6 @@ ALuprexGameModeBase::ALuprexGameModeBase()
|
|||||||
//PrimaryActorTick.TickGroup = TG_PrePhysics; // Probably wrong
|
//PrimaryActorTick.TickGroup = TG_PrePhysics; // Probably wrong
|
||||||
SetActorTickEnabled(true);
|
SetActorTickEnabled(true);
|
||||||
SetActorTickInterval(0.0f);
|
SetActorTickInterval(0.0f);
|
||||||
DebugPrintControl::EnableCollection();
|
|
||||||
ResetToInitialState();
|
ResetToInitialState();
|
||||||
OnWorldPreActorTickHandle = FWorldDelegates::OnWorldPreActorTick.AddUObject(this, &ALuprexGameModeBase::OnWorldPreActorTick);
|
OnWorldPreActorTickHandle = FWorldDelegates::OnWorldPreActorTick.AddUObject(this, &ALuprexGameModeBase::OnWorldPreActorTick);
|
||||||
OnWorldPostActorTickHandle = FWorldDelegates::OnWorldPostActorTick.AddUObject(this, &ALuprexGameModeBase::OnWorldPostActorTick);
|
OnWorldPostActorTickHandle = FWorldDelegates::OnWorldPostActorTick.AddUObject(this, &ALuprexGameModeBase::OnWorldPostActorTick);
|
||||||
@@ -103,12 +104,6 @@ void ALuprexGameModeBase::UpdateConsoleOutput() {
|
|||||||
ConsoleOutput.Append(lockedwrap.FetchStdout());
|
ConsoleOutput.Append(lockedwrap.FetchStdout());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy Debugging Prints into the console.
|
|
||||||
TArray<FString> prints = DebugPrintControl::GetStored();
|
|
||||||
for (const FString& fs : prints) {
|
|
||||||
ConsoleOutput.AppendLine(fs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the Console text has changed, update the widget.
|
// If the Console text has changed, update the widget.
|
||||||
if (ConsoleOutput.IsDirty()) {
|
if (ConsoleOutput.IsDirty()) {
|
||||||
ConsoleSetOutput(ConsoleOutput.Get());
|
ConsoleSetOutput(ConsoleOutput.Get());
|
||||||
@@ -192,21 +187,7 @@ void ALuprexGameModeBase::LuaCallEnd(InvocationKind kind, AActor *place) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ALuprexGameModeBase::ExecuteDebuggingCommand(FlxLockedWrapper &w, const FString &fs) {
|
void ALuprexGameModeBase::ExecuteDebuggingCommand(FlxLockedWrapper &w, const FString &fs) {
|
||||||
if (fs == "\\invokeplayer") {
|
// Nothing here right now.
|
||||||
DPrint(TEXT("Trying to invoke 'myfunction' in lua"));
|
|
||||||
FlxStreamBuffer &sb = LuaCallBegin();
|
|
||||||
sb.write_string("engio");
|
|
||||||
sb.write_string("myfunction");
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
|
||||||
sb.write_double(3.0);
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::STRING);
|
|
||||||
sb.write_string("Howdy");
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
|
|
||||||
sb.write_fvector(FVector(2,3,4));
|
|
||||||
LuaCallEnd(InvocationKind::LUA_INVOKE);
|
|
||||||
} else {
|
|
||||||
ConsoleOutput.AppendLine(TEXT("Unknown Command"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALuprexGameModeBase::ConsoleSendInput(const FString& fs)
|
void ALuprexGameModeBase::ConsoleSendInput(const FString& fs)
|
||||||
@@ -262,16 +243,13 @@ void ALuprexGameModeBase::Tick(float deltaseconds)
|
|||||||
|
|
||||||
void ALuprexGameModeBase::BeginPlay()
|
void ALuprexGameModeBase::BeginPlay()
|
||||||
{
|
{
|
||||||
Super::BeginPlay();
|
|
||||||
|
|
||||||
// Make sure we're starting from a clean slate.
|
|
||||||
// Note: this claims the wrapper lock, so don't claim
|
|
||||||
// the lock before calling this.
|
|
||||||
ResetToInitialState();
|
ResetToInitialState();
|
||||||
|
InitializeGlobalState();
|
||||||
|
Super::BeginPlay();
|
||||||
|
}
|
||||||
|
|
||||||
// Now we're just going to claim the wrapper
|
void ALuprexGameModeBase::InitializeGlobalState()
|
||||||
// lock for the remainder. When we create the thread,
|
{
|
||||||
// the thread will hang until we release this lock.
|
|
||||||
FlxLockedWrapper w(LockableWrapper);
|
FlxLockedWrapper w(LockableWrapper);
|
||||||
|
|
||||||
// Sanity checks. Make sure everything is clean.
|
// Sanity checks. Make sure everything is clean.
|
||||||
@@ -284,7 +262,7 @@ void ALuprexGameModeBase::BeginPlay()
|
|||||||
// If we failed to initialize the wrapper, print an error message.
|
// If we failed to initialize the wrapper, print an error message.
|
||||||
if (w->play_initialize == nullptr)
|
if (w->play_initialize == nullptr)
|
||||||
{
|
{
|
||||||
DPrint("Luprex wrapper initialization failed");
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Luprex wrapper initialization failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If wrapper is initialized, try to initialize the luprex engine.
|
// If wrapper is initialized, try to initialize the luprex engine.
|
||||||
@@ -294,7 +272,8 @@ void ALuprexGameModeBase::BeginPlay()
|
|||||||
std::string srcpakerr = drvutil::package_lua_source(LUPREX_ROOT_PATH, &srcpak);
|
std::string srcpakerr = drvutil::package_lua_source(LUPREX_ROOT_PATH, &srcpak);
|
||||||
if (!srcpakerr.empty())
|
if (!srcpakerr.empty())
|
||||||
{
|
{
|
||||||
DPrint(srcpakerr.c_str());
|
FString FMessage((const UTF8CHAR *)(srcpakerr.c_str()));
|
||||||
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Trying to read Lua source: %s"), *FMessage);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -304,10 +283,11 @@ void ALuprexGameModeBase::BeginPlay()
|
|||||||
w->play_initialize(w.Get(), 1, argv, srcpakv.size(), srcpakv.data(), "");
|
w->play_initialize(w.Get(), 1, argv, srcpakv.size(), srcpakv.data(), "");
|
||||||
if (w->error[0])
|
if (w->error[0])
|
||||||
{
|
{
|
||||||
DPrint(w->error);
|
FString FMessage((const UTF8CHAR *)w->error);
|
||||||
|
UE_LOG(LogLuprexIntegration, Error, TEXT("Calling Luprex play_initialize: %s"), *FMessage);
|
||||||
}
|
}
|
||||||
if (w->engine != nullptr) {
|
if (w->engine != nullptr) {
|
||||||
DPrint("Luprex initialize success");
|
UE_LOG(LogLuprexIntegration, Verbose, TEXT("Luprex initialization success."));
|
||||||
Playing = true;
|
Playing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "GameFramework/GameModeBase.h"
|
#include "GameFramework/GameModeBase.h"
|
||||||
#include "lpx-enginewrapper.hpp"
|
#include "lpx-enginewrapper.hpp"
|
||||||
#include "DebugPrint.h"
|
#include "ConsoleOutput.h"
|
||||||
#include "StringDecoder.h"
|
#include "StringDecoder.h"
|
||||||
#include "TangibleManager.h"
|
#include "TangibleManager.h"
|
||||||
#include "LuprexSockets.h"
|
#include "LuprexSockets.h"
|
||||||
@@ -13,6 +13,11 @@
|
|||||||
#include "BlueprintErrors.h"
|
#include "BlueprintErrors.h"
|
||||||
#include "LuprexGameModeBase.generated.h"
|
#include "LuprexGameModeBase.generated.h"
|
||||||
|
|
||||||
|
// Messages that come from inside the Luprex Core.
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(LogLuprex, Warning, All);
|
||||||
|
|
||||||
|
// Messages that pertain to our Luprex integration with Unreal.
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(LogLuprexIntegration, Warning, All);
|
||||||
|
|
||||||
class LookAtDetector;
|
class LookAtDetector;
|
||||||
|
|
||||||
@@ -35,6 +40,9 @@ public:
|
|||||||
// includes: the Luprex engine, the thread, and the socket state.
|
// includes: the Luprex engine, the thread, and the socket state.
|
||||||
void ResetToInitialState();
|
void ResetToInitialState();
|
||||||
|
|
||||||
|
// Initialize the Luprex DLL, and do other global initialization.
|
||||||
|
void InitializeGlobalState();
|
||||||
|
|
||||||
// Set the entire contents of the console output box.
|
// Set the entire contents of the console output box.
|
||||||
UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Miscellaneous")
|
UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Miscellaneous")
|
||||||
void ConsoleSetOutput(const FString& text);
|
void ConsoleSetOutput(const FString& text);
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
|
|
||||||
#include "LuprexSockets.h"
|
#include "LuprexSockets.h"
|
||||||
|
#include "LuprexGameModeBase.h"
|
||||||
#include "lpx-enginewrapper.hpp"
|
#include "lpx-enginewrapper.hpp"
|
||||||
#include "lpx-drvutil.hpp"
|
#include "lpx-drvutil.hpp"
|
||||||
#include "DebugPrint.h"
|
|
||||||
#include "Sockets.h"
|
#include "Sockets.h"
|
||||||
#include "SocketTypes.h"
|
#include "SocketTypes.h"
|
||||||
#include "SocketSubsystem.h"
|
#include "SocketSubsystem.h"
|
||||||
#include "AddressInfoTypes.h"
|
#include "AddressInfoTypes.h"
|
||||||
|
|
||||||
using namespace DebugPrint;
|
|
||||||
|
|
||||||
#define UI UI_ST
|
#define UI UI_ST
|
||||||
THIRD_PARTY_INCLUDES_START
|
THIRD_PARTY_INCLUDES_START
|
||||||
@@ -215,9 +214,9 @@ public:
|
|||||||
FlxSocketsI(FlxLockedWrapper &w);
|
FlxSocketsI(FlxLockedWrapper &w);
|
||||||
virtual ~FlxSocketsI() override;
|
virtual ~FlxSocketsI() override;
|
||||||
|
|
||||||
// Copy the trace to the DPrint output.
|
// Copy the trace to UE_LOG.
|
||||||
void DPrintTrace();
|
void LogTrace();
|
||||||
|
|
||||||
// Error handling.
|
// Error handling.
|
||||||
void SetError(const std::string& s);
|
void SetError(const std::string& s);
|
||||||
virtual std::string GetError() override { return FatalError; }
|
virtual std::string GetError() override { return FatalError; }
|
||||||
@@ -686,7 +685,7 @@ void FLpxChannel::AdvanceAccepting()
|
|||||||
{
|
{
|
||||||
CloseChannelIfSSLErrorIsSerious( retval);
|
CloseChannelIfSSLErrorIsSerious( retval);
|
||||||
}
|
}
|
||||||
LSI->DPrintTrace();
|
LSI->LogTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLpxChannel::AdvanceReadWrite()
|
void FLpxChannel::AdvanceReadWrite()
|
||||||
@@ -933,12 +932,13 @@ FlxSocketsI::~FlxSocketsI()
|
|||||||
// TODO: Be more thorough.
|
// TODO: Be more thorough.
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlxSocketsI::DPrintTrace()
|
void FlxSocketsI::LogTrace()
|
||||||
{
|
{
|
||||||
char* data;
|
char* data;
|
||||||
int ndata = BIO_get_mem_data(TraceBIO, &data);
|
int ndata = BIO_get_mem_data(TraceBIO, &data);
|
||||||
if (ndata == 0) return;
|
if (ndata == 0) return;
|
||||||
DPrint(data, ndata);
|
FString text(ndata, (const UTF8CHAR *)data);
|
||||||
|
UE_LOG(LogLuprexIntegration, Verbose, TEXT("SSL Trace: %s"), *text);
|
||||||
BIO_reset(TraceBIO);
|
BIO_reset(TraceBIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ bool UlxLuaValues::Initialize(std::string_view data)
|
|||||||
SimpleDynamicTag Tag = Decoder.read_simple_dynamic_tag();
|
SimpleDynamicTag Tag = Decoder.read_simple_dynamic_tag();
|
||||||
|
|
||||||
int64 Pos = Decoder.total_reads();
|
int64 Pos = Decoder.total_reads();
|
||||||
ELxLuaValueType Type;
|
ElxLuaValueType Type;
|
||||||
switch (Tag)
|
switch (Tag)
|
||||||
{
|
{
|
||||||
case SimpleDynamicTag::BOOLEAN: Type=ELxLuaValueType::Boolean; Decoder.read_bool(); break;
|
case SimpleDynamicTag::BOOLEAN: Type=ElxLuaValueType::Boolean; Decoder.read_bool(); break;
|
||||||
case SimpleDynamicTag::NUMBER: Type=ELxLuaValueType::Float; Decoder.read_double(); break;
|
case SimpleDynamicTag::NUMBER: Type=ElxLuaValueType::Float; Decoder.read_double(); break;
|
||||||
case SimpleDynamicTag::STRING: Type=ELxLuaValueType::String; Decoder.read_string_view(); 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::TOKEN: Type=ElxLuaValueType::Name; Decoder.read_string_view(); break;
|
||||||
case SimpleDynamicTag::VECTOR: Type=ELxLuaValueType::Vector; Decoder.read_fvector(); break;
|
case SimpleDynamicTag::VECTOR: Type=ElxLuaValueType::Vector; Decoder.read_fvector(); break;
|
||||||
default: {
|
default: {
|
||||||
Empty();
|
Empty();
|
||||||
return false;
|
return false;
|
||||||
@@ -42,22 +42,57 @@ bool UlxLuaValues::Initialize(std::string_view data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UlxLuaValues::CheckType(ELxLuaValueType Type, ELxLuaValueType Desired)
|
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)
|
if (Type != Desired)
|
||||||
{
|
{
|
||||||
FString TypeName = StaticEnum<ELxLuaValueType>()->GetDisplayNameTextByValue(int64(Type)).ToString();
|
FString TypeName = StaticEnum<ElxLuaValueType>()->GetDisplayNameTextByValue(int64(Type)).ToString();
|
||||||
FString DesiredName = StaticEnum<ELxLuaValueType>()->GetDisplayNameTextByValue(int64(Desired)).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);
|
UE_LOG(LogBlueprint, Error, TEXT("Expected a value of type %s, but found %s instead."), *DesiredName, *TypeName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ELxLuaValueType UlxLuaValues::GetType(int n) const
|
ElxLuaValueType UlxLuaValues::GetType(int n) const
|
||||||
{
|
{
|
||||||
if (n < 0) return ELxLuaValueType::None;
|
if (n < 0) return ElxLuaValueType::None;
|
||||||
if (n >= Types.Num()) return ELxLuaValueType::None;
|
if (n >= Types.Num()) return ElxLuaValueType::None;
|
||||||
return Types[Cursor];
|
return Types[Cursor];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,42 +104,42 @@ ELxLuaValueType UlxLuaValues::GetType(int n) const
|
|||||||
|
|
||||||
FString UlxLuaValues::GetString(int n) const
|
FString UlxLuaValues::GetString(int n) const
|
||||||
{
|
{
|
||||||
if (!CheckType(GetType(n), ELxLuaValueType::String)) return FString();
|
if (!CheckType(GetType(n), ElxLuaValueType::String)) return FString();
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
return Decoder.read_fstring();
|
return Decoder.read_fstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
FName UlxLuaValues::GetName(int n) const
|
FName UlxLuaValues::GetName(int n) const
|
||||||
{
|
{
|
||||||
if (!CheckType(GetType(n), ELxLuaValueType::Name)) return FName();
|
if (!CheckType(GetType(n), ElxLuaValueType::Name)) return FName();
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
return Decoder.read_fname();
|
return Decoder.read_fname();
|
||||||
}
|
}
|
||||||
|
|
||||||
double UlxLuaValues::GetFloat(int n) const
|
double UlxLuaValues::GetFloat(int n) const
|
||||||
{
|
{
|
||||||
if (!CheckType(GetType(n), ELxLuaValueType::Float)) return 0.0;
|
if (!CheckType(GetType(n), ElxLuaValueType::Float)) return 0.0;
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
return Decoder.read_double();
|
return Decoder.read_double();
|
||||||
}
|
}
|
||||||
|
|
||||||
int UlxLuaValues::GetInt(int n) const
|
int UlxLuaValues::GetInt(int n) const
|
||||||
{
|
{
|
||||||
if (!CheckType(GetType(n), ELxLuaValueType::Float)) return 0;
|
if (!CheckType(GetType(n), ElxLuaValueType::Float)) return 0;
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
return int(Decoder.read_double());
|
return int(Decoder.read_double());
|
||||||
}
|
}
|
||||||
|
|
||||||
FVector UlxLuaValues::GetVector(int n) const
|
FVector UlxLuaValues::GetVector(int n) const
|
||||||
{
|
{
|
||||||
if (!CheckType(GetType(n), ELxLuaValueType::Vector)) return FVector();
|
if (!CheckType(GetType(n), ElxLuaValueType::Vector)) return FVector();
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
return Decoder.read_fvector();
|
return Decoder.read_fvector();
|
||||||
}
|
}
|
||||||
|
|
||||||
FVector2D UlxLuaValues::GetVector2D(int n) const
|
FVector2D UlxLuaValues::GetVector2D(int n) const
|
||||||
{
|
{
|
||||||
if (!CheckType(GetType(n), ELxLuaValueType::Vector)) return FVector2D();
|
if (!CheckType(GetType(n), ElxLuaValueType::Vector)) return FVector2D();
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
FVector v = Decoder.read_fvector();
|
FVector v = Decoder.read_fvector();
|
||||||
return FVector2D(v.X, v.Y);
|
return FVector2D(v.X, v.Y);
|
||||||
@@ -112,7 +147,7 @@ FVector2D UlxLuaValues::GetVector2D(int n) const
|
|||||||
|
|
||||||
bool UlxLuaValues::GetBoolean(int n) const
|
bool UlxLuaValues::GetBoolean(int n) const
|
||||||
{
|
{
|
||||||
if (!CheckType(GetType(n), ELxLuaValueType::Boolean)) return false;
|
if (!CheckType(GetType(n), ElxLuaValueType::Boolean)) return false;
|
||||||
FlxStreamBuffer Decoder(Data[n]);
|
FlxStreamBuffer Decoder(Data[n]);
|
||||||
return Decoder.read_bool();
|
return Decoder.read_bool();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
UENUM(BlueprintType)
|
UENUM(BlueprintType)
|
||||||
enum class ELxLuaValueType : uint8 {
|
enum class ElxLuaValueType : uint8 {
|
||||||
None,
|
None,
|
||||||
String,
|
String,
|
||||||
Name,
|
Name,
|
||||||
@@ -105,7 +105,7 @@ private:
|
|||||||
|
|
||||||
// For each chunk, the type of the chunk.
|
// For each chunk, the type of the chunk.
|
||||||
//
|
//
|
||||||
TArray<ELxLuaValueType> Types;
|
TArray<ElxLuaValueType> Types;
|
||||||
|
|
||||||
// For each chunk, a pointer to the serialized data.
|
// For each chunk, a pointer to the serialized data.
|
||||||
//
|
//
|
||||||
@@ -120,16 +120,21 @@ private:
|
|||||||
//
|
//
|
||||||
void Empty();
|
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
|
// Copies the data, and then preprocesses it to make sure
|
||||||
// it's all valid. If it's not valid, returns false.
|
// it's all valid. If it's not valid, returns false.
|
||||||
//
|
//
|
||||||
bool Initialize(std::string_view data);
|
bool Initialize(std::string_view data);
|
||||||
|
|
||||||
// Compare two types. If they aren't equal, log an error and return false.
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
//
|
FString DebugString() const;
|
||||||
static bool CheckType(ELxLuaValueType Type, ELxLuaValueType Desired);
|
|
||||||
|
|
||||||
public:
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
int Length() const { return Types.Num(); }
|
int Length() const { return Types.Num(); }
|
||||||
|
|
||||||
@@ -139,16 +144,17 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
void SetCursor(int n) { Cursor = n; }
|
void SetCursor(int n) { Cursor = n; }
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//
|
//
|
||||||
// Functions that get values from the array, random access.
|
// Functions that get values from the array, random access.
|
||||||
//
|
//
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
ELxLuaValueType GetType(int n) const;
|
ElxLuaValueType GetType(int n) const;
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
bool IsType(int n, ELxLuaValueType Type) const { return GetType(n) == Type; }
|
bool IsType(int n, ElxLuaValueType Type) const { return GetType(n) == Type; }
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
FString GetString(int n) const;
|
FString GetString(int n) const;
|
||||||
@@ -177,10 +183,10 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
ELxLuaValueType NextType() const { return GetType(Cursor); }
|
ElxLuaValueType NextType() const { return GetType(Cursor); }
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
bool IsNextType(ELxLuaValueType Type) const { return IsType(Cursor, Type); }
|
bool IsNextType(ElxLuaValueType Type) const { return IsType(Cursor, Type); }
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
FString ReadString() { return GetString(Cursor++); }
|
FString ReadString() { return GetString(Cursor++); }
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "TangibleManager.h"
|
#include "TangibleManager.h"
|
||||||
#include "LuprexGameModeBase.h"
|
#include "LuprexGameModeBase.h"
|
||||||
|
|
||||||
#define DEFAULT_BLUEPRINT (TEXT("TangibleStaticMesh"))
|
#define DEFAULT_BLUEPRINT (TEXT("StaticMesh"))
|
||||||
|
|
||||||
UlxTangible::UlxTangible()
|
UlxTangible::UlxTangible()
|
||||||
{
|
{
|
||||||
@@ -24,17 +24,18 @@ void UlxTangible::Init(UlxTangibleManager* tm, int64 id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma optimize("", off)
|
#pragma optimize("", off)
|
||||||
void UlxTangible::SetActorBlueprint(const FString &name) {
|
void UlxTangible::SetActorBlueprint(const FString &XName) {
|
||||||
|
FString Name = XName.ToLower();
|
||||||
|
|
||||||
// If we're already of the right class, do nothing.
|
// If we're already of the right class, do nothing.
|
||||||
if (ActorBlueprintName == name) {
|
if (ActorBlueprintName == Name) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the blueprint.
|
// Get the blueprint.
|
||||||
// If the blueprint doesn't exist, or doesn't implement
|
UClass *blueprint = Manager->GetTangibleClass(Name);
|
||||||
// TangibleInterface, then use the fallback blueprint.
|
if (blueprint == nullptr)
|
||||||
UClass *blueprint = Manager->GetTangibleClass(name);
|
{
|
||||||
if ((!name.IsEmpty()) && (blueprint == nullptr)) {
|
|
||||||
blueprint = Manager->GetTangibleClass(DEFAULT_BLUEPRINT);
|
blueprint = Manager->GetTangibleClass(DEFAULT_BLUEPRINT);
|
||||||
check(blueprint != nullptr);
|
check(blueprint != nullptr);
|
||||||
}
|
}
|
||||||
@@ -62,13 +63,16 @@ void UlxTangible::SetActorBlueprint(const FString &name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the blueprint name
|
// Update the blueprint name
|
||||||
ActorBlueprintName = name;
|
ActorBlueprintName = Name;
|
||||||
|
|
||||||
// Now create a new actor, unless the BP is nullptr.
|
// Now create a new actor, unless the BP is nullptr.
|
||||||
if (blueprint != nullptr) {
|
if (blueprint != nullptr) {
|
||||||
UWorld* w = Manager->GetWorld();
|
UWorld* w = Manager->GetWorld();
|
||||||
FActorSpawnParameters params;
|
FActorSpawnParameters params;
|
||||||
|
|
||||||
|
// Give the new actor a reasonable name.
|
||||||
|
params.Name = FName(*FString::Printf(TEXT("%s_%ld"), *Name, TangibleId));
|
||||||
|
|
||||||
// Currently, the actor is spawned at (0,0,0), which is not good.
|
// Currently, the actor is spawned at (0,0,0), which is not good.
|
||||||
// We should spawn at the actor's current location. I'll get to it
|
// We should spawn at the actor's current location. I'll get to it
|
||||||
// eventually.
|
// eventually.
|
||||||
@@ -86,6 +90,9 @@ void UlxTangible::SetActorBlueprint(const FString &name) {
|
|||||||
AActor* a = w->SpawnActor(blueprint, &transform, params);
|
AActor* a = w->SpawnActor(blueprint, &transform, params);
|
||||||
check(a != nullptr);
|
check(a != nullptr);
|
||||||
|
|
||||||
|
// Make sure the label and the name are the same.
|
||||||
|
a->SetActorLabel(params.Name.ToString());
|
||||||
|
|
||||||
// Insert a TangibleComponent into the actor.
|
// Insert a TangibleComponent into the actor.
|
||||||
// Link the actor to its tangible, and the tangible to its actor.
|
// Link the actor to its tangible, and the tangible to its actor.
|
||||||
UActorComponent* ac = a->AddComponentByClass(UlxTangibleComponent::StaticClass(), false, FTransform::Identity, false);
|
UActorComponent* ac = a->AddComponentByClass(UlxTangibleComponent::StaticClass(), false, FTransform::Identity, false);
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Set the actor's blueprint, and recreate the actor if necessary.
|
// Set the actor's blueprint, and recreate the actor if necessary.
|
||||||
//
|
//
|
||||||
// If the blueprint is the empty string, deletes the actor.
|
// If the blueprint is the empty string, deletes the actor.
|
||||||
|
|||||||
@@ -3,11 +3,8 @@
|
|||||||
|
|
||||||
#include "TangibleManager.h"
|
#include "TangibleManager.h"
|
||||||
#include "Tangible.h"
|
#include "Tangible.h"
|
||||||
#include "DebugPrint.h"
|
|
||||||
#include "LuprexGameModeBase.h"
|
#include "LuprexGameModeBase.h"
|
||||||
|
|
||||||
using namespace DebugPrint;
|
|
||||||
|
|
||||||
UFunction *UlxTangibleManager::GetAnimationQueueChanged(UClass *uclass) {
|
UFunction *UlxTangibleManager::GetAnimationQueueChanged(UClass *uclass) {
|
||||||
UFunction *result = uclass->FindFunctionByName(FName(TEXT("Animation Queue Changed")));
|
UFunction *result = uclass->FindFunctionByName(FName(TEXT("Animation Queue Changed")));
|
||||||
if (result == nullptr) return nullptr;
|
if (result == nullptr) return nullptr;
|
||||||
@@ -16,6 +13,8 @@ UFunction *UlxTangibleManager::GetAnimationQueueChanged(UClass *uclass) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UClass *UlxTangibleManager::GetTangibleClass(const FString &name) {
|
UClass *UlxTangibleManager::GetTangibleClass(const FString &name) {
|
||||||
|
UPackage *Pack = LoadObject<UPackage>(nullptr, TEXT("/Game/Tangibles"));
|
||||||
|
UE_LOG(LogBlueprint, Verbose, TEXT("Pack=%ld"), int64(Pack));
|
||||||
if (name.IsEmpty()) {
|
if (name.IsEmpty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -24,8 +23,10 @@ UClass *UlxTangibleManager::GetTangibleClass(const FString &name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FString path(TEXT("/Game/Tangibles/"));
|
FString path(TEXT("/Game/Tangibles/"));
|
||||||
|
path += TEXT("Tan");
|
||||||
path += name;
|
path += name;
|
||||||
path += TCHAR('.');
|
path += TCHAR('.');
|
||||||
|
path += TEXT("Tan");
|
||||||
path += name;
|
path += name;
|
||||||
path += TCHAR('_');
|
path += TCHAR('_');
|
||||||
path += TCHAR('C');
|
path += TCHAR('C');
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
#include "TriggeredTask.h"
|
#include "TriggeredTask.h"
|
||||||
#include "DebugPrint.h"
|
|
||||||
|
|
||||||
using namespace DebugPrint;
|
|
||||||
|
|
||||||
FTriggeredTask::FTriggeredTask() {
|
FTriggeredTask::FTriggeredTask() {
|
||||||
Client = nullptr;
|
Client = nullptr;
|
||||||
@@ -16,7 +13,6 @@ uint32 FTriggeredTask::Run() {
|
|||||||
{
|
{
|
||||||
CallEvent->Wait();
|
CallEvent->Wait();
|
||||||
if (ThreadStopRequested) {
|
if (ThreadStopRequested) {
|
||||||
DPrint("Thread stopping as requested");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// The payload.
|
// The payload.
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ LuaDefine(tangible_build, "config",
|
|||||||
if (!LS.isnil(bp)) {
|
if (!LS.isnil(bp)) {
|
||||||
state.set_string("bp", LS.ckstring(bp));
|
state.set_string("bp", LS.ckstring(bp));
|
||||||
} else {
|
} else {
|
||||||
state.set_string("bp", LS.ckstring(classname));
|
state.set_string("bp", LS.classname(classtab));
|
||||||
}
|
}
|
||||||
if (!LS.isnil(plane)) {
|
if (!LS.isnil(plane)) {
|
||||||
state.set_string("plane", LS.ckstring(plane));
|
state.set_string("plane", LS.ckstring(plane));
|
||||||
|
|||||||
@@ -1,21 +1,14 @@
|
|||||||
makeclass('login')
|
makeclass('login')
|
||||||
makeclass("engio")
|
makeclass("engio")
|
||||||
makeclass('tree')
|
makeclass('cube')
|
||||||
|
makeclass('sphere')
|
||||||
function tree.init(self, config)
|
|
||||||
print("In tree.init:")
|
|
||||||
pprint{self=self, config=config}
|
|
||||||
wait(1)
|
|
||||||
print("tick");
|
|
||||||
wait(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
function login.init()
|
function login.init()
|
||||||
local actor = tangible.actor()
|
local actor = tangible.actor()
|
||||||
dprint("login.init:", actor)
|
dprint("login.init:", actor)
|
||||||
local x = math.random(1, 100)
|
tangible.animinit(actor, {bp="character", plane="earth", xyz={0, 0, 90}})
|
||||||
local y = math.random(1, 100)
|
tangible.build{class=cube, xyz={500,-100,0}}
|
||||||
tangible.animate(actor, nil, {bp="tangiblecharacter", action="warpto", plane="earth", xyz={x, y, 90}})
|
tangible.build{class=sphere, xyz={500,100,0}}
|
||||||
end
|
end
|
||||||
|
|
||||||
function engio.move(action, xyz, facing)
|
function engio.move(action, xyz, facing)
|
||||||
@@ -29,7 +22,7 @@ function engio.printhi(a1, a2, a3, a4, a5)
|
|||||||
pprint("Hi there", a1, a2, a3, a4, a5)
|
pprint("Hi there", a1, a2, a3, a4, a5)
|
||||||
end
|
end
|
||||||
|
|
||||||
function engio.retthree(a1, a2)
|
function engio.retmany()
|
||||||
return 7, vec(8,9,10), "Yo"
|
return 7, vec(8,9,10), "Yo", "Banana", 13.2, vec(2,3,4), "Hi"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user