From 4e74e00adfdbcff97db09d91dfb68e98e30a4790 Mon Sep 17 00:00:00 2001 From: Adam Lerer Date: Thu, 3 Nov 2016 15:53:42 -0400 Subject: [PATCH] Upgrade to support latest UE 4.13 (from 4.8) --- Scripts/uetorch.lua | 24 +- Scripts/uetorch_example.lua | 20 +- Setup.sh | 26 +- Source/UETorch/Classes/TorchPluginComponent.h | 18 +- .../UETorch/Private/TorchPluginComponent.cpp | 15 +- Source/UETorch/Private/UETorch.cpp | 98 +++-- Source/UETorch/UETorch.Build.cs | 6 +- UETorch.uplugin | 6 +- UnrealEngine.patch | 360 ++++++++---------- 9 files changed, 277 insertions(+), 296 deletions(-) diff --git a/Scripts/uetorch.lua b/Scripts/uetorch.lua index e1b6c3c..34dd7db 100644 --- a/Scripts/uetorch.lua +++ b/Scripts/uetorch.lua @@ -27,6 +27,8 @@ struct UObject; struct AActor; struct UMaterial; +AActor *FindActor(const char *fullName); + void GetViewportSize(IntSize* r); bool CaptureScreenshot(IntSize* size, void* data); bool CaptureSegmentation(UObject* _this, const IntSize* size, void* seg_data, int stride, const AActor** objects, int nObjects, bool verbose); @@ -34,7 +36,7 @@ bool CaptureMasks(UObject* _this, const IntSize* size, void* seg_data, int strid bool CaptureOpticalFlow(UObject* _this, const IntSize* size, void* flow_data, void* rgb_data, float maxFlow, int stride, bool verbose); bool CaptureDepthField(UObject* _this, const IntSize* size, void* data, int stride, bool verbose); -void PressKey(const char *key, int ControllerId, int eventType); +void PressKey(UObject* _this, const char *key, int ControllerId, int eventType); void SetMouse(int x, int y); bool SetTickDeltaBounds(UObject* _this, float MinDeltaSeconds, float MaxDeltaSeconds); bool SetResolution(int x, int y); @@ -193,12 +195,12 @@ local IE_RELEASED = 1 -- press and hold the key with this name function uetorch.PressKey(key) - utlib.PressKey(key, 0, IE_PRESSED) + utlib.PressKey(this, key, 0, IE_PRESSED) end -- release the key with this name function uetorch.ReleaseKey(key) - utlib.PressKey(key, 0, IE_RELEASED) + utlib.PressKey(this, key, 0, IE_RELEASED) end local _tapped = {} @@ -233,8 +235,8 @@ end function uetorch.GetActor(name) local level = UE.GetFullName(UE.GetCurrentLevel(this)) level = string.sub(level, 7, -1) -- remove "Level" - local actor = UE.FindObject(Actor.Class(), nil, level..'.'..name) - if tostring(actor) ~= 'userdata: (nil)' then + local actor = utlib.FindActor(level .. '.' .. name) + if tonumber(actor)) ~= 0 then return actor else return nil @@ -257,9 +259,9 @@ function uetorch.Screen(tensor) end tensor = tensor or torch.FloatTensor() + assert(torch.type(tensor) == 'torch.FloatTensor') tensor = tensor:resize(3, size[0].Y, size[0].X):contiguous() - - if not utlib.CaptureScreenshot(size, tensor:storage():cdata().data) then + if not utlib.CaptureScreenshot(size, tensor:data()) then print("ERROR: Unable to capture screenshot") return nil end @@ -298,7 +300,7 @@ function uetorch.ObjectSegmentation(objects, stride, verbose) local objectArr = ffi.new(string.format("AActor*[%d]",#objects), objects) - if not utlib.CaptureSegmentation(this, size, seg:storage():cdata().data, stride, objectArr, #objects, verbose) then + if not utlib.CaptureSegmentation(this, size, seg:data(), stride, objectArr, #objects, verbose) then print("ERROR: Unable to capture segmentation") return nil end @@ -338,7 +340,7 @@ function uetorch.ObjectMasks(objects, stride, verbose) local objectArr = ffi.new(string.format("AActor*[%d]",#objects), objects) - if not utlib.CaptureMasks(this, size, masks:storage():cdata().data, stride, objectArr, #objects, verbose) then + if not utlib.CaptureMasks(this, size, masks:data(), stride, objectArr, #objects, verbose) then print("ERROR: Unable to capture segmentation") return nil end @@ -381,7 +383,7 @@ function uetorch.OpticalFlow(maxFlow, stride, verbose) math.ceil(size[0].X/stride), 3) - if not utlib.CaptureOpticalFlow(this, size, flow:storage():cdata().data, rgb:storage():cdata().data, maxFlow, stride, verbose) then + if not utlib.CaptureOpticalFlow(this, size, flow:data(), rgb:data(), maxFlow, stride, verbose) then print("ERROR: Unable to capture optical flow") return nil end @@ -414,7 +416,7 @@ function uetorch.DepthField(stride, verbose) local depth = torch.FloatTensor(math.ceil(size[0].Y/stride), math.ceil(size[0].X/stride)) - if not utlib.CaptureDepthField(this, size, depth:storage():cdata().data, stride, verbose) then + if not utlib.CaptureDepthField(this, size, depth:data(), stride, verbose) then print("ERROR: Unable to capture depth field") return nil end diff --git a/Scripts/uetorch_example.lua b/Scripts/uetorch_example.lua index 8405dbb..66b0c92 100644 --- a/Scripts/uetorch_example.lua +++ b/Scripts/uetorch_example.lua @@ -7,6 +7,7 @@ ------------------------------------------------------------------------------- local uetorch = require 'uetorch' +print("loading uetorch_example") local M = {} @@ -43,13 +44,16 @@ function my_repl() end local cubes = {} -for i = 1, 11 do - cubes[i] = uetorch.GetActor(string.format('Cube%02d', i)) +for i = 1, 14 do + -- this is hardcoded for the objects in FirstPersonExampleMap,the first-person shooter demo map + -- At least in 4.13, these have names like 'EditorCube8_2' for some reason + cubes[i] = uetorch.GetActor(string.format('EditorCube%d_%d', i + 7, i + 1)) end ------------------------------------------------------------------------------- -- Tick Hook: automatically move towards blocks ------------------------------------------------------------------------------- +local frame = 0 local function ExampleTickHandler(dt) local seg = uetorch.ObjectSegmentation(cubes, 8) local centerStrip = seg:select(2, math.floor(seg:size(2)/2)) @@ -64,6 +68,18 @@ local function ExampleTickHandler(dt) -- move block 7 into the sky for fun local loc = uetorch.GetActorLocation(cubes[7]) uetorch.SetActorLocation(cubes[7], loc.x, loc.y, loc.z + 1) + + -- Demonstrate taking a screenshot. + -- There are other images you can capture like optical flow; + -- check out uetorch.lua for all of them. + if frame == 100 then + local screen = uetorch.Screen() + local filename = "./uetorch_screenshot.png" + print("Saving screenshot to " .. filename) + require 'image' + image.save(filename, screen) + end + frame = frame + 1 end uetorch.AddTickHook(ExampleTickHandler) diff --git a/Setup.sh b/Setup.sh index 7c73cdd..711950d 100755 --- a/Setup.sh +++ b/Setup.sh @@ -3,22 +3,10 @@ set -e DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -if git rev-parse 4.8-UETorch > /dev/null 2>&1; then - if [ $(git rev-parse 4.8-UETorch^1) != $(git rev-parse 4.8) ]; then - echo "git branch 4.8-UETorch already exists and has your commits on it. If you really want to re-run setup, you'll need to clean up and delete this branch yourself." - exit 1 - fi - git checkout 4.8 - git branch -D 4.8-UETorch -fi - -echo "=== Checking out the baseline UE4 commit... ===" -git checkout 4.8 - echo "=== Patching UE4 ===" cd $DIR/../../.. -git branch 4.8-UETorch -git checkout 4.8-UETorch +git branch UETorch_base +git checkout UETorch_base git apply $DIR/UnrealEngine.patch git add -u git commit -m "UETorch patches" @@ -30,12 +18,22 @@ echo "=== Setting up Lua... === " # tar zxf lua-5.2.4.tar.gz # cd lua-5.2.4 # make CFLAGS='-fPIC -DLUA_USE_LINUX' linux test + +# find Lua LUA=`which lua` +echo "LUA= $LUA" if [ $? != 0 ]; then echo "Couldn't find Lua. Did you forget to install torch and run torch-activate?" exit 1 fi +# check Lua version +LUA_VERSION=$($LUA -v | cut -c -7) +if [ "$LUA_VERSION" != "Lua 5.2" ]; then + echo "Expected Lua 5.2, but your Lua version is $LUA_VERSION, which is not supported." + exit 1 +fi + TORCH_BIN=`dirname $LUA` if [ ! -f "$TORCH_BIN/../include/lua.h" ]; then echo "Couldn't find lua.h relative to lua. Did you forget to install torch and run torch-activate?" diff --git a/Source/UETorch/Classes/TorchPluginComponent.h b/Source/UETorch/Classes/TorchPluginComponent.h index 6fcf241..e7c8be3 100644 --- a/Source/UETorch/Classes/TorchPluginComponent.h +++ b/Source/UETorch/Classes/TorchPluginComponent.h @@ -18,7 +18,7 @@ class FTorchContext; * loaded on game start, and can register functions to be executed on each * iteration ('tick') of the game loop. */ -UCLASS(Blueprintable, ClassGroup = Script, hidecategories = (Activation, Collision), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup = Script, hidecategories = (Object), meta = (BlueprintSpawnableComponent)) class UETORCH_API UTorchPluginComponent : public UActorComponent { GENERATED_UCLASS_BODY() @@ -49,14 +49,14 @@ class UETORCH_API UTorchPluginComponent : public UActorComponent UFUNCTION(BlueprintCallable, Category = "Script|Functions") virtual bool CallTorchFunctionString(FString FunctionName, FString In, FString &Out); - /** - * Calls a script defined function (Array -> string) - * @param FunctionName Name of the function to call - * @param In Array of String arguments to the function - * @param Out String output from the function - */ - UFUNCTION(BlueprintCallable, Category = "Script|Functions") - virtual bool CallTorchFunctionArray(FString FunctionName, TArray In, FString &Out); + /** + * Calls a script defined function (Array -> string) + * @param FunctionName Name of the function to call + * @param In Array of String arguments to the function + * @param Out String output from the function + */ + UFUNCTION(BlueprintCallable, Category = "Script|Functions") + virtual bool CallTorchFunctionArray(FString FunctionName, TArray In, FString &Out); // Begin UActorComponent interface. diff --git a/Source/UETorch/Private/TorchPluginComponent.cpp b/Source/UETorch/Private/TorchPluginComponent.cpp index 2eb7433..b5b4527 100644 --- a/Source/UETorch/Private/TorchPluginComponent.cpp +++ b/Source/UETorch/Private/TorchPluginComponent.cpp @@ -18,15 +18,20 @@ UTorchPluginComponent::UTorchPluginComponent(const FObjectInitializer& ObjectIni bTickInEditor = false; bAutoActivate = true; bWantsInitializeComponent = true; - MainModule = TEXT(""); + MainModule = TEXT(""); Context = NULL; } FString UTorchPluginComponent::MakeLuaInitString() { - FString InitStr = - "require 'uetorch';" // FIXME: use local uetorch package - "local _main = require '" + MainModule + "';" - "if type(_main)=='table' and _main.initialize then _main.initialize() end"; + FString InitStr; + if (MainModule != "") { + InitStr = + "require 'uetorch';" + "local _main = require '" + MainModule + "';" + "if type(_main)=='table' and _main.initialize then _main.initialize() end"; + } else { + InitStr = "require 'uetorch';"; + } return InitStr; } diff --git a/Source/UETorch/Private/UETorch.cpp b/Source/UETorch/Private/UETorch.cpp index 92a221d..dceeff6 100644 --- a/Source/UETorch/Private/UETorch.cpp +++ b/Source/UETorch/Private/UETorch.cpp @@ -10,6 +10,7 @@ #include "UETorchPrivatePCH.h" #include "TorchPluginComponent.h" #include "Kismet/KismetSystemLibrary.h" +#include "SceneViewport.h" #include @@ -37,6 +38,17 @@ void FUETorch::ShutdownModule() *************************************************************************/ +/** + * Find an actor by name. + * @param fullName the full name of the actor, usually . + * See uetorch.GetActor() in uetorch.lua for usage. + */ +extern "C" AActor *FindActor(const char *fullName) { + UObject* Obj = StaticFindObject(AActor::StaticClass(), NULL, *FString(fullName), false); + AActor* Result = Cast(Obj); + return Result; +} + /** * Simulate a user input event (press or relese a key). * @@ -48,43 +60,15 @@ void FUETorch::ShutdownModule() * IE_PRESSED - press the key * IE_RELEASED - release the key */ - extern "C" void PressKey(const char *key, int ControllerId, int eventType) { - auto fkey = FKey(key); - auto ViewportClient = GEngine->GameViewport; - - ViewportClient->InputKey(ViewportClient->Viewport, ControllerId, fkey, (EInputEvent) eventType); -} - -// SetTickDeltaBounds() requires a patch to Unreal Engine that adds MinDeltaSeconds and MaxDeltaSeconds -// to UWorld. -// This is an SFINAE check to see whether the patch has been applied. -struct UWorldHasMinDeltaSeconds -{ - struct Fallback { int MinDeltaSeconds; }; - struct Combined : UWorld, Fallback { }; - template struct SFINAE; + extern "C" void PressKey(UObject* _this, const char *key, int ControllerId, int eventType) { + auto fKey = FKey(key); - template static char f(SFINAE*); - template static int f(...); - - static bool const value = sizeof(f(0)) == sizeof(int); -}; - - -template -bool SetTickDeltaBoundsInternal(WorldT* World, float MinDeltaSeconds, float MaxDeltaSeconds, std::true_type) -{ - World->MinDeltaSeconds = MinDeltaSeconds; - World->MaxDeltaSeconds = MaxDeltaSeconds; - return true; -} - -template -bool SetTickDeltaBoundsInternal(WorldT* World, float MinDeltaSeconds, float MaxDeltaSeconds, std::false_type) -{ - printf("You need to the patch file located at Engine/Plugins/UETorch/UnrealEngine.patch\n"); - printf("and rebuild Unreal Engine for SetTickDeltaBounds to work\n"); - return false; + auto PlayerController = UGameplayStatics::GetPlayerController(_this, 0); + if(PlayerController == NULL) { + printf("PlayerController null\n"); + } else { + PlayerController->InputKey(fKey, (EInputEvent) eventType, 1.0, false); + } } /** @@ -101,13 +85,21 @@ bool SetTickDeltaBoundsInternal(WorldT* World, float MinDeltaSeconds, float MaxD */ extern "C" bool SetTickDeltaBounds(UObject* _this, float MinDeltaSeconds, float MaxDeltaSeconds) { - UWorld* World = GEngine->GetWorldFromContextObject(_this); - if(World == NULL) { + UWorld *world = GEngine->GetWorldFromContextObject(_this); + if(world == NULL) { printf("World null\n"); return false; } - return SetTickDeltaBoundsInternal(World, MinDeltaSeconds, MaxDeltaSeconds, - std::integral_constant()); + + AWorldSettings *settings = world->GetWorldSettings(); + if(settings == NULL) { + printf("WorldSettings null\n"); + return false; + } + settings->MinUndilatedFrameTime = MinDeltaSeconds; + settings->MaxUndilatedFrameTime = MaxDeltaSeconds; + + return true; } typedef struct { @@ -194,23 +186,28 @@ extern "C" bool CaptureScreenshot(IntSize* size, void* data) return false; } - TSharedPtr WindowPtr = GEngine->GameViewport->GetWindow(); + TSharedPtr ViewportPtr = GEngine->GameViewport->GetGameViewportWidget(); bool bScreenshotSuccessful = false; - - if( WindowPtr.IsValid() && FSlateApplication::IsInitialized() ) + FIntRect SizeRect(0, 0, size->X, size->Y); + if( ViewportPtr.IsValid() && FSlateApplication::IsInitialized()) { - FIntVector Size(size->X, size->Y, 0); - TSharedRef WindowRef = WindowPtr.ToSharedRef(); - bScreenshotSuccessful = FSlateApplication::Get().TakeScreenshot(WindowRef, Bitmap, Size); + FIntVector OutSize; + TSharedRef ViewportRef = ViewportPtr.ToSharedRef(); + bScreenshotSuccessful = FSlateApplication::Get().TakeScreenshot( + ViewportRef, SizeRect, Bitmap, OutSize); } else { - FIntRect Rect(0, 0, size->X, size->Y); - bScreenshotSuccessful = GetViewportScreenShot(Viewport, Bitmap, Rect); + bScreenshotSuccessful = GetViewportScreenShot(Viewport, Bitmap, SizeRect); } - if(bScreenshotSuccessful) + + if (bScreenshotSuccessful) { + if (Bitmap.Num() != size->X * size->Y) { + printf("Screenshot bitmap had the wrong number of elements: %d\n", Bitmap.Num()); + return false; + } float* values = (float*) data; for (const FColor& color : Bitmap) { *values++ = color.R / 255.0f; @@ -371,7 +368,6 @@ extern "C" bool CaptureSegmentation(UObject* _this, const IntSize* size, void* s FSceneView__SafeDeprojectFVector2D(SceneView, ScreenPosition, WorldOrigin, WorldDirection); // Cast ray from pixel to find intersecting object bool bHit = World->LineTraceSingleByChannel(HitResult, WorldOrigin, WorldOrigin + WorldDirection * HitResultTraceDistance, TraceChannel, CollisionQueryParams); - if (verbose) printf("E\n"); AActor* Actor = NULL; *seg_values = 0; // no foreground object if(bHit) { @@ -970,4 +966,4 @@ extern "C" bool SetResolution(int x, int y) { extern "C" void ExecuteConsoleCommand(UObject* _this, char* command) { UKismetSystemLibrary::ExecuteConsoleCommand(_this, command, NULL); -} \ No newline at end of file +} diff --git a/Source/UETorch/UETorch.Build.cs b/Source/UETorch/UETorch.Build.cs index 4067dbc..91da215 100644 --- a/Source/UETorch/UETorch.Build.cs +++ b/Source/UETorch/UETorch.Build.cs @@ -18,14 +18,14 @@ public UETorch(TargetInfo Target) { PublicIncludePaths.AddRange( new string[] { + "UETorch/Public" // ... add public include paths required here ... } ); PrivateIncludePaths.AddRange( new string[] { - // "UETorch/Private" - // how about Lua? + "UETorch/Private" // ... add other private include paths required here ... } ); @@ -38,7 +38,7 @@ public UETorch(TargetInfo Target) "Engine", "InputCore", "SlateCore", - "ScriptGeneratorPlugin", + // "ScriptGeneratorPlugin", "ScriptPlugin", // ... add other public dependencies that you statically link with here ... } diff --git a/UETorch.uplugin b/UETorch.uplugin index 514f9ee..9b17588 100644 --- a/UETorch.uplugin +++ b/UETorch.uplugin @@ -12,12 +12,12 @@ "Modules": [ { "Name": "UETorch", - "Type": "Developer", - "LoadingPhase": "PreDefault" + "Type": "Runtime", + "LoadingPhase": "Default" } ], "EnabledByDefault": true, "CanContainContent": false, "IsBetaVersion": false, - "Installed": false + "Installed": true } diff --git a/UnrealEngine.patch b/UnrealEngine.patch index 02395f3..dbfe3fd 100644 --- a/UnrealEngine.patch +++ b/UnrealEngine.patch @@ -1,179 +1,77 @@ -diff --git a/Engine/Source/Runtime/Engine/Classes/Engine/World.h b/Engine/Source/Runtime/Engine/Classes/Engine/World.h -index e96e60b..292a108 100644 ---- a/Engine/Source/Runtime/Engine/Classes/Engine/World.h -+++ b/Engine/Source/Runtime/Engine/Classes/Engine/World.h -@@ -928,6 +928,10 @@ public: - * You need Physics Scene if you'd like to trace. This flag changed ticking */ - bool bShouldSimulatePhysics; - -+ /** Min and max time to clamp a world tick. */ -+ float MinDeltaSeconds; -+ float MaxDeltaSeconds; -+ - #if WITH_EDITOR - /** this is special flag to enable collision by default for components that are not Volume - * currently only used by editor level viewport world, and do not use this for in-game scene -diff --git a/Engine/Source/Runtime/Engine/Private/Components/PrimitiveComponent.cpp b/Engine/Source/Runtime/Engine/Private/Components/PrimitiveComponent.cpp -index 44365fc..02d696b 100644 ---- a/Engine/Source/Runtime/Engine/Private/Components/PrimitiveComponent.cpp -+++ b/Engine/Source/Runtime/Engine/Private/Components/PrimitiveComponent.cpp -@@ -1425,7 +1425,6 @@ bool UPrimitiveComponent::MoveComponentImpl( const FVector& Delta, const FQuat& - const float DeltaSize = FMath::Sqrt(DeltaSizeSq); - for(int32 HitIdx=0; HitIdxGetEffectiveTimeDilation(); - // Clamp time between 2000 fps and 2.5 fps. -- DeltaSeconds = FMath::Clamp(DeltaSeconds,0.0005f,0.40f); -+ DeltaSeconds = FMath::Clamp(DeltaSeconds, MinDeltaSeconds, MaxDeltaSeconds); - DeltaTimeSeconds = DeltaSeconds; - - if ( !bIsPaused ) -diff --git a/Engine/Source/Runtime/Engine/Private/World.cpp b/Engine/Source/Runtime/Engine/Private/World.cpp -index 0479097..276a448 100644 ---- a/Engine/Source/Runtime/Engine/Private/World.cpp -+++ b/Engine/Source/Runtime/Engine/Private/World.cpp -@@ -123,6 +123,8 @@ UWorld::UWorld( const FObjectInitializer& ObjectInitializer ) - , AudioDeviceHandle(INDEX_NONE) - , FlushLevelStreamingType(EFlushLevelStreamingType::None) - , NextTravelType(TRAVEL_Relative) -+, MinDeltaSeconds(0.0005f) -+, MaxDeltaSeconds(0.40f) - { - TimerManager = new FTimerManager(); - #if WITH_EDITOR -diff --git a/Engine/Source/Runtime/Linux/ALAudio/Private/ALAudioDevice.cpp b/Engine/Source/Runtime/Linux/ALAudio/Private/ALAudioDevice.cpp -index f917903..84d2cba 100644 ---- a/Engine/Source/Runtime/Linux/ALAudio/Private/ALAudioDevice.cpp -+++ b/Engine/Source/Runtime/Linux/ALAudio/Private/ALAudioDevice.cpp -@@ -84,12 +84,19 @@ void FALAudioDevice::TeardownHardware( void ) - // Close the hardware device - if( &alcCloseDevice ) - { -- checkf(HardwareDevice, TEXT("Tearing down invalid OpenAL device! (HardwareDevice should not be null).")); -- const ALCchar* DeviceName = alcGetString(HardwareDevice, ALC_DEVICE_SPECIFIER); -- UE_LOG(LogALAudio, Log, TEXT("Closing ALAudio device : %s"), StringCast(static_cast(DeviceName)).Get()); -+ if(HardwareDevice) -+ { -+ // checkf(HardwareDevice, TEXT("Tearing down invalid OpenAL device! (HardwareDevice should not be null).")); -+ const ALCchar* DeviceName = alcGetString(HardwareDevice, ALC_DEVICE_SPECIFIER); -+ UE_LOG(LogALAudio, Log, TEXT("Closing ALAudio device : %s"), StringCast(static_cast(DeviceName)).Get()); - -- alcCloseDevice( HardwareDevice ); -- HardwareDevice = nullptr; -+ alcCloseDevice( HardwareDevice ); -+ HardwareDevice = nullptr; -+ } -+ else -+ { -+ UE_LOG(LogALAudio, Log, TEXT("Error: No ALAudio device found")); -+ } - } - - } -diff --git a/Engine/Source/Runtime/Core/Private/Linux/LinuxPlatformProcess.cpp b/Engine/Source/Runtime/Core/Private/Linux/LinuxPlatformProcess.cpp -index 977d885..612482f 100644 ---- a/Engine/Source/Runtime/Core/Private/Linux/LinuxPlatformProcess.cpp -+++ b/Engine/Source/Runtime/Core/Private/Linux/LinuxPlatformProcess.cpp -@@ -16,14 +16,15 @@ void* FLinuxPlatformProcess::GetDllHandle( const TCHAR* Filename ) - FString AbsolutePath = FPaths::ConvertRelativePathToFull(Filename); - - int DlOpenMode = RTLD_LAZY; -- if (AbsolutePath.EndsWith(TEXT("libsteam_api.so"))) -- { -- DlOpenMode |= RTLD_GLOBAL; //Global symbol resolution when loading shared objects - Needed for Steam to work when its library is loaded by a plugin -- } -- else -- { -- DlOpenMode |= RTLD_LOCAL; //Local symbol resolution when loading shared objects - Needed for Hot-Reload -- } -+ // if (AbsolutePath.EndsWith(TEXT("libsteam_api.so"))) -+ // { -+ // DlOpenMode |= RTLD_GLOBAL; //Global symbol resolution when loading shared objects - Needed for Steam to work when its library is loaded by a plugin -+ // } -+ // else -+ // { -+ // DlOpenMode |= RTLD_LOCAL; //Local symbol resolution when loading shared objects - Needed for Hot-Reload -+ // } -+ DlOpenMode |= RTLD_GLOBAL; - - void *Handle = dlopen( TCHAR_TO_ANSI(*AbsolutePath), DlOpenMode ); - if (!Handle) -diff --git a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/ScriptPlugin.cpp b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/ScriptPlugin.cpp -index 1c4fe64..ec6d75e 100644 ---- a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/ScriptPlugin.cpp -+++ b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/ScriptPlugin.cpp -@@ -16,7 +16,7 @@ UProperty* FindScriptPropertyHelper(UClass* Class, FName PropertyName) - return NULL; - } - --#if 0 -+#if WITH_LUA - #include "GeneratedScriptLibraries.inl" - #endif - -diff --git a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.h b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.h -index 658994f..697517b 100644 ---- a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.h -+++ b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.h -@@ -13,6 +13,7 @@ extern "C" - - class FLuaContext : public FScriptContextBase - { -+protected: - bool bHasTick; - bool bHasDestroy; - bool bHasBeginPlay; -diff --git a/Engine/Plugins/ScriptGeneratorPlugin/Source/ScriptGeneratorPlugin/Private/ScriptGeneratorPlugin.cpp b/Engine/Plugins/ScriptGeneratorPlugin/Source/ScriptGeneratorPlugin/Private/ScriptGeneratorPlugin.cpp -index 889dd14..09d6d95 100644 ---- a/Engine/Plugins/ScriptGeneratorPlugin/Source/ScriptGeneratorPlugin/Private/ScriptGeneratorPlugin.cpp -+++ b/Engine/Plugins/ScriptGeneratorPlugin/Source/ScriptGeneratorPlugin/Private/ScriptGeneratorPlugin.cpp -@@ -97,24 +97,6 @@ void FScriptGeneratorPlugin::FinishExport() +diff --git a/Engine/Plugins/ScriptPlugin/ScriptPlugin.uplugin b/Engine/Plugins/ScriptPlugin/ScriptPlugin.uplugin +index 13729f1..9fe6c28 100644 +--- a/Engine/Plugins/ScriptPlugin/ScriptPlugin.uplugin ++++ b/Engine/Plugins/ScriptPlugin/ScriptPlugin.uplugin +@@ -10,10 +10,10 @@ + "DocsURL" : "", + "MarketplaceURL" : "", + "SupportURL" : "", +- "EnabledByDefault" : false, ++ "EnabledByDefault" : true, + "CanContainContent" : false, + "IsBetaVersion" : false, +- "Installed" : false, ++ "Installed" : true, + "CanBeUsedWithUnrealHeaderTool" : true, + + "Modules" : +@@ -26,20 +26,12 @@ + { + "Name" : "ScriptPlugin", + "Type" : "Runtime", +- "LoadingPhase" : "PreDefault", +- "BlacklistPlatforms" : +- [ +- "Linux" +- ] ++ "LoadingPhase" : "PreDefault" + }, + { + "Name" : "ScriptEditorPlugin", + "Type" : "Editor", +- "LoadingPhase" : "Default", +- "BlacklistPlatforms" : +- [ +- "Linux" +- ] ++ "LoadingPhase" : "Default" + } + ] +-} +\ No newline at end of file ++} +diff --git a/Engine/Plugins/ScriptPlugin/Source/ScriptGeneratorPlugin/Private/ScriptGeneratorPlugin.cpp b/Engine/Plugins/ScriptPlugin/Source/ScriptGeneratorPlugin/Private/ScriptGeneratorPlugin.cpp +index aa41365..aad84a3 100644 +--- a/Engine/Plugins/ScriptPlugin/Source/ScriptGeneratorPlugin/Private/ScriptGeneratorPlugin.cpp ++++ b/Engine/Plugins/ScriptPlugin/Source/ScriptGeneratorPlugin/Private/ScriptGeneratorPlugin.cpp +@@ -97,6 +97,7 @@ void FScriptGeneratorPlugin::FinishExport() bool FScriptGeneratorPlugin::SupportsTarget(const FString& TargetName) const { -- // We only support the target if it explicitly enables the required script plugin in its uproject file -- bool bSupportsTarget = false; -- if (FPaths::IsProjectFilePathSet()) -- { -- FProjectDescriptor ProjectDescriptor; -- FText OutError; -- if (ProjectDescriptor.Load(FPaths::GetProjectFilePath(), OutError)) -- { -- for (auto& PluginDescriptor : ProjectDescriptor.Plugins) -- { -- // For your own script plugin you might want to change the hardcoded name here to something else -- if (PluginDescriptor.bEnabled && PluginDescriptor.Name == TEXT("ScriptPlugin")) -- { -- bSupportsTarget = true; -- break; -- } -- } -- } -- } ++#if 0 + // We only support the target if it explicitly enables the required script plugin in its uproject file + bool bSupportsTarget = false; + if (FPaths::IsProjectFilePathSet()) +@@ -116,5 +117,7 @@ bool FScriptGeneratorPlugin::SupportsTarget(const FString& TargetName) const + } + } + } - return bSupportsTarget; --} -\ No newline at end of file -+ // always build ScriptGeneratorPlugin ++#else + return true; -+} -diff --git a/Engine/Plugins/ScriptGeneratorPlugin/Source/ScriptGeneratorPlugin/ScriptGeneratorPlugin.Build.cs b/Engine/Plugins/ScriptGeneratorPlugin/Source/ScriptGeneratorPlugin/ScriptGeneratorPlugin.Build.cs -index a8656b5..c7f62d0 100644 ---- a/Engine/Plugins/ScriptGeneratorPlugin/Source/ScriptGeneratorPlugin/ScriptGeneratorPlugin.Build.cs -+++ b/Engine/Plugins/ScriptGeneratorPlugin/Source/ScriptGeneratorPlugin/ScriptGeneratorPlugin.Build.cs -@@ -48,17 +48,7 @@ namespace UnrealBuildTool.Rules ++#endif + } +\ No newline at end of file +diff --git a/Engine/Plugins/ScriptPlugin/Source/ScriptGeneratorPlugin/ScriptGeneratorPlugin.Build.cs b/Engine/Plugins/ScriptPlugin/Source/ScriptGeneratorPlugin/ScriptGeneratorPlugin.Build.cs +index a907246..d25f310 100644 +--- a/Engine/Plugins/ScriptPlugin/Source/ScriptGeneratorPlugin/ScriptGeneratorPlugin.Build.cs ++++ b/Engine/Plugins/ScriptPlugin/Source/ScriptGeneratorPlugin/ScriptGeneratorPlugin.Build.cs +@@ -46,20 +46,7 @@ namespace UnrealBuildTool.Rules + } + ); - // This checks only for UHT target platform, not the target platform of the game we're building so it's important - // to make sure Lua is compiled for all supported platforms +- // This checks only for UHT target platform, not the target platform of the game we're building so it's important +- // to make sure Lua is compiled for all supported platforms - var LuaLibDirectory = Path.Combine("..", "Plugins", "ScriptPlugin", "Source", "Lua", "Lib", Target.Platform.ToString(), "Release"); - var LuaLibPath = Path.Combine(LuaLibDirectory, "Lua.lib"); - if (File.Exists(LuaLibPath)) @@ -185,25 +83,59 @@ index a8656b5..c7f62d0 100644 - { - Log.TraceVerbose("ScriptGenerator LUA Integration NOT enabled"); - } +- + Definitions.Add("WITH_LUA=1"); + Definitions.Add("HACK_HEADER_GENERATOR=1"); } } --} -\ No newline at end of file -+} +diff --git a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.cpp b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.cpp +index 6ce7beb..d26a00a 100644 +--- a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.cpp ++++ b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.cpp +@@ -612,7 +612,8 @@ bool FLuaContext::Initialize(const FString& Code, UObject* Owner) + bool bResult = false; + LuaState = LuaNewState(); + luaL_openlibs(LuaState); +- LuaRegisterExportedClasses(LuaState); ++ // FIXME: get ScriptGeneratorPlugin to work :( ++ // LuaRegisterExportedClasses(LuaState); + LuaRegisterUnrealUtilities(LuaState); + + if (luaL_loadstring(LuaState, TCHAR_TO_ANSI(*Code)) == 0) +diff --git a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.h b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.h +index ac7a50e..a183b52 100644 +--- a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.h ++++ b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/Private/LuaIntegration.h +@@ -13,6 +13,7 @@ extern "C" + + class FLuaContext : public FScriptContextBase + { ++protected: + bool bHasTick; + bool bHasDestroy; + bool bHasBeginPlay; diff --git a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/ScriptPlugin.Build.cs b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/ScriptPlugin.Build.cs -index 3f80999..77078f4 100644 +index 4d27de3..a6ea780 100644 --- a/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/ScriptPlugin.Build.cs +++ b/Engine/Plugins/ScriptPlugin/Source/ScriptPlugin/ScriptPlugin.Build.cs -@@ -29,6 +29,7 @@ namespace UnrealBuildTool.Rules - "Engine", - "InputCore", - "SlateCore", -+ "ScriptGeneratorPlugin", - // ... add other public dependencies that you statically link with here ... +@@ -10,7 +10,7 @@ namespace UnrealBuildTool.Rules + { + PublicIncludePaths.AddRange( + new string[] { +- //"Programs/UnrealHeaderTool/Public", ++ //"Programs/UnrealHeaderTool/Public" + // ... add other public include paths required here ... } ); -@@ -53,22 +54,23 @@ namespace UnrealBuildTool.Rules +@@ -45,7 +45,6 @@ namespace UnrealBuildTool.Rules + + } + +- + DynamicallyLoadedModuleNames.AddRange( + new string[] + { +@@ -53,27 +52,22 @@ namespace UnrealBuildTool.Rules } ); @@ -211,34 +143,66 @@ index 3f80999..77078f4 100644 - var LuaLibDirectory = Path.Combine(LuaPath, "Lib", Target.Platform.ToString(), "Release"); - var LuaLibPath = Path.Combine(LuaLibDirectory, "Lua.lib"); - if (File.Exists(LuaLibPath)) +- { +- Definitions.Add("WITH_LUA=1"); + var LuaPath = Path.GetFullPath(Path.Combine("..", "Plugins", "ScriptPlugin", "Source", "Lua")); + var LuaInstallDirectory = Path.Combine(LuaPath, "install"); -+ var LuaLibDirectory = Path.Combine(LuaInstallDirectory, "lib"); -+ var LuaIncDirectory = Path.Combine(LuaInstallDirectory, "include"); -+ var LuaLib = Path.Combine(LuaLibDirectory, "liblua.so"); -+ if (File.Exists(LuaLib)) - { - Definitions.Add("WITH_LUA=1"); ++ var LuaLibDirectory = Path.Combine(LuaInstallDirectory, "lib"); ++ var LuaLibPath = Path.Combine(LuaLibDirectory, "liblua.so"); ++ Debug.Assert(File.Exists(LuaLibPath)); ++ Definitions.Add("WITH_LUA=1"); - // Path to Lua include files +- // Path to Lua include files - var IncludePath = Path.GetFullPath(Path.Combine(LuaPath, "Include")); - PrivateIncludePaths.Add(IncludePath); -+ PrivateIncludePaths.Add(LuaIncDirectory); ++ // Path to Lua include files ++ var IncludePath = Path.GetFullPath(Path.Combine(LuaInstallDirectory, "include")); ++ PrivateIncludePaths.Add(IncludePath); - // Lib file - PublicLibraryPaths.Add(LuaLibDirectory); +- // Lib file +- PublicLibraryPaths.Add(LuaLibDirectory); - PublicAdditionalLibraries.Add(LuaLibPath); -+ PublicAdditionalLibraries.Add(LuaLib); ++ // Lib file ++ PublicLibraryPaths.Add(LuaLibDirectory); ++ PublicAdditionalLibraries.Add(LuaLibPath); - Log.TraceVerbose("LUA Integration enabled: {0}", IncludePath); -+ Log.TraceVerbose("LUA Integration enabled: {0}", LuaInstallDirectory); - } - else - { -@@ -76,4 +78,4 @@ namespace UnrealBuildTool.Rules - } +- } +- else +- { +- Log.TraceVerbose("LUA Integration NOT enabled"); +- } ++ Log.TraceVerbose("LUA Integration enabled: {0}", IncludePath); } } -} \ No newline at end of file +} +diff --git a/Engine/Source/Runtime/Core/Private/Linux/LinuxPlatformProcess.cpp b/Engine/Source/Runtime/Core/Private/Linux/LinuxPlatformProcess.cpp +index a8d7a32..122ce3b 100644 +--- a/Engine/Source/Runtime/Core/Private/Linux/LinuxPlatformProcess.cpp ++++ b/Engine/Source/Runtime/Core/Private/Linux/LinuxPlatformProcess.cpp +@@ -26,14 +26,15 @@ void* FLinuxPlatformProcess::GetDllHandle( const TCHAR* Filename ) + FString AbsolutePath = FPaths::ConvertRelativePathToFull(Filename); + + int DlOpenMode = RTLD_LAZY; +- if (AbsolutePath.EndsWith(TEXT("libsteam_api.so"))) +- { +- DlOpenMode |= RTLD_GLOBAL; //Global symbol resolution when loading shared objects - Needed for Steam to work when its library is loaded by a plugin +- } +- else +- { +- DlOpenMode |= RTLD_LOCAL; //Local symbol resolution when loading shared objects - Needed for Hot-Reload +- } ++ // if (AbsolutePath.EndsWith(TEXT("libsteam_api.so"))) ++ // { ++ // DlOpenMode |= RTLD_GLOBAL; //Global symbol resolution when loading shared objects - Needed for Steam to work when its library is loaded by a plugin ++ // } ++ // else ++ // { ++ // DlOpenMode |= RTLD_LOCAL; //Local symbol resolution when loading shared objects - Needed for Hot-Reload ++ // } ++ DlOpenMode |= RTLD_GLOBAL; + + void *Handle = dlopen( TCHAR_TO_UTF8(*AbsolutePath), DlOpenMode ); + if (!Handle)