Hi all,
I’m new to UE but have been tasked with setting up remote rendering via the Movie Render Queue, in particular overriding the Render (Remote) button. The ultimate goal is to allow a remote rendering farm to be set up and multiple jobs rendered from the queue. For the moment however, I’m just concerned with ensuring I can get a job rending in a separate UE window via the button.
First off, this is being done in UE 4.27, however likely to be moving to UE 5 at some point.
I have based a simple script off the UE sample code (MoviePipelineExampleRuntimeExecutor.py). The first step is to ensure I can override the button, which I have been able to do. I have also been able to get the data for the queue that has been set manually in the Movie Render Queue window.
However, the script keeps falling down when trying to create a new MoviePipeline object:
self.activeMoviePipeline = unreal.new_object(unreal.MoviePipeline, outer=self.get_last_loaded_world(), base_type=unreal.MoviePipeline)
The problem appears to be that self.get_last_loaded_world() returns null, as this is the error I keep seeing. This is despite, according to the docs, outer may be unspecificed for this function. If I try to specifically set the outer via the following code, UE crashes:
world = unreal.EditorLevelLibrary.get_editor_world()
self.activeMoviePipeline = unreal.new_object(unreal.MoviePipeline, outer=world, base_type=unreal.MoviePipeline)
I’m aware that the example UE code was created to be run from the commmand line. I assume that for my implementation there are changes that need to be made to allow the code to be run directly by clicking the Render (Remote) button in the Movie Render Queue window. Does anyone know how the code (in full below) would need to be altered to allow this?
import unreal
@unreal.uclass()
class ExecutorWindfirm(unreal.MoviePipelinePythonHostExecutor):
def _post_init(self):
unreal.get_default_object(unreal.MoviePipelinePythonHostExecutor).executor_class = self.get_class()
self.activeMoviePipeline = None
# overrides the behavior of the Render (Remote) button
projectSettings = unreal.get_default_object(unreal.MovieRenderPipelineProjectSettings)
projectSettings.default_remote_executor = self.get_class()
@unreal.ufunction(override=True)
def execute_delayed(self, inPipelineQueue):
# Get the pipeline queue
subsystem = unreal.get_editor_subsystem(unreal.MoviePipelineQueueSubsystem)
pipeline_queue = subsystem.get_queue()
# get just the first job in the queue for now
newJob = pipeline_queue.get_jobs()[0]
# create the pipeline
world = unreal.EditorLevelLibrary.get_editor_world()
self.activeMoviePipeline = unreal.new_object(unreal.MoviePipeline, outer=world, base_type=unreal.MoviePipeline)
# Register to any callbacks we want
self.activeMoviePipeline.on_movie_pipeline_finished_delegate.add_function_unique(self, "on_movie_pipeline_finished")
# initiatize pipeline
self.activeMoviePipeline.initialize(newJob)
# This declares a new UFunction and specifies the return type and the parameter types
# callbacks for delegates need to be marked as UFunctions.
@unreal.ufunction(ret=None, params=[unreal.MoviePipeline, bool])
def on_movie_pipeline_finished(self, inMoviePipeline, bSuccess):
# this is just from the UE sample code
unreal.log("Finished rendering movie! Success: " + str(bSuccess))
self.activeMoviePipeline = None
self.on_executor_finished_impl()