I’ve added a widget to the publisher dialog that I want to query the state of prior to running the collector.
Is it possible to access the app ui widgets from the collector hook?
I imagine something like self.parent.ui.my_widget
should work?
The AppDialog and GUI by default is obscured from the collector and publish plugin hooks. Here are some quick and dirty approaches:
- You can hack it by creating your own
pre_publish
hook that overrides the defaultshow_dialog
behaviour and storing the created, non-model dialog asself.parent.ui
i.e.class PrePublishHook(HookBaseClass): def validate(self): app = self.parent app.ui = None display_name = app.get_setting("display_name") if super(PrePublishHook, self).validate(): # start ui if app.modal: app.engine.show_modal(display_name, app, AppDialog) else: app.ui = app.engine.show_dialog(display_name, app, AppDialog) else: app.logger.debug( "%s validate returned False -- abort publish." % app.pre_publish_hook.__class__.__name__ ) return False # Used our own launch logic, so always return False to abort original logic
- Alternatively, you can try exploring the hook’s
self.parent.engine.created_qt_dialogs
to see if the Publish Dialog is in there somewhere
A more engineered suggestion will be to fork the tk-multi-publish2
app repository and setup a ui
property (or dialogs
if supporting multiple UIs) in app.py
.
Hey. Number one method is not going to work as you don’t have “AppDialog” variable and in order to feed it to the prepublish hook you need to correct the code of the app and take it over anyway.
Number two can find the dialog, but not during the start because it is constructed only after all the collectors and plugins past through the accept phase. So there is no place to put in the code for getting the app dialog. That’s a pity because take over the whole app only because the dialog is so small and you want to change the initial size is a bummer.
I even tried to initiate an additional thread inside the collector, that would search for the newly opened dialog with the name “Publish” and resize it if found. And it works, but only once. The second time you open publisher, 3ds max just crashes… So I had to completely give up on that idea.
that’s the code for the collector
def process_current_session(self, settings, parent_item):
"""
Analyzes the current session open in Max and parents a subtree of
items under the parent_item passed in.
:param parent_item: Root item instance
"""
resize_dialog_thread = threading.Thread(target=_resize_dialog, args=(self,))
resize_dialog_thread.setDaemon(True)
resize_dialog_thread.start()
blablabla
that’s the function for the thread
def _resize_dialog(the_hook):
"""
A method to resize the dialog.
:param the_hook: The base hook to get the engine and the dialog.
"""
for _ in range(15):
time.sleep(0.5)
the_dialogs = the_hook.parent.engine.created_qt_dialogs
for the_dialog in the_dialogs:
if the_dialog.ui.app_name.text() == 'Publish':
the_dialog.resize(1100, 900)
return
Ah yes, my mistake for not explaining the AppDialog
sub-class hack properly.
Here’s what a better pre_publish.py
hook would look like
-
At the top of the file, create a factory method that will construct a sub-class of
AppDialog
def subclassed_app_dialog(AppDialog): class MyAppDialog(AppDialog): """Custom code added in this scope.""" return MyAppDialog
-
Then later on in the hook, call the factory with the original
AppDialog
class imported from hook’sself.import_module("tk_multi_publish2.dialog")
class PrePublishHook(HookBaseClass): def validate(self): app = self.parent app.ui = None display_name = app.get_setting("display_name") if super(PrePublishHook, self).validate(): dialog = self.import_module("tk_multi_publish2.dialog") MyAppDialog = subclassed_app_dialog(dialog.AppDialog) # start ui if app.modal: app.engine.show_modal(display_name, app, MyAppDialog) else: app.ui = app.engine.show_dialog(display_name, app, MyAppDialog) else: app.logger.debug( "%s validate returned False -- abort publish." % app.pre_publish_hook.__class__.__name__ ) return False # Used our own launch logic, so always return False to abort original logic
hey, thank you so much for the tip!
I ended up with this code
class PrePublishHook (HookBaseClass):
"""
This plugin is made to resize the main publish dialog as it is too small.
"""
def validate(self):
app = self.parent
app.ui = None
display_name = app.get_setting("display_name")
dialog = app.import_module("tk_multi_publish2.dialog")
# start ui
if app.modal:
app.engine.show_modal(display_name, app, dialog.AppDialog)
return
app.ui = app.engine.show_dialog(display_name, app, dialog.AppDialog)
the_app_ui = app.ui.ui
qdialog = app.ui.parent().parent().parent()
qdialog.resize(1200,900)
qdialog.move(350,50)
the_app_ui.splitter.setSizes([600,600])
return False # Used our own launch logic, so always return False to abort original logic