The old logic for dealing with the parameters within the Unreal function thunk (UPythonGeneratedClass::CallPythonFunction and UPythonCallableForDelegate::CallPythonNative) assumed that Stack.Locals would be set-up correctly for input, and could be written to for output. This isn't true, as Stack.Locals is populated by a memcpy in UObject::ProcessEvent (so isn't safe to write to for non-POD data), and Blueprints just pass along their existing frame data since they skip the call to ProcessScriptFunction (as Python generated functions are marked FUNC_Native).
This change adds a common thunk processing function (PyGenUtil::InvokePythonCallableFromUnrealFunctionThunk) which is used when calling into Python from an Unreal function thunk. This function steps the data off the stack frame for each property, copying input data to Python, and building the output chain (FOutParmRec) from output data addresses. This matches what the UHT generated thunk does for native functions (via P_GET_PROPERTY and P_GET_PROPERTY_REF), as well as what ProcessScriptFunction does for functions with Blueprint bytecode.
#jira UE-75405
#jira UE-75449
[FYI] Rex.Hill
#rb Dan.OConnor
#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: jamie.dale
#ROBOMERGE-SOURCE: CL 7064650 in //UE4/Release-4.23/... via CL 7064651
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR) (v367-6836689)
[CL 7151907 by jamie dale in Dev-VR branch]
Failing to do this leads to a Native instance inside a non-native instance, which causes GC confusion
#jira UE-74616
#rb Lauren.Ridge
#ROBOMERGE-VERSION: 348-6547088
#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: jamie.dale
#ROBOMERGE-SOURCE: CL 6536762 via CL 6538364 via CL 6538485
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)
[CL 6577234 by jamie dale in Dev-VR branch]
We now ARO these pending types to stop them being GC'd, and added unreal.flush_generated_type_reinstancing() to allow you to force the reinstancing to happen at a certain point in your script (rather than when it ends, or on the next Tick).
#jira UE-72853
#rb Chris.Gagnon
#lockdown Cristina.Riveron
#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: jamie.dale
#ROBOMERGE-SOURCE: CL 5956901 in //UE4/Release-4.22/... via CL 5956925
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)
[CL 5963139 by jamie dale in Dev-VR branch]
The definition of the delegate type must specify the class and property name of the delegate that will use it and the type cannot be used outside of that context or just on the stack.
UMulticastDelegateProperty is now abstract and has 2 subclasses (UMulticastDelegateInlineProperty and UMulticastDelegateSparseProperty). The SparseProperty SignatureFunction will be a USparseDelegateFunction.
The sparse delegates do not work correctly with the python bindings at this point, but this will be visited soon.
#rb Michael.Noland
#jira
#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: marc.audy
#ROBOMERGE-SOURCE: CL 5295832 via CL 5306530 via CL 5306657
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)
[CL 5323394 by marc audy in Dev-VR branch]
This is off by default, and discovery is limited to the local host by default for safety. To enable it you need to turn on remote discovery in the Python plug-in project settings, which will make your editor discoverable for remote execution (via external scripts using the remote_execution.py module).
Remote execution uses a protocol of UTF-8 encoded JSON, and a combination of UDP-based multicast for discovery and remote connection requests, and TCP-based peer-to-peer communication for the actual command channel. See PythonScriptRemoteExecution.cpp for the full protocol definition.
remote_execution.py serves as both a reference implementation for the protocol implementation needed to connect to an editor instance, and as an out-of-the-box solution for applications that are written in (or can execute) Python (by importing it as a module and creating a RemoteExecution instance). remote_execution.py also provides a minimal example at the bottom of the file that demonstrates how to use the API, and this demo application can be seen by executing the file directly.
[FYI] Aaron.Carlisle
#rb Chris.Gagnon
#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: jamie.dale
#ROBOMERGE-SOURCE: CL 5229289 via CL 5236106 via CL 5236230
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)
[CL 5254819 by jamie dale in Dev-VR branch]
You're now able to get back the execution result and log output from running a Python command, as well as control the execution mode of the command, and whether it should be run in "unattended" mode.
This is handled by the new IPythonScriptPlugin::ExecPythonCommandEx function which takes a FPythonCommandEx struct containing the input flags, mode, and command, as well as fields to fill in with the result and log output.
The mode can be set to one of the following:
- ExecuteFile: Execute the Python command as a file. This allows you to execute either a literal Python script containing multiple statements, or a file with optional arguments.
- ExecuteStatement: Execute the Python command as a single statement. This will execute a single statement and print the result. This mode cannot run files.
- EvaluateStatement: Evaluate the Python command as a single statement. This will evaluate a single statement and return the result. This mode cannot run files.
ExecuteFile is the default to preserve existing behavior, however, since ExecuteStatement allows for a REPL like environment, there is now an additional command executor available ("Python (REPL)") which lets you build and test Python scripts in a similar manner to an interactive command line Python environment.
[FYI] Aaron.Carlisle
#rb Chris.Gagnon
#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: jamie.dale
#ROBOMERGE-SOURCE: CL 5229258 via CL 5236098 via CL 5236204
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)
[CL 5254791 by jamie dale in Dev-VR branch]
This fixes crashes where they would take references to things like an actor within a world, and then the active editor world was changed (which verifies against GC reference leaks).
#jira UE-69150
[FYI] Michael.Noland
#rb Lauren.Ridge
#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: jamie.dale
#ROBOMERGE-SOURCE: CL 4987801 in //UE4/Release-4.22/... via CL 4987804
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)
[CL 5034266 by jamie dale in Dev-VR branch]
BlueprintInternalUseOnly functions are usually designed to be called via a K2 node wrapper, which may provide additional sanitization or data transformation (which Python is unaware of, so cannot mimic).
CustomThunk functions rely on popping Bytecode data off the stack, but Python calls functions natively so there is no Bytecode available and these functions will crash. We hope to address CustomThunk support in the future by synthesizing the correct Bytecode.
#jira UE-69818
#rb none
#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: jamie.dale
#ROBOMERGE-SOURCE: CL 4951261 in //UE4/Release-4.22/... via CL 4951262
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)
[CL 5026799 by jamie dale in Dev-VR branch]