userSetup.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #
  2. # Copyright (c) Contributors to the Open 3D Engine Project.
  3. # For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. #
  5. # SPDX-License-Identifier: Apache-2.0 OR MIT
  6. #
  7. #
  8. # -------------------------------------------------------------------------
  9. """
  10. This module fullfils the maya bootstrap pattern as described in their docs
  11. https://tinyurl.com/y2aoz8es
  12. Pattern is similar to Lumberyard Editor\\Scripts\\bootstrap.py
  13. For now the proper way to initiate Maya boostrapping the DCCsi, is to use
  14. the provided env and launcher bat files.
  15. If you are developing for the DCCsi you can use this launcher to start Maya:
  16. DccScriptingInterface\\Launchers\\Windows\\Launch_Maya_2020.bat"
  17. To Do: ATOM-5861
  18. """
  19. __project__ = 'DccScriptingInterface'
  20. # it is really hard to debug userSetup bootstrapping
  21. # this enables some rudimentary logging for debugging
  22. _BOOT_INFO = True
  23. # -------------------------------------------------------------------------
  24. # built in's
  25. import sys
  26. import os
  27. import site
  28. import inspect
  29. from pathlib import Path
  30. import logging as _logging
  31. # -- maya imports
  32. import maya.cmds as cmds
  33. import maya.mel as mel
  34. #from pymel.all import *
  35. # Maya is frozen, entry point module path when frozen
  36. _MODULE_PATH = Path(os.path.abspath(inspect.getfile(inspect.currentframe())))
  37. print(f'o3de userSetup.py path is: {_MODULE_PATH}')
  38. PATH_O3DE_TECHART_GEMS = _MODULE_PATH.parents[5].resolve()
  39. print(f'o3de techart gems path is: {PATH_O3DE_TECHART_GEMS}')
  40. sys.path.insert(0, str(PATH_O3DE_TECHART_GEMS))
  41. from DccScriptingInterface import PATH_DCCSI_PYTHON_LIB
  42. # 3rdparty
  43. from unipath import Path
  44. from box import Box
  45. # -------------------------------------------------------------------------
  46. # -------------------------------------------------------------------------
  47. # global scope
  48. from DccScriptingInterface.Tools.DCC.Maya import _PACKAGENAME
  49. _MODULENAME = f'{_PACKAGENAME}.scripts.userSetup'
  50. __all__ = ['config',
  51. 'constants',
  52. 'setup',
  53. 'start',
  54. 'scripts']
  55. _LOGGER = _logging.getLogger(_MODULENAME)
  56. from DccScriptingInterface import add_site_dir
  57. add_site_dir(PATH_O3DE_TECHART_GEMS) # cleaner add
  58. from DccScriptingInterface.globals import *
  59. from azpy.constants import FRMT_LOG_LONG
  60. _logging.basicConfig(level=_logging.DEBUG,
  61. format=FRMT_LOG_LONG,
  62. datefmt='%m-%d %H:%M')
  63. _LOGGER = _logging.getLogger(_MODULENAME)
  64. # auto-attach ide debugging at the earliest possible point in module
  65. if DCCSI_DEV_MODE:
  66. if DCCSI_GDEBUGGER == 'WING':
  67. import DccScriptingInterface.azpy.test.entry_test
  68. DccScriptingInterface.azpy.test.entry_test.connect_wing()
  69. elif DCCSI_GDEBUGGER == 'PYCHARM':
  70. _LOGGER.warning(f'{DCCSI_GDEBUGGER} debugger auto-attach not yet implemented')
  71. else:
  72. _LOGGER.warning(f'{DCCSI_GDEBUGGER} not a supported debugger')
  73. # this should execute the core config.py first and grab settings
  74. from DccScriptingInterface.Tools.DCC.Maya.config import maya_config
  75. maya_config.settings.setenv() # init settings, ensure env is set
  76. from DccScriptingInterface import ENVAR_PATH_DCCSIG
  77. from DccScriptingInterface.azpy.constants import *
  78. from DccScriptingInterface.constants import *
  79. from DccScriptingInterface.Tools.DCC.Maya.constants import *
  80. # message collection
  81. _LOGGER.info(f'Initializing: {_MODULENAME}')
  82. _LOGGER.debug(f'_MODULE_PATH: {_MODULE_PATH}')
  83. _LOGGER.debug(f'{ENVAR_PATH_DCCSIG}: {maya_config.settings.PATH_DCCSIG}')
  84. _LOGGER.debug(f'{ENVAR_DCCSI_CONFIG_DCC_MAYA}: {maya_config.settings.DCCSI_CONFIG_DCC_MAYA}')
  85. _LOGGER.debug(f'{ENVAR_PATH_DCCSI_TOOLS_DCC_MAYA}: {maya_config.settings.PATH_DCCSI_TOOLS_DCC_MAYA}')
  86. # flag to turn off setting up callbacks, until they are fully implemented
  87. # To Do: consider making it a settings option to define and enable/disable
  88. _G_LOAD_CALLBACKS = True # couple bugs, couple NOT IMPLEMENTED
  89. _LOGGER.info(f'DCCSI_MAYA_SET_CALLBACKS: {_G_LOAD_CALLBACKS}.')
  90. # -------------------------------------------------------------------------
  91. # -------------------------------------------------------------------------
  92. # To Do REMOVE this block and replace with dev module
  93. # debug prints, To Do: this should be moved to bootstrap config
  94. #_G_DEBUGGER = os.getenv(ENVAR_DCCSI_GDEBUGGER, "WING")
  95. #if _DCCSI_DEV_MODE:
  96. #if _G_DEBUGGER == "WING":
  97. #_LOGGER.info('{0}'.format('-' * 74))
  98. #_LOGGER.info('Developer Debug Mode: {0}, Basic debugger: {1}'.format(_G_DEBUG, _G_DEBUGGER))
  99. #try:
  100. #_LOGGER.info('Attempting to start basic WING debugger')
  101. #import azpy.lmbr.test
  102. #_LOGGER.info('Package Imported: azpy.test')
  103. #ouput = azpy.entry_test.main(verbose=False,
  104. #connectDebugger=True,
  105. #returnOuput=_G_DEBUG)
  106. #_LOGGER.info(ouput)
  107. #pass
  108. #except Exception as e:
  109. #_LOGGER.info("Error: azpy.test, entry_test (didn't perform)")
  110. #_LOGGER.info("Exception: {0}".format(e))
  111. #pass
  112. #elif _G_DEBUGGER == "PYCHARM":
  113. ## https://github.com/juggernate/PyCharm-Maya-Debugging
  114. #_LOGGER.info('{0}'.format('-' * 74))
  115. #_LOGGER.info('Developer Debug Mode: {0}, Basic debugger: {1}'.format(_G_DEBUG, _G_DEBUGGER))
  116. #sys.path.append('C:\Program Files\JetBrains\PyCharm 2019.1.3\debug-eggs\pydevd-pycharm.egg')
  117. #try:
  118. #_LOGGER.info('Attempting to start basic PYCHARM debugger')
  119. ## Inside Maya Python Console (Tip: add to a shelf button for quick access)
  120. #import pydevd
  121. #_LOGGER.info('Package Imported: pydevd')
  122. #pydevd.settrace('localhost', port=7720, suspend=False)
  123. #_LOGGER.info('PYCHARM Debugger Attach Success!!!')
  124. ## To disconnect run:
  125. ## pydevd.stoptrace()
  126. #pass
  127. #except Exception as e:
  128. #_LOGGER.info("Error: pydevd.settrace (didn't perform)")
  129. #_LOGGER.info("Exception: {0}".format(e))
  130. #pass
  131. #else:
  132. #pass
  133. ## -------------------------------------------------------------------------
  134. # -------------------------------------------------------------------------
  135. # To Do: implement data driven config
  136. # Currently not used, but will be where we store the ordered dict
  137. # which is parsed from the project bootstrapping config files.
  138. _G_app_config = {}
  139. # global scope maya callbacks container
  140. _G_callbacks = Box(box_dots=True) # global scope container
  141. # used to store fixPaths in the global scope
  142. _fix_paths = None
  143. # -------------------------------------------------------------------------
  144. # -------------------------------------------------------------------------
  145. # add appropriate common tools paths to the maya environment variables
  146. def startup():
  147. """Early starup execution before mayautils.executeDeferred().
  148. Some things like UI and plugins should be defered to avoid failure"""
  149. _LOGGER.info('{}.startup() fired'.format(_MODULENAME))
  150. from DccScriptingInterface import PATH_DCCSIG
  151. from DccScriptingInterface.Tools import PATH_DCCSI_TOOLS
  152. try:
  153. import DccScriptingInterface.azpy.test
  154. _LOGGER.info('SUCCESS, import DccScriptingInterface.azpy.test')
  155. except Exception as e:
  156. _LOGGER.warning('startup(), could not import DccScriptingInterface.azpy.test')
  157. _LOGGER.info('startup(), COMPLETE')
  158. return 0
  159. # -------------------------------------------------------------------------
  160. # -------------------------------------------------------------------------
  161. # verify Shared\Python exists and add it as a site dir. Begin imports and config.
  162. def post_startup():
  163. """Allows for a defered execution startup sequence (post UI boot)"""
  164. # NOTE: at this point, in Maya 2022+, the logging will show in script editor
  165. # not in the boot console window
  166. # to do: investigate if we want to figure out how to stream into output console also
  167. _LOGGER.info('{}.post_startup() fired'.format(_MODULENAME))
  168. # plugins, To Do: these should be moved to bootstrapping config
  169. try:
  170. maya.cmds.loadPlugin("dx11Shader")
  171. except Exception as e:
  172. _LOGGER.exception(f'{e} , traceback =', exc_info=True)
  173. # Lumberyard DCCsi environment ready or error out.
  174. try:
  175. import DccScriptingInterface.azpy.dcc.maya
  176. from DccScriptingInterface.azpy.dcc.maya import _PACKAGENAME
  177. _LOGGER.info('Python module imported: {}'.format(_PACKAGENAME))
  178. except Exception as e:
  179. _LOGGER.exception(f'{e} , traceback =', exc_info=True)
  180. return 1
  181. # DEPRECATE: don't nee to .init() anymore, auto-init (experimental)
  182. ## Dccsi azpy maya ready or error out.
  183. #try:
  184. #azpy.dcc.maya.init()
  185. #from azpy.dcc.maya import _PACKAGENAME
  186. #_LOGGER.info('SUCCESS, {}.init(), code accessible.'.format(_PACKAGENAME))
  187. #except Exception as e:
  188. #_LOGGER.error(e)
  189. #_LOGGER.error(traceback.print_exc())
  190. #return 1
  191. # callbacks, To Do: these should also be moved to the bootstrapping config
  192. # Defered startup after the Ui is running.
  193. _G_CALLBACKS = Box(box_dots=True) # this just ensures a global scope container
  194. if _G_LOAD_CALLBACKS:
  195. try:
  196. import DccScriptingInterface.Tools.DCC.Maya.Scripts
  197. import DccScriptingInterface.Tools.DCC.Maya.Scripts.set_callbacks
  198. from DccScriptingInterface.Tools.DCC.Maya.Scripts.set_callbacks import _G_CALLBACKS
  199. # ^ need to hold on to this as the install repopulate set
  200. except ImportError as e:
  201. _LOGGER.exception(f'{e} , traceback =', exc_info=True)
  202. raise e
  203. # this ensures the fixPaths callback is loaded
  204. # even when the other global callbacks are disabled
  205. #from set_callbacks import install_fix_paths
  206. DccScriptingInterface.Tools.DCC.Maya.Scripts.set_callbacks.install_fix_paths()
  207. # set the project workspace
  208. _project_workspace = os.path.join(maya_config.settings.MAYA_PROJECT, SLUG_MAYA_WORKSPACE)
  209. if os.path.isfile(_project_workspace):
  210. try:
  211. # load workspace
  212. maya.cmds.workspace(maya_config.settings.MAYA_PROJECT, openWorkspace=True)
  213. _LOGGER.info('Loaded workspace file: {0}'.format(_project_workspace))
  214. maya.cmds.workspace(maya_config.settings.MAYA_PROJECT, update=True)
  215. except Exception as e:
  216. _LOGGER.exception(f'{e} , traceback =', exc_info=True)
  217. else:
  218. _LOGGER.warning('Workspace file not found: {1}'.format(maya_config.settings.MAYA_PROJECT))
  219. # Set up Lumberyard, maya default setting
  220. import DccScriptingInterface.Tools.DCC.Maya.Scripts.set_defaults
  221. DccScriptingInterface.Tools.DCC.Maya.Scripts.set_defaults.set_defaults()
  222. # Setup UI tools
  223. # if not maya.cmds.about(batch=True):
  224. # _LOGGER.info('Add UI dependent tools')
  225. # # wrap in a try, because we haven't implmented it yet
  226. # try:
  227. # mel.eval(str(r'source "{}"'.format(SLUG_O3DE_DCC_MAYA_MEL)))
  228. # except Exception as e:
  229. # _LOGGER.exception(f'{e} , traceback =', exc_info=True)
  230. # pass
  231. # manage custom menu in a sub-module
  232. import DccScriptingInterface.Tools.DCC.Maya.Scripts.set_menu
  233. DccScriptingInterface.Tools.DCC.Maya.Scripts.set_menu.set_main_menu()
  234. # To Do: manage custom shelf in a sub-module
  235. _LOGGER.info('post_startup(), COMPLETE')
  236. _LOGGER.info('DCCsi Bootstrap, COMPLETE')
  237. return 0
  238. # -------------------------------------------------------------------------
  239. # -------------------------------------------------------------------------
  240. if __name__ == '__main__':
  241. try:
  242. # Early startup config.
  243. startup()
  244. # This allows defered action post boot (atfer UI is active)
  245. from maya.utils import executeDeferred
  246. _LOGGER.info('attempting to run, post_startup()')
  247. post = executeDeferred(post_startup)
  248. _LOGGER.info('executing userSetup COMPLETE')
  249. except Exception as e:
  250. _LOGGER.exception(f'{e} , traceback =', exc_info=True)
  251. raise e