Maya - userSetup.py

Hi,

I want to have control over userSetup.py when users launch tk-maya.
I want all workstations to read the same unique userSetup.py inside of sgtk config, so that users can customize their own userSetup.py files if they want.

I see there is already install\app_store\tk-maya\v0.9.7\startup\userSetup.py that looks excatly like what I want, but I don’t understand how the file is linked to sgtk config as I can’t find any hook key associated to this file in tk-maya.

I imagine I can also use tk-multi-launchapp\before_app_launch.py, but trying to add settings.tk-multi-launchapp.tk-maya to tk-multi-launchapp breaks my whole config as I don’t know what windows_path, linux_path and mac_path keys are supposed to be.

Can you point me to the right direction here? Using userSetup.py would be the best option I think.

Thanks.

3 Likes

Hi Ben

So first thing to say, is you shouldn’t modify the install\app_store\tk-maya\v0.9.7\startup\userSetup.py file. This is there purely for Toolkit to handle bootstrapping of the engine. You should use your own separate userSetup.py.

The before_app_launch.py hook sounds like the right way to go. You can add the path to your chosen userSetup.py file, by appending it to the PYTHONPATH.

You can use the following utility method to append a path to the env var:

sgtk.util.append_path_to_env_var("PYTHONPATH", path_to_your_usersetup_file)

If you’re bundling your custom userSetup.py file in with the config, you can access the hooks folder in the config by running the following from the hook:

self.disk_location

https://developer.shotgunsoftware.com/tk-core/core.html#sgtk.Hook.disk_location
Then you could modify that path to get to a different folder if needed.

Best
Phil

1 Like

Hi Philip,
Thanks for your answer.

I wouldn’t dare modify a file in the install/ folder! That’s my exact problem: I did not know how to telle sgtk to load {config}/tk-maya/userSetup.py

I’ll try appending userSetup.py path to PYTHONPATH. I did not know maya would launch any userSetup.py in this environment variable at startup.

Is
sgtk.util.append_path_to_env_var("PYTHONPATH", path_to_your_usersetup_file)
the exact same thing as
os.environ["PYTHONPATH"] or is this a sgtk special PYTHONPATH?


Concerning before_app_launch.py, I’m currently trying to make this work but have problems with implementing the settings in tk-maya:

:diamonds: copy before_app_launch.py to {config}/tk-multi-launchapp/before_app_launch.py
:diamonds: add those lines to tk-multi-launchapp.yml:

settings.tk-multi-launchapp.maya:
engine: tk-maya
location: "@apps.tk-multi-launchapp.location"
hook_before_app_launch: "{config}/tk-multi-launchapp/before_app_launch.py"

:diamonds: add tk-multi-launchapp: "@settings.tk-multi-launchapp.tk-maya" to the apps part of your different environments in tk-maya.yml

I’m not exactly sure I’m right there as this gives me errors when launching SG Desktop, but I think that’s the logic here?

TankError: Include error. Could not resolve references for L:\_tech\sgtk_sandbox\config\env\.\includes\settings\tk-maya.yml: Undefined Reference settings.tk-multi-launchapp.tk-maya!

2 Likes

Yes, it’s the same env var, it’s just a convenience method, for taking the current PYTHONPATH value and adding a new string to the end of it separated by the path separator. It runs this code essentially:

You could do it your self, but just make sure you don’t overwrite the current PYTHONPATH value as Toolkit won’t bootstrap, you must append to it.

I’m guessing you created the settings.tk-multi-launchapp.maya: block? You shouldn’t normally need to do this. I posted on the other thread you replied to with the instructions on how to add the hook:

Though technically the error you are getting is that your tk-maya.yml doesn’t know where to find the settings.tk-multi-launchapp.maya: settings block, as you probably haven’t included the tk-multi-launchapp.yml in the includes section of the file. However I think this is the wrong approach anyway, so I would follow the steps in the other post and see if that works for you. (And remove changes you made to the tk-maya.yml and tk-multi-launchapp.yml.)

Hope that helps, let me know if anything is not clear and I’ll try to clarify!
Cheers
Phil

2 Likes

Works perfectly! Thanks Philip

If anyone need help, here’s what I did with Philip advices:

:diamonds: created hooks in tk-multi-launchapp.yml under settings.tk-multi-launchapp and settings.tk-multi-launchapp.shotgun (not sure what this second one is doing)

hook_before_app_launch: "{config}/tk-multi-launchapp/before_app_launch.py"

:diamonds: created my methods in {config}/tk-multi-launchapp/before_app_launch.py. The first method I call makes sur PYTHONPATH is setuped as I want.

