I'm try to create python script to add,connect and Sync the node finally do the rendering using python in blender. I'm added a node using the python command but i can't able to connect and sync the node using scripting. Can you give some suggestions to solve this problems
Hi Sebastian, hope you are well, the problem you have is that this operator is firstly part of our add-on that we have not documented or open sourced.... yet! :) So there is no interface defined for use in other scripts at the moment, we're working on an API to our distribution system as well.
However your use case seems to be triggering a render from a script if I understand you right? So, secondly, the operator you are calling has thrown this error because you didn't invoke it. There is a handler added to the operator object in the call to invoke, since you call the operator in your script with no arguments at all, this tells blender to run the operator with its defaults which is to simply run the execute method.
The execute method expects there to be a handler (the 'x' in your error traceback) and thus the error occurs and an exception is thrown. So, I think all you'd need to do to get your script to work properly, is to call the operator with the positional argument 'INVOKE_DEFAULT' which tells blender to run the operator's invoke method first.
The patter for the call should be something like bpy.ops.crowdrender.render('INVOKE_DEFAULT').
FYI, your second attempt works because you've added the button to a panel, which will call the invoke method by default, hence the different behaviour.
Hope this helps and please do share with us what your script is about! We rarely get people wanting to script using our addon so of course we'd like to know more about this use of the addon and what documentation or API would be helpful!
Thank you for your explanation! Using the argument 'INVOKE_DEFAULT' did work :) but introduces new challenges.
My script is about placing a certain number of cameras into a blender scene. Next, I want to iterate over all cameras and have crowdrender render the corresponding frame for each camera and write each frame as png to my hard drive.
Using the argument 'INVOKE_DEFAULT' causes crowdrender to start the render process in a non-blocking way which causes troubles:
Since I am iterating over all cameras calling bpy.ops.crowdrender.render('INVOKE_DEFAULT') for each iteration blender does not wait for the previous render call to finish and interrupts by starting the current iteration's render call.
Example:
Image only one camera present in the scene. Iterating over only one camera and starting a non blocking render thread just works fine!
Now, let's say we have two cameras. Beeing in the first iteration and calling bpy.ops.crowdrender.render for the first time it will start crowdrender's render pipeline. Meanwhile the script continues (non-blocking way) proceeding with next iteration and calling bpy.ops.crowdrender.render for the second time and interrupting the previous process.
Calling blenders bpy.ops.render.render operator without 'INVOKE_DEFAULT' present in its arguments causes blender to block the script until rendering is complete what solves my problem.
Does something similar exist for the bpy.ops.crowdrender.render operator?
@sebastian.hartwig Calling our operator without the invoke argument will not work, its necessary in the current API.
However, you can probably do this, with a bit of fiddling. Here's the approach.
1. Blender allows you to detect the completion of a render. So you can actually register a function or method that will be called once a render ends, either with CR or with any other engine you choose. Blender allows you to add your method to a list of handlers that will be called for a specific set of events. You can find these handlers in bpy.app.handlers. In particular there is the bpy.app.handlers.render_complete list, if you append a function or method to this list, it will be called when any render finishes.
2. Adding a method to the above list won't solve your problem with Crowdrender though. At least not yet. The problem here is that we've, rightly or wrongly, decided to use a system that allows you to use cycles or eevee while you are working, then you just hit render still or animation on our add-on's crowdrender panel when you want to render. Crowdrender then reads whatever engine you have selected at the time and then switches that to a hidden placeholder engine that we use to manage the render process from your blender session. Once the render is complete, we try to switch it back again.
And for you, this switching back will be a problem you'll need to negotiate. If you simply added a method or function to the render_complete handler and tried to call bpy.ops.crowdrender.render.render, then you'd find that after you did this, the render engine selected would be changed, and this would break your rendering.
The way around this is to add the handler, then call a special operator which you write to wait until the render engine is switched back and you can render again safely with Crowdrender. You can easily write an operator that can do this since all operators can have a modal method which is called periodically. For example...
classmy_timed_operator(bpy.types.Operator):
def invoke(self, context, event):
wm = context.window_manager
#add a timer, run every 32 ms
self.timer = wm.event_timer_add(0.032, window = context.window)return{'RUNNING_MODAL'}
def modal(self, context, event):if event.type =='TIMER':
#only trigger on timer, not events like mouse move, click, etc
if context.scene.render.engine =='CYCLES':
bpy.ops.crowdrender.render.render('INVOKE_DEFAULT')return self.execute(context)return{'PASS_THROUGH'}
def execute(self, context):
wm = context.window_manager
wm.event_timer_remove(self.timer)
Once you have registered something similar to this, then you can call it from a handler like so...
def render_comp_handler(*args):
bpy.ops.your_operator('INVOKE_DEFAULT')
#now simply register this handler
bpy.app.handlers.render_complete.append(render_comp_handler)
3. One thing remains, this is to make sure you keep track somewhere of the cameras you have rendered so you don't just render the same one over and over and over, which you could easily do if you just coded the above and set it running, the setup I describe here would probably render forever!
So, you need to have some way of keeping track of when to stop and some way of controlling the switching between different cameras as you desire.
How you achieve this is up to you. The trick will likely be in having a global variable or property somewhere in blender that you can update after each render so the next render is properly configured.
For this I personally favour using a list of 'things to render' with each thing being taken off the list until all are completed. This way the list gets shorter as each item is done and the process stops once there are no more items in the list.
So, I hope this has been helpful, and I wish you the best of luck! Stop by again if you need help :)
Hello :)
Is there an update regarding API support? I am asking because I would like to control the crowdrender via python. In detail, can I somehow invoke the Render Still operator by a python command, like bpy.ops.crowdrender.render()
Thank you!
You can call our operator to kick off rendering, this operator is
bpy.ops.crowdrender.render
Calling this operator without any arguments will render a still, if you want to render an animation then you can call it with a single argument, 'animation' set to True.
File "/Users/jamescrowther/Desktop/Crowdrender/cr_compile/releases/multi OS releases/blender_addon/2.80/crowdrender/src/cr/ui_operators.py", line 3822, in execute
ValueError: list.remove(x): x not in list
I have tried the following and it works. But that solution does not satisfy my task:
Adding the crowdrender.render operator to my UI Panel like so
When I click this "My Render Still" button the rendering works! But as stated, that is not the use case I try to solve. I want to call the "Render Still" operation from a script and not by adding a button and clicking this button by myself.
Hi there HiYang, we're planning on building an API to do this, and making the current addon to blender open source. This is no where near ready yet though. It might be possible with v014 but I'd have to look into it as a special case since there's no API in place as yet.
We're designing a cleaner version of our system that will have our system available as an API and the blender addon will use the API. Right now they're to tightly bound to each other to do this so we're working to separate this.
Hi,
I'm try to create python script to add,connect and Sync the node finally do the rendering using python in blender. I'm added a node using the python command but i can't able to connect and sync the node using scripting. Can you give some suggestions to solve this problems
Hi Sebastian, hope you are well, the problem you have is that this operator is firstly part of our add-on that we have not documented or open sourced.... yet! :) So there is no interface defined for use in other scripts at the moment, we're working on an API to our distribution system as well.
However your use case seems to be triggering a render from a script if I understand you right? So, secondly, the operator you are calling has thrown this error because you didn't invoke it. There is a handler added to the operator object in the call to invoke, since you call the operator in your script with no arguments at all, this tells blender to run the operator with its defaults which is to simply run the execute method.
The execute method expects there to be a handler (the 'x' in your error traceback) and thus the error occurs and an exception is thrown. So, I think all you'd need to do to get your script to work properly, is to call the operator with the positional argument 'INVOKE_DEFAULT' which tells blender to run the operator's invoke method first.
The patter for the call should be something like bpy.ops.crowdrender.render('INVOKE_DEFAULT').
FYI, your second attempt works because you've added the button to a panel, which will call the invoke method by default, hence the different behaviour.
Hope this helps and please do share with us what your script is about! We rarely get people wanting to script using our addon so of course we'd like to know more about this use of the addon and what documentation or API would be helpful!
Hope this helped?
James
Hello :) Is there an update regarding API support? I am asking because I would like to control the crowdrender via python. In detail, can I somehow invoke the Render Still operator by a python command, like bpy.ops.crowdrender.render() Thank you!
Best Regards.
Hi there HiYang, we're planning on building an API to do this, and making the current addon to blender open source. This is no where near ready yet though. It might be possible with v014 but I'd have to look into it as a special case since there's no API in place as yet.
We're designing a cleaner version of our system that will have our system available as an API and the blender addon will use the API. Right now they're to tightly bound to each other to do this so we're working to separate this.
All the best!