Lots of work on the lua read-eval-print loop
This commit is contained in:
BIN
Content/Luprex/lxGameMode.uasset
LFS
BIN
Content/Luprex/lxGameMode.uasset
LFS
Binary file not shown.
Binary file not shown.
BIN
Content/Testing/WB_Test.uasset
LFS
BIN
Content/Testing/WB_Test.uasset
LFS
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/Widgets/WB_Menu.uasset
LFS
BIN
Content/Widgets/WB_Menu.uasset
LFS
Binary file not shown.
@@ -1,20 +1,10 @@
|
|||||||
|
|
||||||
* UE Wingman rename functions.
|
|
||||||
* ue Wingman 'structprop' doesn't work for UWingXXXRef types, or for Widget slots. It needs to be implemented on top of getdetails.
|
|
||||||
* In the console, do not allow multi-line lua expressions unless it's something that reasonably should be multi-line, like a function definition or an if-statement.
|
|
||||||
|
|
||||||
* Keyboard Event Handling
|
|
||||||
|
|
||||||
* Menus
|
|
||||||
|
|
||||||
* Skeletal Mesh Tangible
|
* Skeletal Mesh Tangible
|
||||||
|
|
||||||
* Implement Interactive Temporary Variables
|
* Implement Interactive Temporary Variables
|
||||||
|
|
||||||
* A better text console
|
|
||||||
|
|
||||||
* Get rid of 3x3 Gridpanel stuff
|
|
||||||
|
|
||||||
* Object-Oriented Lua Support
|
* Object-Oriented Lua Support
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "Kismet/GameplayStatics.h"
|
#include "Kismet/GameplayStatics.h"
|
||||||
#include "Blueprint/UserWidget.h"
|
#include "Blueprint/UserWidget.h"
|
||||||
#include "Components/GridPanel.h"
|
#include "Components/GridPanel.h"
|
||||||
|
#include "Components/CanvasPanelSlot.h"
|
||||||
|
#include "Components/Widget.h"
|
||||||
#include "InputMappingContext.h"
|
#include "InputMappingContext.h"
|
||||||
#include "EnhancedInputComponent.h"
|
#include "EnhancedInputComponent.h"
|
||||||
#include "Animation/AnimSequenceBase.h"
|
#include "Animation/AnimSequenceBase.h"
|
||||||
@@ -156,65 +158,28 @@ bool UlxUtilityLibrary::LineTraceThroughPixel(const APlayerController* PlayerCon
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxUtilityLibrary::SetPositionOfGridPanelMiddleCell(UGridPanel *GridPanel, FVector2D UpperLeftXY, FVector2D LowerRightXY)
|
void UlxUtilityLibrary::ConfigureCanvasPanelSlot(UObject *Target, FAnchors Anchors, FVector2D Position, FVector2D Size, FVector2D Alignment, bool SizeToContent)
|
||||||
{
|
{
|
||||||
if ((GridPanel == nullptr) || (GridPanel->ColumnFill.Num() != 3) || (GridPanel->RowFill.Num() != 3))
|
UCanvasPanelSlot *CanvasSlot = Cast<UCanvasPanelSlot>(Target);
|
||||||
|
if (CanvasSlot == nullptr)
|
||||||
{
|
{
|
||||||
UE_LOG(LogBlueprint, Error, TEXT("SetPositionOfGridPanelMiddleCell only works on 3x3 GridPanels."));
|
UWidget *Widget = Cast<UWidget>(Target);
|
||||||
|
if (Widget != nullptr)
|
||||||
|
{
|
||||||
|
CanvasSlot = Cast<UCanvasPanelSlot>(Widget->Slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CanvasSlot == nullptr)
|
||||||
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("ConfigureCanvasPanelSlot: object is not a CanvasPanelSlot, and is not a Widget in a CanvasPanel."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((LowerRightXY.X < UpperLeftXY.X) || (LowerRightXY.Y < UpperLeftXY.Y))
|
CanvasSlot->SetAnchors(Anchors);
|
||||||
{
|
CanvasSlot->SetAlignment(Alignment);
|
||||||
UE_LOG(LogBlueprint, Error, TEXT("LowerRightXY must be greater than or equal to UpperLeftXY"));
|
CanvasSlot->SetPosition(Position);
|
||||||
return;
|
CanvasSlot->SetSize(Size);
|
||||||
}
|
CanvasSlot->SetAutoSize(SizeToContent);
|
||||||
|
|
||||||
UpperLeftXY.X = FMath::Clamp(UpperLeftXY.X, 0.0f, 1.0f);
|
|
||||||
UpperLeftXY.Y = FMath::Clamp(UpperLeftXY.Y, 0.0f, 1.0f);
|
|
||||||
LowerRightXY.X = FMath::Clamp(LowerRightXY.X, 0.0f, 1.0f);
|
|
||||||
LowerRightXY.Y = FMath::Clamp(LowerRightXY.Y, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
GridPanel->SetRowFill(0, UpperLeftXY.Y);
|
|
||||||
GridPanel->SetRowFill(1, LowerRightXY.Y - UpperLeftXY.Y);
|
|
||||||
GridPanel->SetRowFill(2, 1.0 - LowerRightXY.Y);
|
|
||||||
|
|
||||||
GridPanel->SetColumnFill(0, UpperLeftXY.X);
|
|
||||||
GridPanel->SetColumnFill(1, LowerRightXY.X - UpperLeftXY.X);
|
|
||||||
GridPanel->SetColumnFill(2, 1.0 - LowerRightXY.X);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UlxUtilityLibrary::GetPositionOfGridPanelMiddleCell(UGridPanel *GridPanel, FVector2D &UpperLeftXY, FVector2D &LowerRightXY)
|
|
||||||
{
|
|
||||||
TArray<float> &Col = GridPanel->ColumnFill;
|
|
||||||
TArray<float> &Row = GridPanel->RowFill;
|
|
||||||
|
|
||||||
// Set default return value for error situations.
|
|
||||||
UpperLeftXY.X = 0.0;
|
|
||||||
LowerRightXY.X = 1.0;
|
|
||||||
UpperLeftXY.Y = 0.0;
|
|
||||||
LowerRightXY.Y = 1.0;
|
|
||||||
|
|
||||||
if ((GridPanel == nullptr) || (Row.Num() != 3) || (Col.Num() != 3))
|
|
||||||
{
|
|
||||||
UE_LOG(LogBlueprint, Error, TEXT("SetPositionOfGridPanelMiddleCell only works on 3x3 GridPanels."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
double TotalX = Col[0] + Col[1] + Col[2];
|
|
||||||
double TotalY = Row[0] + Row[1] + Row[2];
|
|
||||||
|
|
||||||
if (TotalX > 0)
|
|
||||||
{
|
|
||||||
UpperLeftXY.X = Col[0] / TotalX;
|
|
||||||
LowerRightXY.X = (Col[0] + Col[1]) / TotalX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TotalY > 0)
|
|
||||||
{
|
|
||||||
UpperLeftXY.Y = Row[0] / TotalY;
|
|
||||||
LowerRightXY.Y = (Row[0] + Row[1]) / TotalY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ElxUsedOrNotUsed UlxUtilityLibrary::IsKeyUsedByMappingContext(const FKey &Key, const UInputMappingContext *MappingContext)
|
ElxUsedOrNotUsed UlxUtilityLibrary::IsKeyUsedByMappingContext(const FKey &Key, const UInputMappingContext *MappingContext)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "Input/Events.h"
|
#include "Input/Events.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||||
|
#include "Components/CanvasPanelSlot.h"
|
||||||
|
|
||||||
#include "UtilityLibrary.generated.h"
|
#include "UtilityLibrary.generated.h"
|
||||||
|
|
||||||
@@ -91,51 +92,15 @@ public:
|
|||||||
ETraceTypeQuery TraceChannel, bool bTraceComplex, EDrawDebugTrace::Type DrawDebugType, bool bIgnorePlayerPawn,
|
ETraceTypeQuery TraceChannel, bool bTraceComplex, EDrawDebugTrace::Type DrawDebugType, bool bIgnorePlayerPawn,
|
||||||
const TArray<AActor*>& ActorsToIgnore, FHitResult& HitResult);
|
const TArray<AActor*>& ActorsToIgnore, FHitResult& HitResult);
|
||||||
|
|
||||||
// Set Position of GridPanel Middle Cell
|
|
||||||
//
|
|
||||||
// Sometimes, you want to specify the position of a widget, and you
|
|
||||||
// don't want to specify the position in slate units, instead, you
|
|
||||||
// want to specify the position using fractions: ie, (0,0) is the
|
|
||||||
// upper left corner of the screen, and (1,1) is the lower-right corner.
|
|
||||||
//
|
|
||||||
// One way to accomplish this is to put your widget in the middle cell
|
|
||||||
// of a 3x3 GridPanel. Then, you can position it by adjusting the grid
|
|
||||||
// fill rules. This utility routine can do the math necessary to
|
|
||||||
// correctly populate those fill rules.
|
|
||||||
//
|
|
||||||
// This routine must be passed a 3x3 GridPanel. This will reposition
|
|
||||||
// the middle cell. You must specify the upper-left and lower-right
|
|
||||||
// corners of the middle cell as fractions between (0,0) and (1,1).
|
|
||||||
//
|
|
||||||
// Be aware that if the content of a grid cell overflows the amount of
|
|
||||||
// space allocated for it, then the grid will adjust to make room.
|
|
||||||
// But that will mean that the grid is no longer faithful to the
|
|
||||||
// positions specified in its fill rules. One way to ensure that the
|
|
||||||
// grid remains faithful to its fill rules is to put an Overlay
|
|
||||||
// into the GridPanel cell, then put -1000 padding into the
|
|
||||||
// Overlay's GridPanel slot, then put +1000 padding into the Overlay
|
|
||||||
// slot. The two paddings cancel each other out, leaving the item in
|
|
||||||
// the Overlay at the originally-intended position. But if the item
|
|
||||||
// in the overlay overflows, it doesn't cause the Grid to deform.
|
|
||||||
// Instead, the item exceeds the bounds of the grid cell, but it leaves
|
|
||||||
// the grid cell where it belongs.
|
|
||||||
//
|
|
||||||
UFUNCTION(BlueprintCallable, Category="Widget")
|
|
||||||
static void SetPositionOfGridPanelMiddleCell(UGridPanel *GridPanel, FVector2D UpperLeftXY, FVector2D LowerRightXY);
|
|
||||||
|
|
||||||
// Get Position of GridPanel Middle Cell
|
// Configure a CanvasPanelSlot's parameters in a single call.
|
||||||
//
|
//
|
||||||
// The routine must be passed a 3x3 GridPanel. This will return the
|
// Target must be either a UCanvasPanelSlot directly, or a UWidget whose
|
||||||
// position of the middle cell of the gridpanel, expressed on a scale
|
// Slot is a UCanvasPanelSlot. If it is neither, logs an error and
|
||||||
// from (0,0) to (1,1).
|
// does nothing.
|
||||||
//
|
|
||||||
// The numbers returned by this routine are based entirely on the
|
|
||||||
// GridPanel fill rules. If an item in the grid is overflowing its
|
|
||||||
// allocated space, causing the grid to deform, then that won't be
|
|
||||||
// reflected in the output of this routine.
|
|
||||||
//
|
//
|
||||||
UFUNCTION(BlueprintPure, Category="Widget")
|
UFUNCTION(BlueprintCallable, Category = "Widget", meta = (SizeToContent = "true"))
|
||||||
static void GetPositionOfGridPanelMiddleCell(UGridPanel *GridPanel, FVector2D &UpperLeftXY, FVector2D &LowerRightXY);
|
static void ConfigureCanvasPanelSlot(UObject *Target, FAnchors Anchors, FVector2D Position, FVector2D Size, FVector2D Alignment, bool SizeToContent);
|
||||||
|
|
||||||
// Check if a given key is used by the specified mapping context.
|
// Check if a given key is used by the specified mapping context.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ eng::string LuaCoreStack::load(LuaSlot result, std::string_view code, std::strin
|
|||||||
const char *str = lua_tolstring(L_, -1, &len);
|
const char *str = lua_tolstring(L_, -1, &len);
|
||||||
eng::string message(str, len);
|
eng::string message(str, len);
|
||||||
lua_pop(L_, 1);
|
lua_pop(L_, 1);
|
||||||
if (sv::has_suffix(message, "near <eof>"))
|
if (sv::has_suffix(message, "near <eof>") && sv::is_possible_long_lua_expression(code))
|
||||||
{
|
{
|
||||||
message = "truncated lua";
|
message = "truncated lua";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,7 +192,6 @@ bool PrintChanneler::channel(const PrintBuffer *printbuffer, StreamBuffer *sb) {
|
|||||||
line_ = printbuffer->first_line();
|
line_ = printbuffer->first_line();
|
||||||
}
|
}
|
||||||
while (line_ < printbuffer->first_unchecked()) {
|
while (line_ < printbuffer->first_unchecked()) {
|
||||||
sb->write_bytes("|");
|
|
||||||
sb->write_bytes(printbuffer->nth(line_));
|
sb->write_bytes(printbuffer->nth(line_));
|
||||||
sb->write_bytes("\n");
|
sb->write_bytes("\n");
|
||||||
line_ += 1;
|
line_ += 1;
|
||||||
|
|||||||
@@ -200,6 +200,24 @@ bool is_lua_comment(string_view s) {
|
|||||||
return s.substr(start, 2) == "--";
|
return s.substr(start, 2) == "--";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_possible_long_lua_expression(string_view s) {
|
||||||
|
read_space(s);
|
||||||
|
string_view id = read_lua_identifier(s);
|
||||||
|
if (id.empty()) return false;
|
||||||
|
if ((id == "function") || (id == "if") || (id == "while") || (id == "for") || (id == "repeat") || (id == "do")) return true;
|
||||||
|
if (id == "local")
|
||||||
|
{
|
||||||
|
read_space(s);
|
||||||
|
id = read_lua_identifier(s);
|
||||||
|
}
|
||||||
|
read_space(s);
|
||||||
|
read_prefix(s, "="); // If not present, returns false but we continue anyway.
|
||||||
|
read_space(s);
|
||||||
|
if (has_prefix(s, "[")) return true;
|
||||||
|
if (has_prefix(s, "(")) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_whitespace(string_view s) {
|
bool is_whitespace(string_view s) {
|
||||||
for (int i = 0; i < int(s.size()); i++) {
|
for (int i = 0; i < int(s.size()); i++) {
|
||||||
if (!ascii_isspace(s[i])) {
|
if (!ascii_isspace(s[i])) {
|
||||||
|
|||||||
@@ -106,6 +106,14 @@ bool is_lua_classname(string_view s);
|
|||||||
// Return true if the line of code is a lua comment.
|
// Return true if the line of code is a lua comment.
|
||||||
bool is_lua_comment(string_view s);
|
bool is_lua_comment(string_view s);
|
||||||
|
|
||||||
|
// Return true if the line of code could be the beginning of a long expression.
|
||||||
|
// In a read-eval-print loop, if the user types something like "function foo",
|
||||||
|
// that's not a complete lua expression. But we don't want to just print an error,
|
||||||
|
// we want to give the user a chance to continue typing so that he can turn it
|
||||||
|
// into a complete lua expression. This function returns true if the string looks
|
||||||
|
// like the beginning of a long lua expression. This is only a heuristic.
|
||||||
|
bool is_possible_long_lua_expression(string_view s);
|
||||||
|
|
||||||
// Return true if the line is entirely whitespace.
|
// Return true if the line is entirely whitespace.
|
||||||
bool is_whitespace(string_view s);
|
bool is_whitespace(string_view s);
|
||||||
|
|
||||||
|
|||||||
@@ -1071,6 +1071,10 @@ void World::run_scheduled_threads() {
|
|||||||
PrettyPrint::Indented().print(LSCO, LuaSpecial(i), <hread_prints_);
|
PrettyPrint::Indented().print(LSCO, LuaSpecial(i), <hread_prints_);
|
||||||
lthread_prints_ << std::endl;
|
lthread_prints_ << std::endl;
|
||||||
}
|
}
|
||||||
|
if (lthread_prints_.view().empty())
|
||||||
|
{
|
||||||
|
lthread_prints_ << "ok\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (status == LUA_YIELD) {
|
} else if (status == LUA_YIELD) {
|
||||||
if (is_authoritative()) {
|
if (is_authoritative()) {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ function cube.lookmenu(add)
|
|||||||
add("Cube Hi", function () dprint("Doing Cube Hi") end)
|
add("Cube Hi", function () dprint("Doing Cube Hi") end)
|
||||||
add("Cube Bye", function () dprint("Doing Cube Bye") end)
|
add("Cube Bye", function () dprint("Doing Cube Bye") end)
|
||||||
add("Cube Yo", function () dprint("Doing Cube Yo") end)
|
add("Cube Yo", function () dprint("Doing Cube Yo") end)
|
||||||
|
add("Cube Z", function () dprint("Doing Cube Z") end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function sphere.lookhotkeys(add)
|
function sphere.lookhotkeys(add)
|
||||||
|
|||||||
Reference in New Issue
Block a user