userSetup.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. # coding:utf-8
  2. #!/usr/bin/python
  3. #
  4. # Copyright (c) Contributors to the Open 3D Engine Project.
  5. # For complete copyright and license terms please see the LICENSE at the root of this distribution.
  6. #
  7. # SPDX-License-Identifier: Apache-2.0 OR MIT
  8. #
  9. #
  10. # -- This line is 75 characters -------------------------------------------
  11. from __future__ import unicode_literals
  12. """
  13. This module fullfils the maya bootstrap pattern as described in their docs
  14. https://tinyurl.com/y2aoz8es
  15. Pattern is similar to Lumberyard Editor\\Scripts\\bootstrap.py
  16. For now the proper way to initiate Maya boostrapping the DCCsi, is to use
  17. the provided env and launcher bat files.
  18. If you are developing for the DCCsi you can use this launcher to start Maya:
  19. DccScriptingInterface\\Launchers\\Windows\\Launch_Maya_2020.bat"
  20. To Do: ATOM-5861
  21. """
  22. __project__ = 'DccScriptingInterface'
  23. # it is really hard to debug userSetup bootstrapping
  24. # this enables some rudimentary logging for debugging
  25. _BOOT_INFO = True
  26. # -------------------------------------------------------------------------
  27. # built in's
  28. import os
  29. import sys
  30. import site
  31. import inspect
  32. import traceback
  33. import logging as _logging
  34. # -- DCCsi Extension Modules
  35. import azpy
  36. from azpy.constants import *
  37. from azpy.env_bool import env_bool
  38. from azpy.constants import ENVAR_DCCSI_GDEBUG
  39. from azpy.constants import ENVAR_DCCSI_DEV_MODE
  40. # To Do: needs to be updated to use dynaconf and config.py
  41. from azpy.env_base import _BASE_ENVVAR_DICT
  42. # -- maya imports
  43. import maya.cmds as cmds
  44. import maya.mel as mel
  45. #from pymel.all import *
  46. # -------------------------------------------------------------------------
  47. # -------------------------------------------------------------------------
  48. # global space
  49. _DCCSI_GDEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
  50. _DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
  51. _DCCSI_DEV_MODE = True # force true for debugger testing
  52. _ORG_TAG = r'Amazon::Lumberyard'
  53. _APP_TAG = r'DCCsi'
  54. _TOOL_TAG = r'SDK.Maya.Scripts.userSetup'
  55. _TYPE_TAG = r'entrypoint' # bootstrap
  56. _MODULENAME = str('{0}.{1}'.format(_APP_TAG, _TOOL_TAG))
  57. _LOGGER = azpy.initialize_logger(_MODULENAME, default_log_level=int(20))
  58. _LOGGER.info('Initializing: {0}.'.format({_MODULENAME}))
  59. _LOGGER.info('DCCSI_GDEBUG: {0}.'.format({_DCCSI_GDEBUG}))
  60. _LOGGER.info('DCCSI_DEV_MODE: {0}.'.format({_DCCSI_DEV_MODE}))
  61. # flag to turn off setting up callbacks, until they are fully implemented
  62. # To Do: consider making it a settings option to define and enable/disable
  63. _G_LOAD_CALLBACKS = True # couple bugs, couple NOT IMPLEMENTED
  64. _LOGGER.info('DCCSI_MAYA_SET_CALLBACKS: {0}.'.format({_G_LOAD_CALLBACKS}))
  65. # early attach WingIDE debugger (can refactor to include other IDEs later)
  66. if _DCCSI_DEV_MODE:
  67. from azpy.test.entry_test import connect_wing
  68. foo = connect_wing()
  69. # -------------------------------------------------------------------------
  70. # -------------------------------------------------------------------------
  71. # To Do REMOVE this block and replace with dev module
  72. # debug prints, To Do: this should be moved to bootstrap config
  73. #_G_DEBUGGER = os.getenv(ENVAR_DCCSI_GDEBUGGER, "WING")
  74. #if _DCCSI_DEV_MODE:
  75. #if _G_DEBUGGER == "WING":
  76. #_LOGGER.info('{0}'.format('-' * 74))
  77. #_LOGGER.info('Developer Debug Mode: {0}, Basic debugger: {1}'.format(_G_DEBUG, _G_DEBUGGER))
  78. #try:
  79. #_LOGGER.info('Attempting to start basic WING debugger')
  80. #import azpy.lmbr.test
  81. #_LOGGER.info('Package Imported: azpy.test')
  82. #ouput = azpy.entry_test.main(verbose=False,
  83. #connectDebugger=True,
  84. #returnOuput=_G_DEBUG)
  85. #_LOGGER.info(ouput)
  86. #pass
  87. #except Exception as e:
  88. #_LOGGER.info("Error: azpy.test, entry_test (didn't perform)")
  89. #_LOGGER.info("Exception: {0}".format(e))
  90. #pass
  91. #elif _G_DEBUGGER == "PYCHARM":
  92. ## https://github.com/juggernate/PyCharm-Maya-Debugging
  93. #_LOGGER.info('{0}'.format('-' * 74))
  94. #_LOGGER.info('Developer Debug Mode: {0}, Basic debugger: {1}'.format(_G_DEBUG, _G_DEBUGGER))
  95. #sys.path.append('C:\Program Files\JetBrains\PyCharm 2019.1.3\debug-eggs\pydevd-pycharm.egg')
  96. #try:
  97. #_LOGGER.info('Attempting to start basic PYCHARM debugger')
  98. ## Inside Maya Python Console (Tip: add to a shelf button for quick access)
  99. #import pydevd
  100. #_LOGGER.info('Package Imported: pydevd')
  101. #pydevd.settrace('localhost', port=7720, suspend=False)
  102. #_LOGGER.info('PYCHARM Debugger Attach Success!!!')
  103. ## To disconnect run:
  104. ## pydevd.stoptrace()
  105. #pass
  106. #except Exception as e:
  107. #_LOGGER.info("Error: pydevd.settrace (didn't perform)")
  108. #_LOGGER.info("Exception: {0}".format(e))
  109. #pass
  110. #else:
  111. #pass
  112. ## -------------------------------------------------------------------------
  113. # -------------------------------------------------------------------------
  114. # validate access to the DCCsi and it's Lib site-packages
  115. # bootstrap site-packages by version
  116. from azpy.constants import PATH_DCCSI_PYTHON_LIB_PATH
  117. try:
  118. os.path.exists(PATH_DCCSI_PYTHON_LIB_PATH)
  119. site.addsitedir(PATH_DCCSI_PYTHON_LIB_PATH)
  120. _LOGGER.info('azpy 3rdPary site-packages: is: {0}'.format(PATH_DCCSI_PYTHON_LIB_PATH))
  121. except Exception as e:
  122. _LOGGER.error('ERROR: {0}, {1}'.format(e, PATH_DCCSI_PYTHON_LIB_PATH))
  123. raise e
  124. # 3rdparty
  125. from unipath import Path
  126. from box import Box
  127. # -------------------------------------------------------------------------
  128. # -------------------------------------------------------------------------
  129. # Maya is frozen
  130. #_MODULE_PATH = Path(__file__)
  131. # https://tinyurl.com/y49t3zzn
  132. # module path when frozen
  133. _MODULE_FILEPATH = os.path.abspath(inspect.getfile(inspect.currentframe()))
  134. _MODULE_PATH = os.path.dirname(_MODULE_FILEPATH)
  135. if _BOOT_INFO:
  136. _LOGGER.debug('Boot: CWD: {}'.format(os.getcwd()))
  137. _LOGGER.debug('Frozen: _MODULE_FILEPATH: {}'.format(_MODULE_FILEPATH))
  138. _LOGGER.debug('Frozen: _MODULE_PATH: {}'.format(_MODULE_PATH))
  139. _LOGGER.debug('Module __name__: {}'.format(__name__))
  140. # root: INFO: Module __name__: __main__
  141. _LOGGER.info('_MODULENAME: {}'.format(_MODULENAME))
  142. # -------------------------------------------------------------------------
  143. # check some env var tags (fail if no, likely means no proper code access)
  144. _STR_ERROR_ENVAR = "Envar 'key' does not exist in base_env: {0}"
  145. _DCCSI_TOOLS_PATH = None
  146. # To Do: needs to be updated to use dynaconf and config.py
  147. try:
  148. _DCCSI_TOOLS_PATH = _BASE_ENVVAR_DICT[ENVAR_DCCSI_TOOLS_PATH]
  149. except Exception as e:
  150. _LOGGER.critical(_STR_ERROR_ENVAR.format(_BASE_ENVVAR_DICT[ENVAR_DCCSI_TOOLS_PATH]))
  151. _O3DE_PROJECT_PATH = None
  152. try:
  153. _O3DE_PROJECT_PATH = _BASE_ENVVAR_DICT[ENVAR_O3DE_PROJECT_PATH]
  154. except Exception as e:
  155. _LOGGER.critical(_STR_ERROR_ENVAR.format(_BASE_ENVVAR_DICT[ENVAR_O3DE_PROJECT_PATH]))
  156. # check some env var tags (fail if no, likely means no proper code access)
  157. _O3DE_DEV = _BASE_ENVVAR_DICT[ENVAR_O3DE_DEV]
  158. _O3DE_DCCSIG_PATH = _BASE_ENVVAR_DICT[ENVAR_DCCSIG_PATH]
  159. _O3DE_DCCSI_LOG_PATH = _BASE_ENVVAR_DICT[ENVAR_DCCSI_LOG_PATH]
  160. _O3DE_AZPY_PATH = _BASE_ENVVAR_DICT[ENVAR_DCCSI_AZPY_PATH]
  161. # -------------------------------------------------------------------------
  162. # -------------------------------------------------------------------------
  163. # To Do: implement data driven config
  164. # Currently not used, but will be where we store the ordered dict
  165. # which is parsed from the project bootstrapping config files.
  166. _G_app_config = {}
  167. # global scope maya callbacks container
  168. _G_callbacks = Box(box_dots=True) # global scope container
  169. # used to store fixPaths in the global scope
  170. _fix_paths = None
  171. # -------------------------------------------------------------------------
  172. # -------------------------------------------------------------------------
  173. # add appropriate common tools paths to the maya environment variables
  174. def startup():
  175. """Early starup execution before mayautils.executeDeferred().
  176. Some things like UI and plugins should be defered to avoid failure"""
  177. _LOGGER.info('startup() fired')
  178. # get known paths
  179. _KNOWN_PATHS = site._init_pathinfo()
  180. if os.path.isdir(_DCCSI_TOOLS_PATH):
  181. site.addsitedir(_DCCSI_TOOLS_PATH, _KNOWN_PATHS)
  182. try:
  183. import azpy.test
  184. _LOGGER.info('SUCCESS, import azpy.test')
  185. except Exception as e:
  186. _LOGGER.warning('startup(), could not import azpy.test')
  187. _LOGGER.info('startup(), COMPLETE')
  188. return 0
  189. # -------------------------------------------------------------------------
  190. # -------------------------------------------------------------------------
  191. # verify Shared\Python exists and add it as a site dir. Begin imports and config.
  192. def post_startup():
  193. """Allows for a defered execution startup sequence"""
  194. _LOGGER.info('post_startup() fired')
  195. # plugins, To Do: these should be moved to bootstrapping config
  196. try:
  197. maya.cmds.loadPlugin("dx11Shader")
  198. except Exception as e:
  199. _LOGGER.error(e) # not a hard failure
  200. # Lumberyard DCCsi environment ready or error out.
  201. try:
  202. import azpy.dcc.maya
  203. _LOGGER.info('Python module imported: azpy.dcc.maya')
  204. except Exception as e:
  205. _LOGGER.error(e)
  206. _LOGGER.error(traceback.print_exc())
  207. return 1
  208. # Dccsi azpy maya ready or error out.
  209. try:
  210. azpy.dcc.maya.init()
  211. _LOGGER.info('SUCCESS, azpy.dcc.maya.init(), code accessible.')
  212. except Exception as e:
  213. _LOGGER.error(e)
  214. _LOGGER.error(traceback.print_exc())
  215. return 1
  216. # callbacks, To Do: these should also be moved to the bootstrapping config
  217. # Defered startup after the Ui is running.
  218. _G_CALLBACKS = Box(box_dots=True) # this just ensures a global scope container
  219. if _G_LOAD_CALLBACKS:
  220. from set_callbacks import _G_CALLBACKS
  221. # ^ need to hold on to this as the install repopulate set
  222. # this ensures the fixPaths callback is loaded
  223. # even when the other global callbacks are disabled
  224. from set_callbacks import install_fix_paths
  225. install_fix_paths()
  226. # set the project workspace
  227. #_O3DE_PROJECT_PATH = _BASE_ENVVAR_DICT[ENVAR_O3DE_PROJECT_PATH]
  228. _project_workspace = os.path.join(_O3DE_PROJECT_PATH, TAG_MAYA_WORKSPACE)
  229. if os.path.isfile(_project_workspace):
  230. try:
  231. # load workspace
  232. maya.cmds.workspace(_O3DE_PROJECT_PATH, openWorkspace=True)
  233. _LOGGER.info('Loaded workspace file: {0}'.format(_project_workspace))
  234. maya.cmds.workspace(_O3DE_PROJECT_PATH, update=True)
  235. except Exception as e:
  236. _LOGGER.error(e)
  237. else:
  238. _LOGGER.warning('Workspace file not found: {1}'.format(_O3DE_PROJECT_PATH))
  239. # Set up Lumberyard, maya default setting
  240. from set_defaults import set_defaults
  241. set_defaults()
  242. # Setup UI tools
  243. if not maya.cmds.about(batch=True):
  244. _LOGGER.info('Add UI dependent tools')
  245. # wrap in a try, because we haven't implmented it yet
  246. try:
  247. mel.eval(str(r'source "{}"'.format(TAG_O3DE_DCC_MAYA_MEL)))
  248. except Exception as e:
  249. _LOGGER.error(e)
  250. # manage custom menu in a sub-module
  251. from set_menu import set_main_menu
  252. set_main_menu()
  253. # To Do: manage custom shelf in a sub-module
  254. _LOGGER.info('post_startup(), COMPLETE')
  255. _LOGGER.info('DCCsi Bootstrap, COMPLETE')
  256. return 0
  257. # -------------------------------------------------------------------------
  258. # -------------------------------------------------------------------------
  259. if __name__ == '__main__':
  260. try:
  261. # Early startup config.
  262. startup()
  263. # This allows defered action post boot (atfer UI is active)
  264. from maya.utils import executeDeferred
  265. post = executeDeferred(post_startup)
  266. except Exception as e:
  267. traceback.print_exc()