-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Plugin Logic Proposal #75
Conversation
src/QuiltiX/qx_plugin.py
Outdated
logger = logging.getLogger(__name__) | ||
|
||
class QuiltiXPlugin(): | ||
def __init__(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More fields can be added. It's simple for now with a key and implementation.
src/QuiltiX/qx_plugin.py
Outdated
|
||
def install_plugins(self): | ||
self.plugins = [] | ||
plugin_roots = [os.path.join(self.root, "plugins"), os.getenv("QUILTIX_PLUGIN_FOLDER", "")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gives an initial package and env var location.
src/QuiltiX/qx_plugin.py
Outdated
spec.loader.exec_module(module) | ||
|
||
# Call module install_plugin function if it exists | ||
if hasattr(module, "install_plugin"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A specific entry point is looked for.
except ImportError: | ||
logger.error("materialxjson.core not found") | ||
|
||
class QuiltiX_JSON_serializer(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no encapsulation of the core code as is the case with the current way of just overriding the entire application.
Hey Bernard! Sorry for not getting to this earlier. |
Hi @manuelkoester , |
Hey Bernard! I've gone ahead and changed the plugin system quite a bit. It is now using I also changed the discovery a tiny bit, which allows for setting multiple paths in the |
src/QuiltiX/qx_plugin.py
Outdated
class QuiltixHookspecs: | ||
@hookspec | ||
def after_ui_init(self, editor: "quiltix.QuiltiXWindow"): | ||
""" | ||
:param editor: The QuiltiX Window | ||
""" | ||
|
||
@hookspec | ||
def before_ui_init(self, editor: "quiltix.QuiltiXWindow"): | ||
""" | ||
:param editor: The QuiltiX Window | ||
""" | ||
|
||
@hookspec | ||
def before_mx_import(self): | ||
""" | ||
This allows any code to execute before MaterialX gets imported | ||
""" | ||
|
||
@hookspec | ||
def before_pxr_import(self): | ||
""" | ||
This allows any code to execute before OpenUSD's pxr gets imported | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These hookspecs specify the hooks, and what arguments the individual hooks get supplied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar comment to the before_mx_import
. Seems like it would be better to have as an after_pxr_import
. Also maybe it's better to call this after_usd_import
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I prefer pxr
, as AFAIK it is responsible for setting the env vars and startup. Also Usd
at least in this context is just another submodule of pxr next to things like Gf
, UsdGeom
and the likes.
src/QuiltiX/qx_plugin.py
Outdated
if hasattr(module, PLUGIN_ID_FUNCTION_NAME): | ||
plugin_id_function = getattr(module, PLUGIN_ID_FUNCTION_NAME) | ||
plugin_id_name = plugin_id_function() | ||
self.register(module, plugin_id_name) | ||
logger.info(f"Registered plugin '{plugin_id_name} at {module.__file__}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now plugins are required to provide the plugin_id
function in their plugin.py
so it gets picked up by the Manager.
plugin_manager.load_plugins_from_environment_variable() | ||
plugin_manager.add_hookspecs(qx_plugin.QuiltixHookspecs) | ||
|
||
plugin_manager.hook.before_mx_import() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how the hooks actually get triggered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be more useful to have an after MaterialX imported then the plugin can use the loaded version and if desired. Could cut down on overhead and also enhance consistent usage of the same runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These named this way so users can theoretically still modify environment variables before
MaterialX or the likes get initialized and read from them.
But yeah it would probably make sense to also add the after_
versions.
@qx_plugin.hookimpl | ||
def after_ui_init(editor: "quiltix.QuiltiXWindow"): | ||
editor.json_serializer = QuiltiX_JSON_serializer(editor, constants.ROOT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how and where we use the after_ui_init
hook that get's triggered by the Manager.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice and interesting approach. Feels very clean!
try: | ||
import materialxjson.core as jsoncore | ||
except ImportError: | ||
logger.error("materialxjson.core not found") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This plugin isn't usable without jsoncore. Would it make sense to stop loading the plugin at this point and somehow disable it after logging the error?
Some logic for plugins to define requirements, which need to be met before the plugin can be loaded, could be handy. This could be used to define plugins, which only work on a specific OS or with a specific MaterialX versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @RichardFrangenberg
There used to be a validity check before the refactor. I've added this back in with an explicit `is_valid()1 check on the plugin. It leaves it up to the plugin to decide where it can work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed it so a plugin doesn't need to implement is_valid
, but it can choose to do so.
Hey Bernard! I hope it is okay if I push over your changes with some of the things that I have started yesterday evening while chatting with Richard. It will functionally be very similar to yours however! |
@kwokcb @RichardFrangenberg please feel free to leave any comments/feedback! Should be nearly done. The tiny test in |
@manuelkoester Thanks for adding the pre and post. Looks good to me. |
…upting a json load operation
Nice! Works perfectly! I'll now merge this in. Thank you very much for the first implementation @kwokcb . There's very little we had to add here <3 |
Proposal
This is an initial proposed design for allow users to create compartmentalized plug-ins without having to override the main Qt application.
Design
QuiltiXPlugin
class. For now this has the minimal of:QuiltiXPluginManager
which is just a list ofQuiltiXPlugin
.Discovery
plugin.py
file which contains a module with ainstall_plugin
entry point.plugins
folder under the root of the Python distribution.QUILTIX_PLUGIN_FOLDER
Example
materialxjson
folder under a newsample_plugins
folder.@manuelkoester, @RichardFrangenberg : Let me know what you think of this. It's naturally very basic to start with.
If something like this is reasonable, I'd like to move on to adding glTF support this way. Thanks!