:diamonds: also added userSetup.py’s folder path to PYTHONPATH through a method that only execute if engine_name == ‘tk-maya’

2 Likes

That sounds spot on!

FYI the second settings.tk-multi-launchapp.shotgun block is used purely by the tk-shotgun engine. In other words those are the settings it will use if you launch a software via the browser integration. I’m not totally sure why the browser integration needed skip_engine_instances: ["tk-nukestudio"] specifically, but that is the difference.

2 Likes

I want to launch a particular script in Maya once SGTK has been setuped.
The problem with using userSetup.py is that I have absolutly no control over when the setup is launched. Even with cmds.userDeffered, I have problems.

Is there a hook that would allow me to launch a script (similar to userSetup.py) but which would only be activated once maya is setuped (every plugins loaded, engine.context available, etc)?

Thanks

1 Like

Hi Ben

The engine_init.py core hook would probably do what you need.

You would need to check that the engine was tk-maya before doing anything specific to Maya, and also this would get run whenever you restarted the engine, so you might need to implement some kind of check if you only ever want to run this once.

if engine.name == "tk-maya":
   # do some Maya stuff
1 Like

Great, thanks Philip!

I can’t find any reference to this hook in /env dir, how can I make sure sgtk will call engine_init.py from my /config and not from /install ?

1 Like

Ah sorry I should have explained. We are currently missing a doc on how hooks work and we are working on writing one.

So there are two types of hooks. Core hooks and hooks that belong to bundles like an App, Engine or Framework.

App, Engine or Framework hooks must be configured via the bundle in question’s settings in the environment YAMLs.

Core hooks just need to be copied over to the config/core/hooks folder and can’t be renamed. They will then get picked up by core during normal usage.

2 Likes

Okay, thanks for you quick reply :slight_smile:

1 Like

It seems engine_init.py is called right before when maya engine is initialised, which produces an error.

File "L:\_tech\sgtk_configs\config_sandbox\core\hooks\engine_init.py", line 46, in execute
    import python_modules.maya.userSetup.userSetup as userSetupModule

File "L:\_tech\python_modules\maya\userSetup\userSetup.py", line 27, in <module>
    import python_modules.maya.set_workspace as swm
    swmO = swm.MayaWorkspace()

File "L:\_tech\python_modules\maya\set_workspace.py", line 27, in __init__
    self.engine = sgtk.platform.current_engine()
    self.projectName = self.engine.context.project.get('name', '').lower()

AttributeError: 'NoneType' object has no attribute 'context' #

Workaround: engine already exists in engine_init, pass it as argument to the Objects we want to call, then it will works perfetcly!

This give way more contrl than userSetup.py ! Perfect :slight_smile:

1 Like

Yeah, I’ve seen this before, you’re right, the engine has started but it’s not registered itself as the current engine at that point, I think it’s the next thing that happens after calling that hook. Arguably it should perhaps have registered the current engine before calling the hook.

So as you say the workaround is to pass the engine provided in the hook onto any other processes you need to call.
Nice work!

2 Likes

I’m trying to build a pulldown menu, like the ‘Shotgrid’ one. I want to dynamically build this once Maya is loaded up through SG Desktop. I tried adding the code to engine_init.py but this didn’t work. I get 2 Shotgrid menus for some reason.
I’m curious to how @benwall solved this by passing to the Objects. My backup plan is to use the userSetup.py file but I would rather a more elegant solution using engine_init.py.

Thanks,

Mark

Hey @mdthielen,
I chose the easy way on this one and used sgtk’s userSetup.py :wink:

Consider install pyenv for this.

pyenv lets you easily switch between multiple versions of Python. It’s simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well.

Also, using a distribution like Anaconda with built-in package management. With Anaconda you can easily isolate your Python2 and Python3 environments and not have to mess with PYTHON PATH.

Erratum: I just re-checked the code, turns out I did not use userSetup.py but wrote my own class which is called with evalDeferred in engine_init:

if self.engine.name == "tk-maya":
    message = 'launch USERSETUP\n\n'
    logger.info(message)
    ## import modules now, as we have to be inside Maya to import cmds
    from maya import cmds
    cmd0 = 'import sgtk'
    cmd1 = 'import myOwn.userSetup as userSetupModule'
    cmd2 = 'userSetupModule.UserSetupClass(inputEngine = sgtk.platform.current_engine())'
    cmds.evalDeferred( cmd0 )
    cmds.evalDeferred( cmd1 )
    cmds.evalDeferred( cmd2 )

Passing the arg sgtk.platform.current_engine() rather than self.engine is just to be absolutly sure to get the latest one when evalDeferred launchs.

It’s probably not the cleanest way, but it works pretty well.