How to understand symbols of some spcial case ?
-
Hello everyone,
Question
I get some strange words from sdk and never found what they means, how can I get some info more spcificly?
e.g. I try to check rendering states of my batch render ,when batch render come with a error then , alert me rather than waste all night time, some I think I can get a state list of render queue, when error happens , take an alert and never warning this element this time . but when I test the state , it seems
RM_ERROR2
is the only one , I delete some texture to test a warning document ,RM_ERROR
still not worked , How can I get this symbols meaning ?This problem also heppened when some undo or some symbols have a number ending
by the way , I think GetEnableElement document is wrong ?
Cheers
-
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
andRM_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 isRM_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 toBatchRender.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,
FerdinandResult:
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()
-
@ferdinand Thanks for that!
I think
BatchRender.GetJsonJobs
do a great job but a little pitty that the velue of the json is not use an "int" , so when I want to support Chinese users , it returns'status': '在队列中
like this , so I think it a little bit limitation for not a native English users.And the
RM_ERROR
andRM_ERROR2
code shows most I want , I belive a lot of symbols has teh sameXXXX
andXXXX2
situation,but most document didn't have any infomations .And a little questions with "Batch Render" but not the symbol, I don't sure should I post in another topic:
When I use
IsRendering
to spy the render queue ,if A and B is switch rendering status ( aka , A is finishing , and B is just starting ).this few time would break thewhile
and return a bad value not I want. How can I fix this?batchRender: BatchRender = c4d.documents.GetBatchRender() while batchRender.IsRendering(): c4d.StatusSetText(f"Rendering....") time.sleep(5)
Cheers~
-
Hello @dunhou,
it returns 'status':
在队列中
like this , so I think it a little bit limitation for not a native English users.status
is the HTML-encoded Unicode string for the characters '在队列中'.&#
is how Unicode is encoded in HTML, and xNNNN is the Unicode and;
is the delimiter. You can either decode them manually usingstr
andbytes
or just use the handyhtml.unescape
.import html status: str = "在队列中" print (html.unescape(status))
And the RM_ERROR and RM_ERROR2 code shows most I want , I belive a lot of symbols has teh same XXXX and XXXX2 situation,but most document didn't have any infomations.
Yes, we are aware. We fix them when we are pushed onto errors, but cannot just fix them all at once. You must understand that Cinema 4D has code which is up to two decades old, so documentation can get out of whack over time.
When I use IsRendering to spy the render queue ,if A and B is switch rendering status ( aka , A is finishing , and B is just starting ).this few time would break the while and return a bad value not I want. How can I fix this?
I assume you are talking here about the case that you have a render queue with two jobs A and B. And it seems to be the case that there is a brief moment when A has already finished B has not yet started, where
batchRender.IsRendering()
returnsFalse
, although there is still an upcoming rendering.Your solution with time.sleep seems sort of fine, but error prone for cases where initializing the new rendering takes more than five seconds. I would simply write something which checks if there are still pending jobs (
c4d.RM_QUEUE
) in the queue in addition to checking if the batch renderer is actively rendering.Cheers,
Ferdinand -
@ferdinand Thanks for your help.
I did search on web and find the Unicode string, and Chinese characters is so much complicated ,when most user use Chinese for the GUI language, Maybe sometime the translation of the world "在队列中" witch means "in the queue" in English has changed ( I belive now Chinese translation is response to IHDT so it won't randomly changed). That is not a big problem but maybe a little "uniform" with the "ID"
And the "brief moment" is I don't sure why does it happend. In another word ,I think the initializing render process can be also called "rendering" . so it is a bit of counterintuitive for me , maybe I should add an additional check to make sure the spying will not break while the brief.
Cheers~