bootstrap.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  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. """! This module is for use in bootstrapping the DccScriptingInterface Gem
  10. < dccsi > with O3DE. The dccsi package if a framework, which includes DCC
  11. tool integrations for O3DE workflows; and also provides technical artists
  12. and out-of-box python development environment.
  13. azlmbr represents the O3DE editor python bindings API
  14. This bootstrap file requires azlmbr and thus only runs within O3DE.
  15. :file: DccScriptingInterface\\editor\\scripts\\boostrap.py
  16. :Status: Prototype
  17. :Version: 0.0.2
  18. :Future: is unknown
  19. :Entrypoint: is an entrypoint and thus configures logging
  20. :Notice:
  21. Currently windows only (not tested on other platforms)
  22. No support for legacy DCC tools stuck on py2 (py3 only)
  23. """
  24. # standard imports
  25. import sys
  26. import os
  27. import site
  28. import subprocess
  29. from pathlib import Path
  30. import logging as _logging
  31. # -------------------------------------------------------------------------
  32. # -------------------------------------------------------------------------
  33. # global scope
  34. _DCCSI_SLUG = 'DccScriptingInterface'
  35. _MODULENAME = 'DCCsi.Editor.Scripts.bootstrap'
  36. _LOGGER = _logging.getLogger(_MODULENAME)
  37. _LOGGER.debug('Initializing: {0}.'.format({_MODULENAME}))
  38. # this file
  39. _MODULE_PATH = Path(__file__)
  40. _LOGGER.debug(f'_MODULE_PATH: {_MODULE_PATH.as_posix()}')
  41. # we can't import DccScriptingInterface yet, need to bootstrap core access
  42. #from DccScriptingInterface import PATH_O3DE_TECHART_GEMS
  43. #from DccScriptingInterface import PATH_DCCSIG
  44. # add gems parent, dccsi lives under:
  45. # < o3de >\Gems\AtomLyIntegration\TechnicalArt
  46. PATH_O3DE_TECHART_GEMS = _MODULE_PATH.parents[3].resolve()
  47. os.chdir(PATH_O3DE_TECHART_GEMS.as_posix())
  48. #sys.path.append(PATH_O3DE_TECHART_GEMS.as_posix())
  49. from DccScriptingInterface import add_site_dir
  50. add_site_dir(PATH_O3DE_TECHART_GEMS)
  51. # < o3de >\Gems\AtomLyIntegration\TechnicalArt\< dccsi >
  52. PATH_DCCSIG = _MODULE_PATH.parents[2].resolve()
  53. from DccScriptingInterface.azpy.constants import ENVAR_PATH_DCCSIG
  54. os.environ[ENVAR_PATH_DCCSIG] = PATH_DCCSIG.as_posix()
  55. # make the dccsi cwd
  56. os.chdir(PATH_DCCSIG.as_posix())
  57. PATH_DCCSIG_SETTINGS = PATH_DCCSIG.joinpath('settings.json')
  58. os.environ['SETTINGS_MODULE_FOR_DYNACONF'] = PATH_DCCSIG_SETTINGS.as_posix()
  59. # -------------------------------------------------------------------------
  60. # ---- debug stuff --------------------------------------------------------
  61. # local dccsi imports
  62. # this accesses common global state, e.g. DCCSI_GDEBUG (is True or False)
  63. from DccScriptingInterface.globals import *
  64. # auto-attach ide debugging at the earliest possible point in module
  65. from DccScriptingInterface.azpy.config_utils import attach_debugger
  66. if DCCSI_DEV_MODE: # from DccScriptingInterface.globals
  67. attach_debugger()
  68. #
  69. import DccScriptingInterface.config as dccsi_core_config
  70. # note: if you used win_launch_wingide.bat, settings will be over populated
  71. # because of the .bat file env chain that includes active apps
  72. # note: initializing the config PySide2 access here may not be ideal
  73. # it will set envars that may propagate, and have have the side effect
  74. # of interfering with apps like Wing because it is a Qt5 app and the
  75. # envars set cause a boot failure
  76. # if your tool is running inside of o3de you already have PySide2/Qt
  77. # if you are launching a standalone tool that does need access,
  78. # that application will need to run and manage config on it's own
  79. # # to do: refactor config.py and implement ConfigClass
  80. # from DccScriptingInterface.config import ConfigClass
  81. # dccsi_config = ConfigClass(config_name='dccsi', auto_set=True)
  82. # for now, use the legacy code, until CoreConfig class is complete
  83. _settings_core = dccsi_core_config.get_config_settings(enable_o3de_python=True,
  84. enable_o3de_pyside2=False,
  85. set_env=True)
  86. # configure basic logger
  87. # it is suggested that this be replaced with a common logging module later
  88. if DCCSI_GDEBUG or DCCSI_DEV_MODE:
  89. DCCSI_LOGLEVEL = _logging.DEBUG
  90. _LOGGER.setLevel(DCCSI_LOGLEVEL) # throttle up help
  91. _logging.basicConfig(level=DCCSI_LOGLEVEL,
  92. format=FRMT_LOG_LONG,
  93. datefmt='%m-%d %H:%M')
  94. _LOGGER = _logging.getLogger(_MODULENAME)
  95. # -------------------------------------------------------------------------
  96. # -------------------------------------------------------------------------
  97. O3DE_EDITOR = Path(sys.executable).resolve() # executible
  98. _LOGGER.debug(f'The sys.executable is: {O3DE_EDITOR}')
  99. # O3DE imports
  100. import azlmbr
  101. import azlmbr.bus
  102. import azlmbr.paths
  103. import azlmbr.action
  104. # put the Action Manager handler into a global scope so it's not deleted
  105. handler_action_manager = azlmbr.action.ActionManagerRegistrationNotificationBusHandler()
  106. # path devs might be interested in retreiving
  107. _LOGGER.debug(f'engroot: {azlmbr.paths.engroot}')
  108. _LOGGER.debug(f'executableFolder: {azlmbr.paths.executableFolder}')
  109. _LOGGER.debug(f'log: {azlmbr.paths.log}')
  110. _LOGGER.debug(f'products: {azlmbr.paths.products}')
  111. _LOGGER.debug(f'projectroot: {azlmbr.paths.projectroot}')
  112. # base paths
  113. O3DE_DEV = Path(azlmbr.paths.engroot).resolve()
  114. PATH_O3DE_BIN = Path(azlmbr.paths.executableFolder).resolve()
  115. PATH_O3DE_PROJECT = Path(azlmbr.paths.projectroot).resolve()
  116. # the DCCsi Gem expects QtForPython Gem is active
  117. try:
  118. azlmbr.qt.QtForPythonRequestBus(azlmbr.bus.Broadcast, 'IsActive')
  119. except Exception as e:
  120. _LOGGER.error(f'O3DE Qt / PySide2 not available, exception: {e}')
  121. raise e
  122. # debug logging, these are where Qt lives
  123. params = azlmbr.qt.QtForPythonRequestBus(azlmbr.bus.Broadcast, 'GetQtBootstrapParameters')
  124. _LOGGER.debug(f'qtPluginsFolder: {params.qtPluginsFolder}')
  125. _LOGGER.debug(f'qtBinaryFolder: {params.qtBinaryFolder}')
  126. #PySide2 imports
  127. from PySide2 import QtWidgets
  128. from PySide2.QtWidgets import QMenuBar, QMenu, QAction
  129. from PySide2 import QtGui
  130. from PySide2.QtCore import Slot, QObject, QUrl
  131. from shiboken2 import wrapInstance, getCppPointer
  132. # additional DCCsi imports that utilize PySide2
  133. from DccScriptingInterface.Editor.Scripts.ui import start_service
  134. from DccScriptingInterface.Editor.Scripts.ui import hook_register_action_sampleui
  135. # SLUGS
  136. START_SLUG = 'Start'
  137. HELP_SLUG = 'Help ...'
  138. # slug for editor action context
  139. editor_mainwindow_context_slug = 'o3de.context.editor.mainwindow'
  140. # slug is a string path.to.object.name
  141. editor_mainwindow_menubar_slug = 'o3de.menubar.editor.mainwindow'
  142. # actions are similar path.to.action.name
  143. dccsi_action_context = 'o3de.action.python.dccsi'
  144. # name to display for DCCsi Menu
  145. dccsi_menu_name = 'studiotools'
  146. # add to slug.path.to.object.name
  147. dccsi_menu_slug = 'o3de.menu.studiotools'
  148. # -------------------------------------------------------------------------
  149. # - slot ------------------------------------------------------------------
  150. # as the list of slots/actions grows, refactor into sub-modules
  151. def click_action_blender_start() -> start_service:
  152. """Start Blender DCC application"""
  153. _LOGGER.debug(f'Clicked: click_action_blender_start')
  154. from DccScriptingInterface.Tools.DCC.Blender import PATH_DCCSI_TOOLS_DCC_BLENDER
  155. py_file = Path(PATH_DCCSI_TOOLS_DCC_BLENDER, 'start.py').resolve()
  156. return start_service(py_file)
  157. # - hook ------------------------------------------------------------------
  158. def hook_register_action_blender_start(parameters):
  159. # Create an Action Hook for starting Blender from menu
  160. _LOGGER.debug(f'Registered: hook_register_action_blender_start')
  161. action_properties = azlmbr.action.ActionProperties()
  162. action_properties.name = START_SLUG
  163. action_properties.description = "A menu item to call an action to Start Blender"
  164. action_properties.category = "Python"
  165. azlmbr.action.ActionManagerPythonRequestBus(azlmbr.bus.Broadcast,
  166. 'RegisterAction',
  167. editor_mainwindow_context_slug,
  168. 'o3de.action.python.dccsi.dcc.blender.start',
  169. action_properties,
  170. click_action_blender_start)
  171. # -------------------------------------------------------------------------
  172. # - slot ------------------------------------------------------------------
  173. def click_action_blender_help():
  174. """Open Blender DCCsi docs (readme currently)"""
  175. _LOGGER.debug(f'Clicked: click_action_blender_help')
  176. url = "https://github.com/o3de/o3de/tree/development/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Tools/DCC/Blender/readme.md"
  177. return QtGui.QDesktopServices.openUrl(QUrl(url, QUrl.TolerantMode))
  178. # - hook ------------------------------------------------------------------
  179. def hook_register_action_blender_help(parameters):
  180. _LOGGER.debug(f'Registered: hook_register_action_blender_help')
  181. action_properties = azlmbr.action.ActionProperties()
  182. action_properties.name = HELP_SLUG
  183. action_properties.description = "A menu item to open Dccsi Blender Readme (help docs)"
  184. action_properties.category = "Python"
  185. azlmbr.action.ActionManagerPythonRequestBus(azlmbr.bus.Broadcast,
  186. 'RegisterAction',
  187. editor_mainwindow_context_slug,
  188. 'o3de.action.python.dccsi.dcc.blender.help',
  189. action_properties,
  190. click_action_blender_help)
  191. # -------------------------------------------------------------------------
  192. # - slot ------------------------------------------------------------------
  193. def click_action_maya_start() -> start_service:
  194. """Start Maya DCC application"""
  195. _LOGGER.debug(f'Clicked: click_action_maya_start')
  196. from DccScriptingInterface.Tools.DCC.Maya import PATH_DCCSI_TOOLS_DCC_MAYA
  197. py_file = Path(PATH_DCCSI_TOOLS_DCC_MAYA, 'start.py').resolve()
  198. return start_service(py_file)
  199. # - hook ------------------------------------------------------------------
  200. def hook_register_action_maya_start(parameters):
  201. # Create an Action Hook for starting Maya from menu
  202. _LOGGER.debug(f'Registered: hook_register_action_maya_start')
  203. action_properties = azlmbr.action.ActionProperties()
  204. action_properties.name = START_SLUG
  205. action_properties.description = "A menu item to call an action to Start Maya"
  206. action_properties.category = "Python"
  207. azlmbr.action.ActionManagerPythonRequestBus(azlmbr.bus.Broadcast,
  208. 'RegisterAction',
  209. editor_mainwindow_context_slug,
  210. 'o3de.action.python.dccsi.dcc.maya.start',
  211. action_properties,
  212. click_action_maya_start)
  213. # -------------------------------------------------------------------------
  214. # - slot ------------------------------------------------------------------
  215. def click_action_maya_help():
  216. """Open Maya DCCsi docs (readme currently)"""
  217. _LOGGER.debug(f'Clicked: click_action_maya_help')
  218. url = "https://github.com/o3de/o3de/tree/development/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Tools/DCC/Maya/readme.md"
  219. return QtGui.QDesktopServices.openUrl(QUrl(url, QUrl.TolerantMode))
  220. # - hook ------------------------------------------------------------------
  221. def hook_register_action_maya_help(parameters):
  222. _LOGGER.debug(f'Registered: hook_register_action_maya_help')
  223. action_properties = azlmbr.action.ActionProperties()
  224. action_properties.name = HELP_SLUG
  225. action_properties.description = "A menu item to open Dccsi Maya Readme (help docs)"
  226. action_properties.category = "Python"
  227. azlmbr.action.ActionManagerPythonRequestBus(azlmbr.bus.Broadcast,
  228. 'RegisterAction',
  229. editor_mainwindow_context_slug,
  230. 'o3de.action.python.dccsi.dcc.maya.help',
  231. action_properties,
  232. click_action_blender_help)
  233. # -------------------------------------------------------------------------
  234. # - slot ------------------------------------------------------------------
  235. def click_action_wing_start() -> start_service:
  236. """Start Wing IDE"""
  237. _LOGGER.debug(f'Clicked: click_action_wing_start')
  238. from DccScriptingInterface.Tools.IDE.Wing import PATH_DCCSI_TOOLS_IDE_WING
  239. py_file = Path(PATH_DCCSI_TOOLS_IDE_WING, 'start.py').resolve()
  240. return start_service(py_file)
  241. # - hook ------------------------------------------------------------------
  242. def hook_register_action_wing_start(parameters):
  243. # Create an Action Hook for starting WingIDE from menu
  244. _LOGGER.debug(f'Registered: hook_register_action_wing_start')
  245. action_properties = azlmbr.action.ActionProperties()
  246. action_properties.name = START_SLUG
  247. action_properties.description = "A menu item to call an action to Start Wing IDE"
  248. action_properties.category = "Python"
  249. azlmbr.action.ActionManagerPythonRequestBus(azlmbr.bus.Broadcast,
  250. 'RegisterAction',
  251. editor_mainwindow_context_slug,
  252. 'o3de.action.python.dccsi.ide.wing.start',
  253. action_properties,
  254. click_action_wing_start)
  255. # -------------------------------------------------------------------------
  256. # - slot ------------------------------------------------------------------
  257. def click_action_wing_help():
  258. """Open Wing IDE DCCsi docs (readme currently)"""
  259. _LOGGER.debug(f'Clicked: click_action_wing_help')
  260. url = "https://github.com/o3de/o3de/tree/development/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Tools/IDE/Wing/readme.md"
  261. return QtGui.QDesktopServices.openUrl(QUrl(url, QUrl.TolerantMode))
  262. # - hook ------------------------------------------------------------------
  263. def hook_register_action_wing_help(parameters):
  264. _LOGGER.debug(f'Registered: hook_register_action_wing_help')
  265. action_properties = azlmbr.action.ActionProperties()
  266. action_properties.name = HELP_SLUG
  267. action_properties.description = "A menu item to open Dccsi Wing IDE Readme (help docs)"
  268. action_properties.category = "Python"
  269. azlmbr.action.ActionManagerPythonRequestBus(azlmbr.bus.Broadcast,
  270. 'RegisterAction',
  271. editor_mainwindow_context_slug,
  272. 'o3de.action.python.dccsi.ide.wing.help',
  273. action_properties,
  274. click_action_wing_help)
  275. # -------------------------------------------------------------------------
  276. # - slot ------------------------------------------------------------------
  277. from DccScriptingInterface.Editor.Scripts.about import DccsiAbout
  278. def click_action_dccsi_about():
  279. """Open DCCsi About Dialog"""
  280. _LOGGER.debug(f'Clicked: click_action_dccsi_about')
  281. # import additional O3DE QtForPython Gem modules
  282. import az_qt_helpers
  283. EDITOR_MAIN_WINDOW = az_qt_helpers.get_editor_main_window()
  284. about_dialog = DccsiAbout(EDITOR_MAIN_WINDOW)
  285. return about_dialog.exec_()
  286. # - hook ------------------------------------------------------------------
  287. def hook_register_action_dccsi_about(parameters):
  288. _LOGGER.debug(f'Registered: hook_register_action_dccsi_about')
  289. action_properties = azlmbr.action.ActionProperties()
  290. action_properties.name = 'About'
  291. action_properties.description = "Open DccScriptingInterface About Dialog"
  292. action_properties.category = "Python"
  293. azlmbr.action.ActionManagerPythonRequestBus(azlmbr.bus.Broadcast,
  294. 'RegisterAction',
  295. editor_mainwindow_context_slug,
  296. 'o3de.action.python.dccsi.about',
  297. action_properties,
  298. click_action_dccsi_about)
  299. # -------------------------------------------------------------------------
  300. # -------------------------------------------------------------------------
  301. def hook_on_menu_registration(parameters):
  302. _LOGGER.debug('DCCsi:bootstrap_Editor:hook_on_menu_registration')
  303. # Create a StudioTools Menu (o3de.menu.studiotools)
  304. menu_studiotools_properties = azlmbr.action.MenuProperties()
  305. menu_studiotools_properties.name = "Studio Tools"
  306. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  307. 'RegisterMenu',
  308. 'o3de.menu.studiotools',
  309. menu_studiotools_properties)
  310. # Studio Tools > DCC
  311. menu_studiotools_dcc_properties = azlmbr.action.MenuProperties()
  312. menu_studiotools_dcc_properties.name = "DCC"
  313. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  314. 'RegisterMenu',
  315. 'o3de.menu.studiotools.dcc',
  316. menu_studiotools_dcc_properties)
  317. # Studio Tools > DCC > Blender
  318. menu_studiotools_dcc_blender_properties = azlmbr.action.MenuProperties()
  319. menu_studiotools_dcc_blender_properties.name = "Blender"
  320. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  321. 'RegisterMenu',
  322. 'o3de.menu.studiotools.dcc.blender',
  323. menu_studiotools_dcc_blender_properties)
  324. # Studio Tools > DCC > Maya
  325. menu_studiotools_dcc_maya_properties = azlmbr.action.MenuProperties()
  326. menu_studiotools_dcc_maya_properties.name = "Maya"
  327. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  328. 'RegisterMenu',
  329. 'o3de.menu.studiotools.dcc.maya',
  330. menu_studiotools_dcc_maya_properties)
  331. # Studio Tools > IDE
  332. menu_studiotools_ide_properties = azlmbr.action.MenuProperties()
  333. menu_studiotools_ide_properties.name = "IDE"
  334. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  335. 'RegisterMenu',
  336. 'o3de.menu.studiotools.ide',
  337. menu_studiotools_ide_properties)
  338. # Studio Tools > IDE > Wing
  339. menu_studiotools_ide_wing_properties = azlmbr.action.MenuProperties()
  340. menu_studiotools_ide_wing_properties.name = "Wing"
  341. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  342. 'RegisterMenu',
  343. 'o3de.menu.studiotools.ide.wing',
  344. menu_studiotools_ide_wing_properties)
  345. # Studio Tools > examples
  346. menu_studiotools_examples_properties = azlmbr.action.MenuProperties()
  347. menu_studiotools_examples_properties.name = "Examples"
  348. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  349. 'RegisterMenu',
  350. 'o3de.menu.studiotools.examples',
  351. menu_studiotools_examples_properties)
  352. # -------------------------------------------------------------------------
  353. # -------------------------------------------------------------------------
  354. def hook_on_menu_binding(parameters):
  355. _LOGGER.debug('DCCsi:bootstrap_Editor:hook_on_menu_binding')
  356. # Add Blender Actions to menu tree
  357. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  358. 'AddActionToMenu',
  359. 'o3de.menu.studiotools.dcc.blender',
  360. 'o3de.action.python.dccsi.dcc.blender.start',
  361. 100)
  362. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  363. 'AddActionToMenu',
  364. 'o3de.menu.studiotools.dcc.blender',
  365. 'o3de.action.python.dccsi.dcc.blender.help',
  366. 200)
  367. # Add Maya Actions to menu tree
  368. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  369. 'AddActionToMenu',
  370. 'o3de.menu.studiotools.dcc.maya',
  371. 'o3de.action.python.dccsi.dcc.maya.start',
  372. 100)
  373. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  374. 'AddActionToMenu',
  375. 'o3de.menu.studiotools.dcc.maya',
  376. 'o3de.action.python.dccsi.dcc.maya.help',
  377. 200)
  378. # Add Wing Actions to menu tree
  379. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  380. 'AddActionToMenu',
  381. 'o3de.menu.studiotools.ide.wing',
  382. 'o3de.action.python.dccsi.ide.wing.start',
  383. 100)
  384. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  385. 'AddActionToMenu',
  386. 'o3de.menu.studiotools.ide.wing',
  387. 'o3de.action.python.dccsi.ide.wing.help',
  388. 200)
  389. # Add examples SampleUI
  390. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  391. 'AddActionToMenu',
  392. 'o3de.menu.studiotools.examples',
  393. 'o3de.action.python.dccsi.examples.sampleui',
  394. 100)
  395. # Add dccsi About
  396. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  397. 'AddActionToMenu',
  398. 'o3de.menu.studiotools',
  399. 'o3de.action.python.dccsi.about',
  400. 100)
  401. # manage dccsi menu tree
  402. # Add StudioTools > DCC (subMenu)
  403. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  404. 'AddSubMenuToMenu',
  405. 'o3de.menu.studiotools',
  406. 'o3de.menu.studiotools.dcc',
  407. 100)
  408. # Add StudioTools > DCC > Blender (subMenu)
  409. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  410. 'AddSubMenuToMenu',
  411. 'o3de.menu.studiotools.dcc',
  412. 'o3de.menu.studiotools.dcc.blender',
  413. 100)
  414. # Add StudioTools > DCC > Maya (subMenu)
  415. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  416. 'AddSubMenuToMenu',
  417. 'o3de.menu.studiotools.dcc',
  418. 'o3de.menu.studiotools.dcc.maya',
  419. 200)
  420. # Add StudioTools > IDE (subMenu)
  421. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  422. 'AddSubMenuToMenu',
  423. 'o3de.menu.studiotools',
  424. 'o3de.menu.studiotools.ide',
  425. 200)
  426. # Add StudioTools > IDE > Wing (subMenu)
  427. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  428. 'AddSubMenuToMenu',
  429. 'o3de.menu.studiotools.ide',
  430. 'o3de.menu.studiotools.ide.wing',
  431. 100)
  432. # Add StudioTools > Examples (subMenu)
  433. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  434. 'AddSubMenuToMenu',
  435. 'o3de.menu.studiotools',
  436. 'o3de.menu.studiotools.examples',
  437. 300)
  438. # Add our 'Studio Tools' Menu to O3DE Editor Menu Bar
  439. azlmbr.action.MenuManagerPythonRequestBus(azlmbr.bus.Broadcast,
  440. 'AddMenuToMenuBar',
  441. editor_mainwindow_menubar_slug,
  442. 'o3de.menu.studiotools',
  443. 1000)
  444. # -------------------------------------------------------------------------
  445. # -------------------------------------------------------------------------
  446. def hook_on_action_registration(parameters):
  447. """DCCsi Action Registration"""
  448. _LOGGER.debug('DCCsi:bootstrap_Editor:hook_on_action_registration')
  449. hook_register_action_blender_start(parameters)
  450. hook_register_action_blender_help(parameters)
  451. hook_register_action_maya_start(parameters)
  452. hook_register_action_maya_help(parameters)
  453. hook_register_action_wing_start(parameters)
  454. hook_register_action_wing_help(parameters)
  455. hook_register_action_sampleui(parameters)
  456. hook_register_action_dccsi_about(parameters)
  457. # -------------------------------------------------------------------------
  458. # -------------------------------------------------------------------------
  459. def bootstrap_Editor(handler_action_manager):
  460. """! Put bootstrapping code here to execute in O3DE Editor.exe"""
  461. _LOGGER.debug('DCCsi:bootstrap_Editor')
  462. handler_action_manager.connect()
  463. # dccsi actions
  464. handler_action_manager.add_callback('OnActionRegistrationHook', hook_on_action_registration)
  465. # dccsi StudioTools menu
  466. handler_action_manager.add_callback('OnMenuRegistrationHook', hook_on_menu_registration)
  467. handler_action_manager.add_callback('OnMenuBindingHook', hook_on_menu_binding)
  468. # -------------------------------------------------------------------------
  469. # -------------------------------------------------------------------------
  470. def bootstrap_MaterialEditor():
  471. """Put bootstrapping code here to execute in O3DE MaterialEditor.exe"""
  472. pass
  473. return None
  474. # -------------------------------------------------------------------------
  475. # -------------------------------------------------------------------------
  476. def bootstrap_MaterialCanvas():
  477. """Put bootstrapping code here to execute in O3DE MaterialCanvas.exe"""
  478. pass
  479. return None
  480. # -------------------------------------------------------------------------
  481. # -------------------------------------------------------------------------
  482. def bootstrap_PassCanvas():
  483. """Put bootstrapping code here to execute in O3DE PassCanvas.exe"""
  484. pass
  485. return None
  486. # -------------------------------------------------------------------------
  487. # -------------------------------------------------------------------------
  488. def bootstrap_AssetProcessor():
  489. """Put boostrapping code here to execute in O3DE AssetProcessor.exe"""
  490. pass
  491. return None
  492. # -------------------------------------------------------------------------
  493. # -------------------------------------------------------------------------
  494. def bootstrap_AssetBuilder():
  495. """Put boostrapping code here to execute in O3DE AssetBuilder.exe"""
  496. pass
  497. return None
  498. # -------------------------------------------------------------------------
  499. ###########################################################################
  500. # Main Code Block, runs this script as main (testing)
  501. # -------------------------------------------------------------------------
  502. if __name__ == '__main__':
  503. # set and retreive the *basic* env context/_settings on import
  504. # What application is executing the bootstrap?
  505. # Python is being run from:
  506. # editor.exe
  507. # materialeditor.exe
  508. # assetprocessor.exe
  509. # assetbuilder.exe, or the Python executable.
  510. # Exclude the .exe so it works on other platforms
  511. if sys.platform.startswith('win'):
  512. if O3DE_EDITOR.stem.lower() == "editor":
  513. # if _DCCSI_GDEBUG then run the pyside2 test
  514. _settings = bootstrap_Editor(handler_action_manager)
  515. elif O3DE_EDITOR.stem.lower() == "materialeditor":
  516. _settings = bootstrap_MaterialEditor()
  517. elif O3DE_EDITOR.stem.lower() == "materialcanvas":
  518. _settings = bootstrap_MaterialCanvas()
  519. elif O3DE_EDITOR.stem.lower() == "passcanvas":
  520. _settings = bootstrap_PassCanvas()
  521. elif O3DE_EDITOR.stem.lower() == "assetprocessor":
  522. _settings = bootstrap_AssetProcessor()
  523. elif O3DE_EDITOR.stem.lower() == "assetbuilder":
  524. _settings= bootstrap_AssetBuilder()
  525. elif O3DE_EDITOR.stem.lower() == "python":
  526. # in this case, we can re-use the editor settings
  527. # which will init python and pyside2 access externally
  528. _settings = bootstrap_Editor()
  529. else:
  530. _LOGGER.warning(f'No bootstrapping code for: {O3DE_EDITOR}')
  531. else:
  532. _LOGGER.warning(f'Non-windows platforms not implemented or tested.')
  533. # -------------------------------------------------------------------------