Hello @dunhou,
Thank you for reaching out to us. I am not fully sure if I understand you correctly here. I wrote a small example script (see end of posting), and BatchRender.GetElementStatus
does what I would expect it to do.
The problem here is the sparsely documented nature of RM_ERROR
and RM_ERROR_2
. Both statuses are of semi-private nature and are not really meant to convey anything else than that 'something' has gone wrong with a rendering. Internally, it is RM_ERROR
which conveys most of the 'interesting' error cases.
case RM_ERROR2:
switch (error)
{
case RM_ERR_OUTPUT: ...
case RM_ERR_OUTPUTMULTI: ...
case RM_ERR_TEXFAIL: ...
default: ...
}
case RM_ERROR:
{
switch (error)
{
case (Int32)RENDERRESULT::OUTOFMEMORY: ...
case (Int32)RENDERRESULT::ASSETMISSING: ...
case (Int32)RENDERRESULT::SAVINGFAILED: ...
case (Int32)RENDERRESULT::GICACHEMISSING: ...
case (Int32)RENDERRESULT::NOMACHINE: ...
case RM_ERR_DEL: ...
case (Int32)RENDERRESULT::ERRORLOADINGPROJECT: ...
case (Int32)RENDERRESULT::USERBREAK: ...
default: ...
}
}
But in the front-end, they are then lumped together, with both errors then having their combined meaning.
It is also important that not all statuses are conveyed in all contexts. The statues are meant to feed the render queue manager. So, when there is a problem with a job it will convey that before the queue is running. But once a job is queued in a running queue, it will not convey anymore missing textures, because in the logic of the render queue, it is now either "too late for that" or "intended by the user". So, when one wants to detect a problem with a job, one must also do that before running a queue. It might also be worth having a look at BatchRender.GetJsonJobs
in addition to BatchRender.GetElementStatus
, because the JSON data is more granular.
I agree that the short description for BatchRender.GetEnableElement
is misleading a probably was copied from .EnableElement
I will fix that in an upcoming release. Having a quick look at the C++ documentation, it also seems like the C++ and Python docs are not aligned.
Cheers,
Ferdinand
Result:
Before rendering:
----------------------------------------------------------------------------------------------------
Render job 0 (C:\Users\f_hoppe\Desktop\missing_texture.c4d) has the status: RM_ERROR2.
----------------------------------------------------------------------------------------------------
[{'added_to_queue': '01/03/2023, 13:47:14',
'estimated_time': '',
'filename': 'missing_texture.c4d',
'frame': '00:00:00 ',
'frames': [],
'id': '0',
'image': 'missing_texture.c4d',
'image_path': 'missing_texture_rendering',
'last_frame': '00:00:00 ',
'log': '',
'message': 'Error - Missing Files',
'outputheight': '720',
'outputwidth': '1280',
'progress': '0',
'render_started_on': '-',
'render_time': '00:00:00 ',
'status': 'Error',
'total_frames': '1',
'uuid': '19140F93-1025-4836-BDA0-8279BEB58999'}]
While rendering:
----------------------------------------------------------------------------------------------------
Render job 0 (C:\Users\f_hoppe\Desktop\missing_texture.c4d) has the status: RM_PROGRESS.
----------------------------------------------------------------------------------------------------
[{'added_to_queue': '01/03/2023, 13:47:14',
'estimated_time': '00:00:00 ',
'filename': 'missing_texture.c4d',
'frame': '00:00:00 ',
'frames': [],
'id': '0',
'image': 'missing_texture.c4d',
'image_path': 'missing_texture_rendering',
'last_frame': '00:00:00 ',
'log': '---File Information---\r\n'
'File Name : missing_texture.c4d\r\n'
'File Path : C:\\Users\\f_hoppe\\Desktop\r\n'
'---Render Data---\r\n'
'Render Settings : My Render Setting\r\n'
'Take : Main\r\n'
'Camera : Default Camera\r\n'
'Width : 1280\r\n'
'Height : 720\r\n'
'Film Aspect : 1.778\r\n'
'Pixel Aspect : 1\r\n'
'FPS : 30\r\n'
'From : 0\r\n'
'To : 0\r\n'
'Step : 1\r\n'
'---Save Information---\r\n'
'Path : \r\n'
'Depth : 8\r\n'
'Format : PNG\r\n'
'---Render Information---\r\n',
'message': '',
'outputheight': '720',
'outputwidth': '1280',
'progress': '0',
'render_started_on': '01/03/2023, 13:47:15',
'render_time': '00:00:00 ',
'status': 'In Progress',
'total_frames': '1',
'uuid': '19140F93-1025-4836-BDA0-8279BEB58999'}]
Code:
"""Demonstrates the different contexts and methods to retrieve render queue job item information with.
Must be run as a Script Manager script. Should be run on a scene which is missing assets, e.g., a
texture to have a meaningful output.
"""
import c4d
import os
import pprint
"""Translates render queue error symbols to their symbol string.
"""
RM_STATUS_SYMBOLS: dict[int, str] = {
c4d.RM_PROGRESS: "RM_PROGRESS",
c4d.RM_FINISHED: "RM_FINISHED",
c4d.RM_STOPPED: "RM_STOPPED",
c4d.RM_ERROR: "RM_ERROR",
c4d.RM_ERROR2: "RM_ERROR2",
c4d.RM_PAUSED: "RM_PAUSED",
c4d.RM_QUEUE: "RM_QUEUE",
c4d.RM_NONE: "RM_NONE",
}
doc: c4d.documents.BaseDocument # The active document.
def GetBatchRenderJobStatusesString(batchRender: c4d.documents.BatchRender) -> str:
"""Returns a pretty formatted string for all currently enqueued batch render jobs.
This will include disabled jobs.
"""
result: list[str] = []
for index in range(batchRender.GetElementCount()):
result.append(f"Render job {index} ({batchRender.GetElement(index)}) has the status: "
f"{RM_STATUS_SYMBOLS[batchRender.GetElementStatus(index)]}.")
return "\n".join(result)
def main() -> None:
"""Runs the example.
"""
# Get the document path and the batch renderer.
path: str = os.path.join(doc.GetDocumentPath(), doc.GetDocumentName())
if not os.path.exists(path):
c4d.gui.MessageDialog("Please save the document first.")
return
batchRender: c4d.documents.BatchRender = c4d.documents.GetBatchRender()
if batchRender.IsRendering():
c4d.gui.MessageDialog("Batch renderer is already rendering.")
return
# Put the new job in front of the queue.
batchRender.AddFile(path, 0)
# When #doc contains an #RENDERRESULT::ASSETMISSING error, it will bubble up as an #RM_ERROR here.
print ("Before rendering:")
print("-" * 100)
print(GetBatchRenderJobStatusesString(batchRender))
print("-" * 100)
pprint.pprint(batchRender.GetJsonJobs())
# Start the rendering.
batchRender.SetRendering(c4d.BR_START)
# But it will not here since in the logic of the render queue, it is "too late" to worry about
# that once the rendering is running.
print ("\nWhile rendering:")
print("-" * 100)
print(GetBatchRenderJobStatusesString(batchRender))
print("-" * 100)
pprint.pprint(batchRender.GetJsonJobs())
if __name__ == '__main__':
main()