Skip to content
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

Environment plugin #133

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

davidlatwe
Copy link
Collaborator

@davidlatwe davidlatwe commented Nov 18, 2020

So this is the implementation of #113.
And seems related to #63 ?

Anyway, here we go 🚀

What is environment plugin for ?

A way that allows to build additional interface that can be embedded into Allzpark for user to make additional choices, and parse those decisions into environment variables then pass into the application that is being launched.

For example, in production pipeline involved workflow, may require passing additional arguments as environment variables to application that is being launched. And those environment variables, like shot numbers, may change regularly so can't be easily fixed or defined in any Rez package.

The injected environment variables will be merged on top of parent environment, and user environment will be on top of them, like 👇🏼

user_env = {"foo": "bar"}
plugin_env = {"shot": "sh0100"}
parent_env = {"WINDIR": "C:\Windows", "USERNAME": "david", "PATH": "some/important;path"}
# merge
environ = parent_env.copy()
environ = dict(environ, **plugin_env)
environ = dict(environ, **user_env)
# launch application
context.execute_shell(parent_environ=environ)

How to make an environment plugin ?

By subclassing allzpark.plugin.EnvPluginBase, here is an example I made for Avalon 👉🏼 allzparkplugin.py

And register that subclass with allzparkconfig.environment_plugin

# allzparkconfig.py
def environment_plugin():
    import allzparkplugin
    return allzparkplugin.AvalonLauncher
The screen shot

image

How does an environment plugin interact with Allzpark and vice versa ?

EnvPluginBase.on_profile_changed

A slot that will be connected with Allzpark's profile changed signal, profile package object will be sent.
This does nothing by default, you need to re-implement this.

EnvPluginBase.on_application_changed

A slot that will be connected with Allzpark's application changed signal, application package object will be sent.
This does nothing by default, you need to re-implement this.

EnvPluginBase.validate

This will be called by Allzpark when an application is about to launch, the merged environment dict (not resolved environment) will be sent with the application package that is being launched.

This provide a chance to validate whether the environment is valid or not, and stop launching process if invalid.
And of course, this does nothing by default, you need to re-implement this.

EnvPluginBase.set_env

Inject additional environment variables.

EnvPluginBase.clear_env

Reset additional environment variables.

EnvPluginBase.reveal

Call this to show plugin dock widget. Could be used when input is required and need user to focus on the plugin page.

EnvPluginBase.to_console

Call this to show Allzpark console dock widget. Could be used when there are something happened and need user to know, if the plugin widget doesn't implement any notification function on itself.

EnvPluginBase.debug, info, warning, error

Send message into Allzpark console (only send message, not showing console)


And there it is, please let me know what you think :)

Comment on lines +234 to +235
btn_icon = (widget.icon if isinstance(widget.icon, QtGui.QIcon)
else res.icon(widget.icon))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems related to #83.
Currently, the res.icon only look for images inside allzpark.resources, so the custom plugin can only create their QIcon by itself, hence adding this extra if-statement.

@davidlatwe
Copy link
Collaborator Author

Here's another example plugin that is based on allzparkdemo

# allzparkconfig.py

def environment_plugin():
    from allzpark.vendor.Qt import QtWidgets
    from allzpark.vendor import qargparse
    from allzpark.plugin import EnvPluginBase

    class EnvFlavoring(EnvPluginBase):
        name = "Flavoring"

        def __init__(self, parent=None):
            super(EnvFlavoring, self).__init__(parent=parent)
            options = [
                qargparse.Enum("asset", items=["-", "toy", "cat"]),
                qargparse.Enum("shot", items=["-", "sh0100", "sh0200"]),
                qargparse.Enum("fps", items=["24", "30"]),
            ]
            widgets = {
                "options": qargparse.QArgumentParser(options)
            }
            layout = QtWidgets.QVBoxLayout(self)
            layout.addWidget(widgets["options"])

            widgets["options"].changed.connect(self.on_options_changed)

            self._widgets = widgets
            self._env = dict()

        def on_options_changed(self, arg):
            key = arg["name"]
            value = arg.read()

            if value == "-":
                self._env.pop(key, None)
            else:
                self._env[key] = arg.read()

            self.set_env(self._env)

        def on_application_changed(self, package):
            if package.name in ["maya", "blender", "nuke"]:
                self.set_env(self._env)
            else:
                self.clear_env()

        def validate(self, environ, package):
            if package.name in ["maya", "blender", "nuke"]:
                if any(k not in environ for k in ["asset", "shot"]):
                    self.to_console()
                    return "Shot/Asset not set."
                if any(environ[k] == "-" for k in ["asset", "shot"]):
                    self.to_console()
                    return "Shot/Asset not selected."

    return EnvFlavoring

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant