Integrating up through commit 90f050496

This commit is contained in:
alexpete
2021-04-07 14:03:29 -07:00
parent 8f2ed080a9
commit c2cbd430fe
2694 changed files with 285622 additions and 176874 deletions
@@ -0,0 +1,94 @@
# coding:utf-8
#!/usr/bin/python
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# -- This line is 75 characters -------------------------------------------
"""azpy.dev.ide.__init__"""
from azpy.env_bool import env_bool
from azpy.constants import ENVAR_DCCSI_GDEBUG
from azpy.constants import ENVAR_DCCSI_DEV_MODE
# global space
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = 'azpy.dev.ide'
from azpy import initialize_logger
_LOGGER = initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
__all__ = []
try:
import wingapi
__all__ = init_wing(__all__)
except:
pass
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def init_wing(_all):
"""If the wingapi is required for a package/module to import,
then it should be initialized and added here so general imports
don't fail"""
# Make sure we can import the native apis
import wingapi # this will fail if we can't
_all.append('wing')
# add others
# Importing additional local packages/modules
return _all
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def init_all(_all):
"""If the wingapi is required for a package/module to import,
then it should be initialized and added here so general imports
don't fail"""
# Make sure we can import the native apis
import wingapi # this will fail if we can't
_all.append('wing')
# add others
# Importing additional local packages/modules
return _all
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def import_all(_all=__all__):
"""this will test imports of __all__
can be run before or after init() to test"""
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(_all,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
return _all
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
import_all(__all__)
# -------------------------------------------------------------------------
@@ -0,0 +1,83 @@
# coding:utf-8
#!/usr/bin/python
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# -- This line is 75 characters -------------------------------------------
# send each line to maya with > send_py_cmd_to_maya
print('Hello World: Command received from WingIDE')
import maya.cmds as cmds
foo = cmds.polySphere(n='DemoSphere', radius=1.0)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# more complex example
import maya.cmds as cmds
import random
import time
name = 'DemoCube'
size = random.uniform(0.5, 2.0)
variation = random.uniform(1.5, 5.0)
amount = random.randint(9, 21)
# remove previous
obj_list = cmds.ls('{}*'.format(name))
if len(obj_list) > 0:
cmds.delete(obj_list)
for i in range(0, amount - 1):
depth_rand = random.uniform(size, size * variation)
tegel = cmds.polyCube(name='{}#'.format(name),
w=size, h=size, d=depth_rand)
cmds.move(size * i, 0, 5)
i += 1
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
import maya.cmds as cmds
import random
import time
name = 'DemoCube'
size = random.uniform(0.5, 2.0)
variation = random.uniform(1.5, 5.0)
amount = random.randint(9, 21)
def make_some_wonky_cubes(name=, size, variation, amount):
# remove previous
obj_list = cmds.ls('{}*'.format(name))
if len(obj_list) > 0:
cmds.delete(obj_list)
for i in range(0, amount - 1):
depth_rand = random.uniform(size, size * variation)
tegel = cmds.polyCube(name='{}#'.format(name),
w=size, h=size, d=depth_rand)
cmds.move(size * i, 0, 5)
i += 1
return
foo = make_some_wonky_cubes()
time.sleep(10)
foo = make_some_wonky_cubes()
while 1:
foo = make_some_wonky_cubes()
time.sleep(5)
foo = make_some_wonky_cubes(size=0.5, amount=20)
time.sleep(5)
break
@@ -0,0 +1,21 @@
# coding:utf-8
#!/usr/bin/python
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# -- This line is 75 characters -------------------------------------------
"""azpy.dev.ide.wing.__init__"""
__all__ = ['hot_keys', 'test']
@@ -0,0 +1,355 @@
# coding:utf-8
#!/usr/bin/python
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# inspiration: http://www.emeraldartist.com/blog/2012/10/11/remotely-sending-code-to-maya-from-wing
from __future__ import unicode_literals
""" Module to remotely send code to maya. Inside of WingIDE prefs, you will
need to add the parent dire of this module to 'IDE Extension Scripting>Search Path'
Additionally, you will need set up custom key bindings 'User Interface>Keyboard'
"""
# -- This line is 75 characters -------------------------------------------
# standard imports
import socket
import random
import sys
import os
import time
import logging as _logging
# wing ide
import wingapi
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
MODULENAME = 'azpy.dev.ide.wing.hot_keys'
_LOGGER = _logging.getLogger(MODULENAME)
## extend logger
#_handler = _logging.StreamHandler(sys.stdout)
#_handler.setLevel(_logging.DEBUG)
#FRMT_LOG_LONG = "[%(name)s][%(levelname)s] >> %(message)s (%(asctime)s; %(filename)s:%(lineno)d)"
#_formatter = _logging.Formatter(FRMT_LOG_LONG)
#_handler.setFormatter(_formatter)
#_LOGGER.addHandler(_handler)
#_LOGGER.debug('Loading: {0}.'.format({MODULENAME}))
_LOCAL_HOST = socket.gethostbyname(socket.gethostname())
_LOGGER.info('local_host: {}'.format(_LOCAL_HOST))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def display_text(test_str):
"""Displays text in a WingIDE pop-up dialog"""
app = wingapi.gApplication
v = "Product info is: " + str(app.GetProductInfo())
v += "\nAnd you typed: %s" % test_str
wingapi.gApplication.ShowMessageDialog("Test Message", v)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def get_wing_text(): # no hotkey
"""
Return the text currently selected in wing
"""
editor = wingapi.gApplication.GetActiveEditor()
if editor is None:
return None
else:
current_doc = editor.GetDocument()
start, end = editor.GetSelection()
text_block = current_doc.GetCharRange(start, end)
_LOGGER.debug('selected text is: {}'.format(text_block))
return text_block
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def display_wing_text(): # Ctrl+Shift+D
text_block = get_wing_text()
display_text(text_block)
return text_block
display_wing_text.contexts = [
wingapi.kContextNewMenu("DCCsi Scripts"),
wingapi.kContextEditor(),
]
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def get_stub_check_path(in_path=__file__, check_stub='engineroot.txt'):
'''
Returns the branch root directory of the dev\\'engineroot.txt'
(... or you can pass it another known stub)
so we can safely build relative filepaths within that branch.
If the stub is not found, it returns None
'''
path = os.path.abspath(os.path.join(os.path.dirname(in_path), ".."))
_LOGGER.info('parent dir: {}'.format(path))
while 1:
test_path = os.path.join(path, check_stub)
if os.path.isfile(test_path):
return os.path.abspath(os.path.join(os.path.dirname(test_path)))
else:
path, tail = (os.path.abspath(os.path.join(os.path.dirname(test_path), "..")),
os.path.basename(test_path))
if (len(tail) == 0):
return None
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# globals
_LY_DEV = get_stub_check_path()
_LOGGER.info('_LY_DEV: {}'.format(_LY_DEV))
_PROJ_CACHE = os.path.join(_LY_DEV, 'cache', 'DCCsi', 'wing')
_LOGGER.info('_PROJ_CACHE: {}'.format(_PROJ_CACHE))
if not os.path.exists(_PROJ_CACHE):
os.makedirs(_PROJ_CACHE)
_LOGGER.info('SUCCESS creating: {}'.format(_PROJ_CACHE))
else:
_LOGGER.info('_PROJ_CACHE already exists: {}'.format(_PROJ_CACHE))
# makedirs(_PROJ_CACHE)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def create_client_socket(local_host=_LOCAL_HOST,command_port=6000):
"""create a client (wing) socket connection to maya (server, commandPort)"""
for res in socket.getaddrinfo(local_host, command_port,
socket.AF_UNSPEC, socket.SOCK_STREAM,0, socket.AI_PASSIVE):
af, socktype, proto, canonname, sa = res
try:
mSocket = socket.socket(af, socktype, proto)
except socket.error as e:
mSocket = None
continue
try:
# Make our socket --> Maya connection:
mSocket.connect(sa)
except socket.error as e:
mSocket.close()
mSocket = None
continue
break
if not mSocket:
raise RuntimeError("Unable to initialise client socket.")
return mSocket
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def send_selection_to_maya(language='python',
local_host=_LOCAL_HOST,
command_port=6000):
"""Basic method to connect to Maya and send selected code over.
chunks can be large, which makes socket programming cumbersome.
This module stashes the selection in a temp .txt file in the cache.
Then send maya a command for a specific module, which will then
read that file and execute the code line-by-line, allowing for
arbirtarily large selections that might otherwise overrun buffer"""
port_name = str('{0}:{1}'.format(local_host, command_port))
_LOGGER.info('port_name: {}'.format(port_name))
if language != "mel" and language != "python":
raise ValueError("Expecting either 'mel' or 'python'")
# Save the text to a temp file.
# If mel, make sure it end with a semicolon
selected_text = get_wing_text()
if language == 'mel':
if not selected_text.endswith(';'):
selected_text += ';'
# This saves a temp file on Windows
# Mac\Linux support may need updating
temp_file_name = 'tmp_wing_data.txt'
temp_file_path = os.path.join(_PROJ_CACHE, temp_file_name)
temp_file_path = os.path.abspath(temp_file_path)
temp_file = temp_file_path.replace("\\", "/") # maya is linux paths?
_LOGGER.debug('temp_file_path is: {}'.format(temp_file_path))
if os.access(temp_file, os.F_OK):
# open and print the file in Maya:
f=open(temp_file_path, "w")
f.write(selected_text)
f.close()
else:
_LOGGER.info("No temp file exists: {}".format(temp_file))
file=open(temp_file, "w")
if os.path.isfile(temp_file):
_LOGGER.info('Created the file, please try again')
else:
_LOGGER.info('File not created')
# Create the socket that will connect to Maya, Opening a socket can vary from
mSocket = create_client_socket(local_host, command_port)
if mSocket:
# Now ping Maya over the command-port
message = ("import azpy.maya.utils.execute_wing_code;"
"azpy.maya.utils.execute_wing_code.main('{}')".format(language))
if language == 'mel':
message = 'python({})'.format(message) # wrap in in mel python cmd
try:
# Send our code to Maya:
mSocket.send(message.encode('ascii'))
time.sleep(1)
client_response = str(mSocket.recv(4096)).encode("utf-8") # receive the result info
# time.sleep(0.25)
# next command
except Exception as e:
_LOGGER.error("Sending command to Maya failed: {}".format(e))
_LOGGER.info("salt:{0}:: sent: {1}".format(str(random.randint(1, 9999)), message))
_LOGGER.info("The result is: {}".format(client_response))
mSocket.close()
else:
_LOGGER.error('No client socket, mSocket is: {}'.format(mSocket))
return
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def send_command_to_maya(language='python',
local_host=_LOCAL_HOST,
command_port=6000):
"""Basic method to connect to Maya and send a single smaller command directly"""
port_name = str('{0}:{1}'.format(local_host, command_port))
_LOGGER.info('port_name: {}'.format(port_name))
if language != "mel" and language != "python":
raise ValueError("Expecting either 'mel' or 'python'")
# Save the text to a temp file.
# If mel, make sure it end with a semicolon
selected_text = get_wing_text()
if language == 'mel':
if not selected_text.endswith(';'):
selected_text += ';'
# Create the socket that will connect to Maya, Opening a socket can vary from
mSocket = create_client_socket(local_host, command_port)
_LOGGER.info('mSocket is: {}'.format(mSocket))
if mSocket:
# Now ping Maya over the command-port
message = str(selected_text)
if language == 'mel':
message = 'python({})'.format(message) # wrap in in mel python cmd
# Now ping Maya over the command-port
try:
if language == 'mel':
message = 'python({})'.format(message)
# to do: the buffer default I think is 4096
# long selections are going to fail (not sure how)
mSocket.send(message.encode('ascii'))
time.sleep(1)
client_response = str(mSocket.recv(4096)).encode("utf-8") # receive the result info
# time.sleep(0.25)
# next command
except Exception as e:
_LOGGER.error("Sending command to Maya failed: {}".format(e))
_LOGGER.info("salt:{0}:: sent: {1}".format(str(random.randint(1, 9999)), message))
_LOGGER.info("The result is: {}".format(client_response))
mSocket.close()
else:
_LOGGER.error('No client socket, mSocket is: {}'.format(mSocket))
return
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def send_py_cmd_to_maya():
"""Send the selected Python command to Maya"""
send_command_to_maya() # default language is 'python'
send_py_cmd_to_maya.contexts = [
wingapi.kContextNewMenu("DCCsi Scripts"),
wingapi.kContextEditor(),
]
def send_mel_cmd_to_maya():
"""Send the selected code to Maya as mel"""
send_command_to_maya('mel')
send_mel_cmd_to_maya.contexts = [
wingapi.kContextNewMenu("DCCsi Scripts"),
wingapi.kContextEditor(),
]
def python_selection_to_maya():
"""Send the selected Python code to Maya"""
send_selection_to_maya() # default language is 'python'
python_selection_to_maya.contexts = [
wingapi.kContextNewMenu("DCCsi Scripts"),
wingapi.kContextEditor(),
]
def mel_selection_to_maya():
"""Send the selected code to Maya as mel"""
send_selection_to_maya('mel')
mel_selection_to_maya.contexts = [
wingapi.kContextNewMenu("DCCsi Scripts"),
wingapi.kContextEditor(),
]
# -------------------------------------------------------------------------
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
# there are not really tests to run here due to this being a list of
# constants for shared use.
_G_DEBUG = True
_DCCSI_DEV_MODE = True
_LOGGER.setLevel(_logging.DEBUG) # force debugging
foo = get_wing_text()
# send each line to maya with > send_py_cmd_to_maya
print('Hello World: Command received from WingIDE')
#import maya.cmds as cmds
#foo = cmds.polySphere()
@@ -0,0 +1,66 @@
This particular sub-package is devoted to WingIDE
It is mainly wingide specific extensions
Some notes ...
There are a couple of projects set up for Lumberyard python development with WingIDE
The FIRST is the DCCsi:
dev\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Solutions\.wing\DCCsi_7x.wpr
This provides devs a project to directly work on the DCCsi itself
You can launch wing and directly load this project via the following .bat file:
dev\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Launch_WingIDE-7-1.bat
Note: the data-driven env hooks for the DCCsi are in the Env.bat:
dev\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env.bat
^ when you launch wing via the .bat file it bootstraps that env first
Additionally, that same env is being transitioned to a python implementation using dynaconf (WIP):
dev\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\.env
dev\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\settings.json
dev\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\config.py
^ this last file is the root dynaconf config for the DCCsi
This will also allow us to have per-tool, per-project, per-dcc app env extensions and settings in a more nested way
The SECOND is the AtomTechArt Lumberyard project: dev\AtomTechArt
dev\AtomTechArt\DCCsi\envs\AtomTechArt\AtomTechArt.wpr
Note: this is set up as a venv based on the lumberyard python intstall
and thus provides a sandbox silo to develop outside of the lumberyard python, and outside of the DCCsi
This .bat will launch wing and directly load this project:
dev\AtomTechArt\DCCsi\Launch_AtomTechArt_WingIDE-7-1.bat
WingIDE auto-complete with Lumberyard:
Lumberyard when built will generate .pyi files for source analysis, inspection and auto-complete
On a per-project basis they are generated in the cache like:
dev\Cache\AtomTechArt\pc\user\python_symbols\azlmbr
Note: to get this to work unfortunatley each user must configure the wingide prefs to include this path
(there is no shared project / data-driven way that I know of to set this up otherwise)
Note: lumberyard is not currently generating __init__.pyi files in that package structure:
https://jira.agscollab.com/browse/SPEC-3315
The workaround is to create them yourself (they can be empty) and needs to be in the root of each package folder, like this:
dev\Cache\AtomTechArt\pc\user\python_symbols\azlmbr\__init__.pyi
dev\Cache\AtomTechArt\pc\user\python_symbols\azlmbr\materialeditor\__init__.pyi
ETC...
Then to enable do the following in WingIDE
1. (Dialog) WingIDE > Edit > Peferences
2. (Section) Category > Source Analysis > Advanced
3. (Add Path) In the area labeled "Interface File Path", insert a new path and point it to your cache:
Example (mine): g:\depot\JG_PC1_spectrAtom\dev\Cache\AtomTechArt\pc\user\python_symbols
You might need to reboot wing. Then you should have auto-complete for the lumberyard api
> import azlmbr
Note: the entirety of azlmbr api does not generate .pyi files currently,
all of the "Behaviour Context" based classes do
non-BC modules such as azlmbr.paths currently do not
https://jira.agscollab.com/browse/SPEC-3316
@@ -0,0 +1,83 @@
# coding:utf-8
#!/usr/bin/python
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
"""This is a module to test script extensions for WingIDE
reference: https://wingware.com/doc/scripting/example
note: there are important instructions in that doc for
setting up your project files with wingapi auto-complete, etc.
We added C:\Program Files (x86)\Wing Pro 7.1\src to the
PYTHONPATH via env.bat and dynaconf config instead so it is
part of the inhereted environment."""
import sys
import logging as _logging
import wingapi
# -------------------------------------------------------------------------
_MODULENAME = 'azpy.dev.ide.wing.test'
_LOGGER = _logging.getLogger(_MODULENAME)
_handler = _logging.StreamHandler(sys.stdout)
_handler.setLevel(_logging.DEBUG)
FRMT_LOG_LONG = "[%(name)s][%(levelname)s] >> %(message)s (%(asctime)s; %(filename)s:%(lineno)d)"
_formatter = _logging.Formatter(FRMT_LOG_LONG)
_handler.setFormatter(_formatter)
_LOGGER.addHandler(_handler)
_LOGGER.debug('Loading: {0}.'.format({_MODULENAME}))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def dccsi_test_script(test_str):
"""Simple test command for WingIDE
to run in wing: Edit > Command by Name
^ opens a commanline at bottom of IDE
type: test-script (then return)
^ commandline now takes entering a Test Str
Test Str: Booyah
^ a Pop-up dialog will display in wing
"""
app = wingapi.gApplication
v = "Product info is: " + str(app.GetProductInfo())
v += "\nAnd you typed: %s" % test_str
wingapi.gApplication.ShowMessageDialog("Test Message", v)
#dccsi_test_script.contexts = [wingapi.kContextNewMenu("Scripts")]
# this will add to a menu in WingIDE
dccsi_test_script.contexts = [
wingapi.kContextNewMenu("DCCsi Scripts"),
wingapi.kContextEditor(),
]
# -------------------------------------------------------------------------
# bind a hotkey inside Wing that will execute our newly installed Module
# Inside Wing, choose Edit -> Preferences, and on the left, under User Interface, choose Keyboard
# In the center right of the Keyboard section is where you can add "Ccustom Key Bindings" combinations to execute code
# For this test example, I have bound Ctrl+Alt+Shift+T as my key combination for executing dccsi_test_script
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
# there are not really tests to run here due to this being a list of
# constants for shared use.
_G_DEBUG = True
_DCCSI_DEV_MODE = True
_LOGGER.setLevel(_logging.DEBUG) # force debugging
foo = dccsi_test_script("This is a test")
@@ -0,0 +1,16 @@
# coding:utf-8
#!/usr/bin/python
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# -- This line is 75 characters -------------------------------------------
# define api package for each IDE supported
__all__ = ['check']
@@ -0,0 +1,18 @@
# coding:utf-8
#!/usr/bin/python
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# -- This line is 75 characters -------------------------------------------
# define api package for each IDE supported
__all__ = ['running_state', 'maya_app']
# maya_app, named such to avoid namespace collisions with maya dcc app api
@@ -0,0 +1,157 @@
# coding:utf-8
#!/usr/bin/python
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# -- This line is 75 characters -------------------------------------------
# -- Standard Python modules --
import sys
import os
import inspect
import logging as _logging
# -- External Python modules --
# none
# -- Extension Modules --
import azpy
from azpy.env_bool import env_bool
from azpy.constants import ENVAR_DCCSI_GDEBUG
from azpy.constants import ENVAR_DCCSI_DEV_MODE
# --------------------------------------------------------------------------
# -- Global Definitions --
_DCCSI_DCC_APP = None
# set up global space, logging etc.
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
_MODULENAME = 'azpy.dev.utils.check.maya_app'
_LOGGER = _logging.getLogger(_MODULENAME)
# -------------------------------------------------------------------------
###########################################################################
## These mini-functions need to be defined, before they are called
# -------------------------------------------------------------------------
# run this, if we are in Maya
def set_dcc_app(dcc_app='maya'):
"""
azpy.dev.utils.check.maya.set_dcc_app()
this will set global _DCCSI_DCC_APP = 'maya'
and os.environ["DCCSI_DCC_APP"] = 'maya'
"""
_DCCSI_DCC_APP = dcc_app
_LOGGER.info('Setting DCCSI_DCC_APP to: {0}'.format(dcc_app))
return _DCCSI_DCC_APP
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def clear_dcc_app(dcc_app=False):
"""
azpy.dev.utils.check.maya.set_dcc_app()
this will set global _DCCSI_DCC_APP = False
and os.environ["DCCSI_DCC_APP"] = False
"""
_DCCSI_DCC_APP = dcc_app
_LOGGER.info('Setting DCCSI_DCC_APP to: {0}'.format(dcc_app))
return _DCCSI_DCC_APP
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def validate_state(DCCSI_DCC_APP=_DCCSI_DCC_APP):
'''
This will detect if we are running in Maya or not,
then will call either, set_dcc_app('maya') or clear_dcc_app(dcc_app=False)
'''
if _G_DEBUG:
_LOGGER.debug(autolog())
try:
import maya.cmds as cmds
DCCSI_DCC_APP = set_dcc_app('maya')
except ImportError as e:
_LOGGER.warning('Can not perform: import maya.cmds as cmds')
DCCSI_DCC_APP = clear_dcc_app()
else:
try:
if cmds.about(batch=True):
DCCSI_DCC_APP = set_dcc_app('maya')
except AttributeError as e:
_LOGGER.warning("maya.cmds module isn't fully loaded/populated, "
"(cmds populates only in batch, maya.standalone, or maya GUI)")
# NO Maya
DCCSI_DCC_APP=clear_dcc_app()
return DCCSI_DCC_APP
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def autolog():
'''Automatically log the current function details.'''
# Get the previous frame in the stack, otherwise it would
# be this function!!!
func = inspect.currentframe().f_back.f_back.f_code
# Dump the message + the name of this function to the log.
output = ('{module} AUTOLOG:\r'
'Called from::\n{0}():\r'
'In file: {1},\r'
'At line: {2}\n'
''.format(func.co_name,
func.co_filename,
func.co_firstlineno,
module=_MODULENAME))
return output
#-------------------------------------------------------------------------
# -------------------------------------------------------------------------
# run the check on import
_DCCSI_DCC_APP = validate_state()
# -------------------------------------------------------------------------
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
# there are not really tests to run here due to this being a list of
# constants for shared use.
_G_DEBUG = True
_DCCSI_DEV_MODE = True
_LOGGER.setLevel(_logging.DEBUG) # force debugging
## reduce cyclical azpy imports
## it only has a basic logger configured, add log to console
#_handler = _logging.StreamHandler(sys.stdout)
#_handler.setLevel(_logging.DEBUG)
#FRMT_LOG_LONG = "[%(name)s][%(levelname)s] >> %(message)s (%(asctime)s; %(filename)s:%(lineno)d)"
#_formatter = _logging.Formatter(FRMT_LOG_LONG)
#_handler.setFormatter(_formatter)
#_LOGGER.addHandler(_handler)
#_LOGGER.debug('Loading: {0}.'.format({_MODULENAME}))
# happy print
from azpy.constants import STR_CROSSBAR
_LOGGER.info(STR_CROSSBAR)
_LOGGER.info('{} ... Running script as __main__'.format(_MODULENAME))
_LOGGER.info(STR_CROSSBAR)
_DCCSI_DCC_APP = validate_state()
_LOGGER.info('Is Maya Running? _DCCSI_DCC_APP = {}'.format(_DCCSI_DCC_APP))
@@ -0,0 +1,257 @@
# coding:utf-8
#!/usr/bin/python
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# -- This line is 75 characters -------------------------------------------
# -- Standard Python modules --
import sys
import os
import logging as _logging
# -- External Python modules --
# none
# -- Extension Modules --
# none (yet)
# --------------------------------------------------------------------------
# -- Global Definitions --
_DCCSI_DCC_APP = None
_MODULENAME = 'azpy.dev.utils.check.running_state'
_LOGGER = _logging.getLogger(_MODULENAME)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# First Class
class CheckRunningState(object):
"""
< To Do: document Class >
"""
# Class Variables
DCCSI_DCC_APP = None
def __init__(self, *args, **kwargs):
'''
CheckRunningState Class Initialization
< To Do: Need to document >
Input Attributes:
-----------------
self. -> SCALAR: Description.
Default =
Keyword Arguments:
------------------
self. -> STRING: Description.
Default =
self. -> OBJECT: Description.
Default =
Additional Attributes:
----------------------
self. -> BOOLEAN: Description.
Default =
Documentation last updated: Month. Day, Year - Author
'''
# -- Default Values --
# top level storage for whether or not we are running
# in a DCC tool interpreter
self._dcc_py = False
# basic python info
# if these can't run, we are in a bad state anyway
self._python = sys.version
self._py_version_info = sys.version_info
# -- Input Checks --
self.check_known()
# ---------------------------------------------------------------------
# --method-------------------------------------------------------------
def check_known(self):
# -- init --
# first let's check if any of these DCC apps are running
# 0 - maya first
CheckRunningState.DCCSI_DCC_APP = self.maya_running()
# 1 - then max
if not CheckRunningState.DCCSI_DCC_APP:
CheckRunningState.DCCSI_DCC_APP = self.max_running()
else:
_LOGGER.warning('DCCSI_DCC_APP is already set: {}'.format(CheckRunningState.DCCSI_DCC_APP))
# 2 - then blender
if not CheckRunningState.DCCSI_DCC_APP:
CheckRunningState.DCCSI_DCC_APP = self.blender_running()
else:
_LOGGER.warning('DCCSI_DCC_APP is already set: {}'.format(CheckRunningState.DCCSI_DCC_APP))
# store checks for DCC info
if CheckRunningState.DCCSI_DCC_APP:
self.dcc_py = True
# store check for is maya running headless
if CheckRunningState.DCCSI_DCC_APP == 'maya':
self.maya_headless = self.is_maya_headless()
# set a envar other modules can easily check
if CheckRunningState.DCCSI_DCC_APP:
os.environ['DCCSI_DCC_APP'] = CheckRunningState.DCCSI_DCC_APP
# ---------------------------------------------------------------------
#--properties----------------------------------------------------------
@property
def python(self):
return self._python
@python.setter
def python(self, value):
self._python = value
return self._python
@property
def py_version_info(self):
return self._py_version_info
@py_version_info.setter
def py_version_info(self, value):
self._py_version_info = value
return self._py_version_info
@property
def dcc_app(self):
return self._dcc_py
@dcc_app.setter
def dcc_app(self, value):
self._dcc_py = value
return self._dcc_py
@property
def maya_headless(self):
return self._maya_headless
@maya_headless.setter
def maya_headless(self, value):
self._maya_headless = value
return self._maya_headless
# template property
# @property
# def foo(self):
# return self._foo
# @foo.setter
# def foo(self, value):
#self._foo = value
# return self._foo
# --properties----------------------------------------------------------
# --method-------------------------------------------------------------
def maya_running(self):
"""< To Do: Need to document >"""
try:
import azpy.dev.utils.check.maya_app as check_dcc
DCCSI_DCC_APP = check_dcc.validate_state()
except ImportError as e:
_LOGGER.info('Not Implemented: azpy.dev.utils.check.maya_app')
if DCCSI_DCC_APP:
CheckRunningState.DCCSI_DCC_APP = check_dcc.validate_state()
os.environ["DCCSI_DCC_APP"] = str(DCCSI_DCC_APP)
return CheckRunningState.DCCSI_DCC_APP
#----------------------------------------------------------------------
# --method-------------------------------------------------------------
def is_maya_headless(self):
"""< To Do: Need to document >"""
if self.maya_app:
import maya.cmds as mc
try:
if mc.about(batch=True):
return True
else:
return False
except Exception as e:
# cmds module isn't fully loaded/populated
# (which only happens in batch, maya.standalone, or maya GUI)
# no maya
return False
else:
return False
# --method-------------------------------------------------------------
# --method-------------------------------------------------------------
def max_running(self):
"""
< To Do: implement >
"""
try:
import azpy.dev.utils.check.max_app as check_dcc
CheckRunningState.DCCSI_DCC_APP = check_dcc.validate_state()
except ImportError as e:
_LOGGER.info('Not Implemented: azpy.dev.utils.check.max')
if CheckRunningState.DCCSI_DCC_APP:
CheckRunningState.DCCSI_DCC_APP = check_dcc.validate_state()
os.environ["DCCSI_DCC_APP"] = str(CheckRunningState.DCCSI_DCC_APP)
return CheckRunningState.DCCSI_DCC_APP
#----------------------------------------------------------------------
# --method-------------------------------------------------------------
def blender_running(self):
"""
< To Do: implement >
"""
try:
import azpy.dev.utils.check.blender_app as check_dcc
CheckRunningState.DCCSI_DCC_APP = check_dcc.validate_state()
except ImportError as e:
_LOGGER.info('Not Implemented: azpy.dev.utils.check.blender')
if CheckRunningState.DCCSI_DCC_APP:
CheckRunningState.DCCSI_DCC_APP = check_dcc.validate_state()
os.environ["DCCSI_DCC_APP"] = str(CheckRunningState.DCCSI_DCC_APP)
return CheckRunningState.DCCSI_DCC_APP
#----------------------------------------------------------------------
#==========================================================================
# Class Test
#==========================================================================
if __name__ == '__main__':
_G_DEBUG = True
_DCCSI_DEV_MODE = True
_LOGGER.setLevel(_logging.DEBUG) # force debugging
# -- Extend Logger
#_handler = _logging.StreamHandler(sys.stdout)
# _handler.setLevel(_logging.DEBUG)
#FRMT_LOG_LONG = "[%(name)s][%(levelname)s] >> %(message)s (%(asctime)s; %(filename)s:%(lineno)d)"
#_formatter = _logging.Formatter(FRMT_LOG_LONG)
# _handler.setFormatter(_formatter)
# _LOGGER.addHandler(_handler)
#_LOGGER.debug('Loading: {0}.'.format({_MODULENAME}))
# happy print
from azpy.constants import STR_CROSSBAR
_LOGGER.info(STR_CROSSBAR)
_LOGGER.info('{} ... Running script as __main__'.format(_MODULENAME))
_LOGGER.info(STR_CROSSBAR)
foo = CheckRunningState()
_LOGGER.info('DCCSI_DCC_APP: {}'.format(foo.DCCSI_DCC_APP))