1
$\begingroup$

I can start an operator with file selection by adding "INVOK_DEFAULT" to it's call, e.g. bpy.ops.wm.alembic_import('INVOKE_DEFAULT') (without it, it will raise an exception RuntimeError: Error: No filepath given).

But how do I add code after this operator has finished? It would be needed to process just impored model without need for additional input from user. E.g. model is imported with bpy.ops.wm.obj_import() and then I need to setup it's materials in a certain way.

Or before when file is already choosen? Can be useful since at this point we'll know the filepath and can start importing any other related assets.

If we just add line after operator('INVOKE_DEFAULT') it will be exeuted after file selection window appears, not after the operator has finished the execution:

import bpy
print('before invoke')
bpy.ops.wm.alembic_import('INVOKE_DEFAULT')
print('after wm.alembic_import invoke')
print('runs after file selection window was created')

PS I know that I can create new operator with file selection and call the operator with bpy.ops.wm.alembic_import(self.filepath) like described here but I'm looking for more general solution - I don't want to mirror all operator's import properties in my operator, want to be able to call multiple INVOKE_DEFAULT operators.

$\endgroup$
3
  • $\begingroup$ Something like this? blender.stackexchange.com/questions/212545/… $\endgroup$
    – Psyonic
    Commented Dec 2, 2023 at 7:49
  • $\begingroup$ @Psyonic it's the same approach I've mentioned in post scriptum - I'd need to mirror all the during import paramaters of bpy.ops.import_mesh.stl in mine operator and it doesn't allow calling multiple INVOKE_DEFAULT operators one after another. $\endgroup$ Commented Dec 2, 2023 at 8:56
  • $\begingroup$ Hmmm... OK, just a dumb thought... could you wait until the object count increases using len(bpy.context.view_layer.objects.items())?? $\endgroup$
    – Psyonic
    Commented Dec 2, 2023 at 9:11

1 Answer 1

0
$\begingroup$

So, there's probably a MUCH smarter way to do this, but this seems to work...
The one caveat is that you will need your operator to run as modal, but this is quite easy to do.

In your def invoke() function:

self.done = False
self.count = len(bpy.context.view_layer.objects.items())
print("count: ", self.count)

print('before invoke')
bpy.ops.wm.alembic_import('INVOKE_DEFAULT')
print('after wm.alembic_import invoke')
print('runs after file selection window was created')
return {"RUNNING_MODAL"}

Then in your def modal() function:

if len(bpy.context.view_layer.objects.items()) > self.count and self.done is False:
    print("DONE!!")
    self.done = True

This runs any code placed in this if statement once the object count is greater than the original object count and also remains in your modal routine. From my testing the object count only increases AFTER the import function has finished and the new object has been added to the scene.

I have no doubt there is a better way to do this, maybe by subscribing to the message bus or some kind of handler but this is very fast and from my rudimentary testing it seems to work...

$\endgroup$
1
  • $\begingroup$ I think it'll work. Though it won't allow to run multiple INVOKE_DEFAULT operators too. $\endgroup$ Commented Dec 3, 2023 at 13:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .