There's a new API method in the next daily build of H18.5 that should do what you need. It gives you a way to run a Python function on the main thread, and optionally wait for the function to complete. You can use it anywhere in Python as part of a PDG cook, so in a Python Script or a Python Processor's onCookTask callback, for example. The method will let you pass a function and a list of arguments, which will get queued up and run serially on the main thread. That means, for example, you could use it to open a Qt dialog from a Python Script and then wait for a response:
from hutil.Qt import QtWidgets
def show_dialog(message, text):
dialog = QtWidgets.QMessageBox()
dialog.setWindowTitle(message)
dialog.setText(text)
dialog.addButton(QtWidgets.QMessageBox.Yes)
dialog.addButton(QtWidgets.QMessageBox.No)
return dialog.exec_()
result = work_item.node.scheduler.runOnMainThread(
True, show_dialog, "Cook PDG Message", "Should the work item succeed?")
if result == QtWidgets.QMessageBox.No:
raise pdg.CookError("Item Failed due to user input")
The docs for the new API method will also be in the build tomorrow, but to give a brief summary the
pdg.Scheduler class has a new
runOnMainThread method that can run an arbitrary Python function on the main thread. The first argument indicates whether you want to wait for the function to run -- if you need access to the returned value from the function, then you'll have to wait for example. The second argument is the Python function or callable object, and any additional arguments after that are passed to the function when it gets called.
This is similar to the existing
hdefereval available in HOM, but it's managed by the PDG cook instead. That means if you cancel a PDG cook any unstarted main thread tasks will also be dropped from the queue. It will also work in a headless Houdini session, for example when cooking a TOP graph from hbatch or hython, as long as the headless graph cook is configured to block instead of cook in the background.
It's using the same internal mechanism that the built-in in process scheduler uses. Note that its still not possible to write a custom in process scheduler, which we do plan to add support for as well. That's a larger change though, and I think the new
runOnMainThread method is enough to solve your use case on its own.