Hey guys!
Unfortunately I get the error Operator bpy.ops.object.convert.poll() failed, context is incorrect
from bpy.ops.object.convert(target="MESH")
When using context overrides.
So do I have a misconception of what those overrides actually do?
Checking the API docs I cannot spot any mistakes in my code: https://docs.blender.org/api/current/bpy.types.Context.html
The script should duplicate some objects in a collection and then apply all of their modifiers.
I could use apply_modifiers() but that has other troubles for me, I really want to understand whats wrong with the context overrides.
Thanks in advance for any hints!
import bpy
for collection in [c for c in bpy.data.collections if 'M_' in c.name]:
for obj in [o.copy() for o in collection.objects if o.type == 'MESH']:
obj.data = obj.data.copy()
if obj.animation_data:
obj.animation_data.action = obj.animation_data.action.copy()
bpy.context.collection.objects.link(obj)
with bpy.context.temp_override(active_object=obj):
bpy.ops.object.convert(target="MESH")
each operator uses its own unique poll function whose criteria can vary wildly. you’ve overridden the active object for your temp context, but there’s something else the object.convert op is looking for that is not overridden. unfortunately the only way to know for sure what needs to be overridden is to look at the source for the poll function in question. I have a detailed post on how I go about doing this over on devtalk.
regarding selected objects- keep in mind that the context structure has many areas for selected objects you have to override in some cases. for example:
object, active_object, selected_objects, selected_editable_objects
the later two being lists of objects. anecdotally I can tell you that overriding the four I just mentioned will work, since I also use object.convert in one of my scripts and those are the ones I had overridden.
Couldn’t you do this instead? I rarely do anything that requires it so perhaps there’s a limitation I’m unaware of. In this case it was to bool something.
yeah, technically copying the evaluated mesh would do the same thing- i’ve found that copying large meshes in this way can be a bit crashy though so I use the operator for safety reasons.
edit: another limitation (I had to go back and look at my comments, because I remember running into a few different things with depsgraph)- if you’re trying to write a ‘one size fits all’ apply modifiers function that will work on any type of object (such as Curves for example), you’ll need to use object.convert on anything that is non-mesh since the base object.type will remain a curve and you’ll get an error when you try to assign the copied depsgraph data to the original object. that’s more of an esoteric edge case specific to my usage, but probably worth pointing out in case somebody else runs into the same thing.
I’ll have to make a note of that.
I vaguely recall using singledispatch to handle different types cleanly but anything involving context is rarely necessary for what I do and always a last resort (usually out of stubbornness).
I believe it’s necessary to explicitly copy the evaluated mesh as a reference won’t survive long. Perhaps that’s the issue you ran into previously.
As this is more of a smart workaround to my initial question, I think the closest answer to the thread title is given by testure, so im gonna mark this response as a solution. Both seem to work!
Smells like a bug. I don’t have a developer environment on this computer, but according to x64dbg Blender is dereferencing a nullpointer in the function library_foreach_ID_link in lib_query.c when an object is linked to the scene.
For now it’s probably best to create a new empty mesh, then use bmesh to join the converted meshes into it, and just not deal with the copied evaluated objects directly.
Just to put it out there. Regarding the original question about object.convert - blender devs confirmed that currently it’s not possible to run it by specifying object with temp_override.
More about it here - https://projects.blender.org/blender/blender/issues/93188
I don’t think so, objs[0].select_set(True) defeats the whole purpose of the override, which is to not have to worry about object selection or active object. If you remove this line, it will not work anymore.
Changing selection state in a script can have unintended consequences. It will also make Blender unresponsive if you have tens of thousands of objects.