Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,52 @@
# 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 -------------------------------------------
# Sets up the project environment for python scripting using the
export DYNACONF_COMPANY=Amazon
# if a lumberyard project isn't set use this gem
export DYNACONF_LY_PROJECT=DccScriptingInterface
export DYNACONF_LY_PROJECT_PATH=`pwd`
export DYNACONF_LY_DEV=${LY_PROJECT_PATH}\..\..\..\..
# LY build folder
export DYNACONF_LY_BUILD_PATH=${LY_DEV}\windows_vs2019
export DYNACONF_LY_BIN_PATH=${LY_BUILD_PATH}\bin\profile
# default IDE and debug settings
export DYNACONF_DCCSI_GDEBUG=false
export DYNACONF_DCCSI_DEV_MODE=false
export DYNACONF_DCCSI_GDEBUGGER=WING
export DYNACONF_DCCSI_LOGLEVEL=20
# defaults for DccScriptingInterface (DCCsi)
export DYNACONF_DCCSIG_PATH=${LY_DEV}\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface
# set up default python interpreter (Lumberyard)
export DYNACONF_DCCSI_PY_VERSION_MAJOR=3
export DYNACONF_DCCSI_PY_VERSION_MINOR=7
export DYNACONF_DCCSI_PY_VERSION_RELEASE=5
export DYNACONF_DCCSI_PYTHON_PATH=${DCCSIG_PATH}\3rdParty\Python
# add access to a Lib location that matches the py version (3.7.x)
# switch this for other python version like maya (2.7.x)
export DYNACONF_DCCSI_PYTHON_LIB_PATH=${DCCSI_PYTHON_PATH}\Lib\${DCCSI_PY_VERSION_MAJOR}.x\${DCCSI_PY_VERSION_MAJOR}.${DCCSI_PY_VERSION_MINOR}.x\site-packages
# TO DO: figure out how to best deal with OS folder (i.e. 'windows')
export DYNACONF_DCCSI_PYTHON_INSTALL=${LY_DEV}\Tools\Python\${DCCSI_PY_VERSION_MAJOR}.${DCCSI_PY_VERSION_MINOR}.${DCCSI_PY_VERSION_RELEASE}\${OS_FOLDER}
export DYNACONF_DDCCSI_PY_BASE=${DCCSI_PYTHON_INSTALL}\python.exe
# set up Qt / PySide2
# TO DO: These should NOT be set in the global env as they will cause conflicts
# with other Qt apps (like DCC tools), only set in local.env, or modify config.py
# for utils/tools/apps that need them ( see config.init_ly_pyside() )
#export DYNACONF_QTFORPYTHON_PATH=${LY_DEV}\Gems\QtForPython\3rdParty\pyside2\windows\release
#export DYNACONF_QT_PLUGIN_PATH=${LY_BUILD_PATH}\bin\profile\EditorPlugins
#export DYNACONF_QT_QPA_PLATFORM_PLUGIN_PATH=${LY_BUILD_PATH}\bin\profile\EditorPlugins\platforms
@@ -0,0 +1,4 @@
# Ignore dynaconf secret files
.secrets.*
settings.local.json
@@ -0,0 +1,21 @@
*.log
*.mayaSwatches
*.ma.swatches
*.dds
*.bak
!Solutions
BinTemp
*.pyc
*.wpu
!*.wpr
!*.lnk
Cache
__*__/*
# Ignore all files in __DEV__ directories
__DEV__/*
__WIP__/*
!stub
!.p4ignore
!.gitignore
.secrets.*
settings.local.json
@@ -0,0 +1,12 @@
#
# 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.
#
add_subdirectory(Code)
@@ -0,0 +1,63 @@
#
# 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.
#
ly_add_target(
NAME DccScriptingInterface.Static STATIC
NAMESPACE Gem
FILES_CMAKE
dccscriptinginterface_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Source
PUBLIC
Include
BUILD_DEPENDENCIES
PUBLIC
AZ::AzCore
)
ly_add_target(
NAME DccScriptingInterface.Editor ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE}
NAMESPACE Gem
OUTPUT_NAME Gem.Atom_DccScriptingInterface.Editor.7bf5a77dacd8438bb4966a66b5a678d8.v0.1.0
FILES_CMAKE
dccscriptinginterface_shared_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Source
PUBLIC
Include
BUILD_DEPENDENCIES
PRIVATE
Gem::DccScriptingInterface.Static
)
################################################################################
# Tests
################################################################################
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_add_target(
NAME DccScriptingInterface.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
NAMESPACE Gem
FILES_CMAKE
dccscriptinginterface_tests_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Tests
BUILD_DEPENDENCIES
PRIVATE
AZ::AzTest
Gem::DccScriptingInterface.Static
)
ly_add_googletest(
NAME Gem::DccScriptingInterface.Tests
)
endif()
@@ -0,0 +1,34 @@
/*
* 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.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
namespace DCCScriptingInterface
{
class DCCScriptingInterfaceRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
// Put your public methods here
};
using DCCScriptingInterfaceRequestBus = AZ::EBus<DCCScriptingInterfaceRequests>;
} // namespace DCCScriptingInterface
@@ -0,0 +1,51 @@
/*
* 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.
*
*/
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Module/Module.h>
#include <DCCScriptingInterfaceSystemComponent.h>
namespace DCCScriptingInterface
{
class DCCScriptingInterfaceModule
: public AZ::Module
{
public:
AZ_RTTI(DCCScriptingInterface::DCCScriptingInterfaceModule, "{9A30C8CC-042A-4C5B-8D1F-1ABA5C58337E}", AZ::Module);
AZ_CLASS_ALLOCATOR(DCCScriptingInterfaceModule, AZ::SystemAllocator, 0);
DCCScriptingInterfaceModule()
: AZ::Module()
{
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
m_descriptors.insert(m_descriptors.end(), {
DCCScriptingInterfaceSystemComponent::CreateDescriptor(),
});
}
/**
* Add required SystemComponents to the SystemEntity.
*/
AZ::ComponentTypeList GetRequiredSystemComponents() const override
{
return AZ::ComponentTypeList {
azrtti_typeid<DCCScriptingInterfaceSystemComponent>(),
};
}
};
}
// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM
// The first parameter should be GemName_GemIdLower
// The second should be the fully qualified name of the class above
AZ_DECLARE_MODULE_CLASS(DCCScriptingInterface_7bf5a77dacd8438bb4966a66b5a678d8, DCCScriptingInterface::DCCScriptingInterfaceModule)
@@ -0,0 +1,74 @@
/*
* 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.
*
*/
#include <DCCScriptingInterfaceSystemComponent.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
namespace DCCScriptingInterface
{
void DCCScriptingInterfaceSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<DCCScriptingInterfaceSystemComponent, AZ::Component>()
->Version(0)
;
if (AZ::EditContext* ec = serialize->GetEditContext())
{
ec->Class<DCCScriptingInterfaceSystemComponent>("DCCScriptingInterface", "[Description of functionality provided by this System Component]")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System"))
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
;
}
}
}
void DCCScriptingInterfaceSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("DCCScriptingInterfaceService"));
}
void DCCScriptingInterfaceSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("DCCScriptingInterfaceService"));
}
void DCCScriptingInterfaceSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
AZ_UNUSED(required);
}
void DCCScriptingInterfaceSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
AZ_UNUSED(dependent);
}
void DCCScriptingInterfaceSystemComponent::Init()
{
}
void DCCScriptingInterfaceSystemComponent::Activate()
{
DCCScriptingInterfaceRequestBus::Handler::BusConnect();
}
void DCCScriptingInterfaceSystemComponent::Deactivate()
{
DCCScriptingInterfaceRequestBus::Handler::BusDisconnect();
}
} // namespace DCCScriptingInterface
@@ -0,0 +1,49 @@
/*
* 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.
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <DccScriptingInterface/DCCScriptingInterfaceBus.h>
namespace DCCScriptingInterface
{
class DCCScriptingInterfaceSystemComponent
: public AZ::Component
, protected DCCScriptingInterfaceRequestBus::Handler
{
public:
AZ_COMPONENT(DCCScriptingInterface::DCCScriptingInterfaceSystemComponent, "{286CFDB5-952B-4A38-AD47-DA76F8A80514}");
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
protected:
////////////////////////////////////////////////////////////////////////
// DCCScriptingInterfaceRequestBus interface implementation
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AZ::Component interface implementation
void Init() override;
void Activate() override;
void Deactivate() override;
////////////////////////////////////////////////////////////////////////
};
} // namespace DCCScriptingInterface
@@ -0,0 +1,35 @@
/*
* 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.
*
*/
#include <AzTest/AzTest.h>
class DCCScriptingInterfaceTest
: public ::testing::Test
{
protected:
void SetUp() override
{
}
void TearDown() override
{
}
};
TEST_F(DCCScriptingInterfaceTest, SanityTest)
{
ASSERT_TRUE(true);
}
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
@@ -0,0 +1,15 @@
#
# 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.
#
set(FILES
Source/DCCScriptingInterfaceSystemComponent.cpp
Source/DCCScriptingInterfaceSystemComponent.h
)
@@ -0,0 +1,14 @@
#
# 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.
#
set(FILES
"Source/DCCScriptingInterfaceModule.cpp"
)
@@ -0,0 +1,14 @@
#
# 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.
#
set(FILES
Tests/DCCScriptingInterfaceTest.cpp
)
@@ -0,0 +1,130 @@
# 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 -------------------------------------------
"""This module is for use in boostrapping the DccScriptingInterface Gem
with Lumberyard. Note: this boostrap is only designed fo be py3 compatible.
If you need DCCsi access in py27 (Autodesk Maya for instance) you may need
to implement your own boostrapper module. Currently this is boostrapped
from add_dccsi.py, as a temporty measure related to this Jira:
https://jira.agscollab.com/browse/SPEC-2581"""
# standard imports
import sys
import os
import site
import importlib.util
from pathlib import Path
import logging as _logging
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# we don't use dynaconf setting here as we might not yet have access
# to that site-dir.
_MODULE = 'DCCsi.bootstrap'
# we need to set up basic access to the DCCsi
_MODULE_PATH = os.path.realpath(__file__) # To Do: what if frozen?
_DCCSIG_PATH = os.path.normpath(os.path.join(_MODULE_PATH, '../../..'))
_DCCSIG_PATH = os.getenv('DCCSIG_PATH', _DCCSIG_PATH)
site.addsitedir(_DCCSIG_PATH)
# we can get basic access to the DCCsi.azpy api now
import azpy
# early attach WingIDE debugger (can refactor to include other IDEs later)
while 0: # flag on to attemp to connect wingIDE debugger
from azpy.env_bool import env_bool
if not env_bool('DCCSI_DEBUGGER_ATTACHED', False):
# if not already attached lets do it here
from azpy.test.entry_test import connect_wing
foo = connect_wing()
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# settings.setenv() # doing this will add the additional DYNACONF_ envars
def get_dccsi_config(DCCSIG_PATH=_DCCSIG_PATH):
"""Convenience method to set and retreive settings directly from module."""
# we can go ahead and just make sure the the DCCsi env is set
# config is SO generic this ensures we are importing a specific one
_spec_dccsi_config = importlib.util.spec_from_file_location("dccsi.config",
Path(DCCSIG_PATH,
"config.py"))
_dccsi_config = importlib.util.module_from_spec(_spec_dccsi_config)
_spec_dccsi_config.loader.exec_module(_dccsi_config)
return _dccsi_config
# -------------------------------------------------------------------------
# set and retreive the base settings on import
config = get_dccsi_config()
settings = config.get_config_settings()
# done with basic setup
# --- END -----------------------------------------------------------------
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
"""Run this file as main"""
_G_DEBUG = True
_G_TEST_PYSIDE = True
_config = get_dccsi_config()
_settings = config.get_config_settings()
_log_level = int(_settings.DCCSI_LOGLEVEL)
if _G_DEBUG:
_log_level = int(10) # force debug level
_LOGGER = azpy.initialize_logger(_MODULE,
log_to_file=True,
default_log_level=_log_level)
# we can now grab values from the DCCsi.config.py dynamic env settings
# the rest of this block is basic debug testing the dynamic settings at boot
_LOGGER.info(f'Running module: {_MODULE}')
_LOGGER.info(f'DCCSIG_PATH: {_settings.DCCSIG_PATH}')
_LOGGER.info(f'DCCSI_G_DEBUG: {_settings.DCCSI_GDEBUG}')
_LOGGER.info(f'DCCSI_DEV_MODE: {_settings.DCCSI_DEV_MODE}')
_LOGGER.info(f'OS_FOLDER: {_settings.OS_FOLDER}')
_LOGGER.info(f'LY_PROJECT: {_settings.LY_PROJECT}')
_LOGGER.info(f'LY_PROJECT_PATH: {_settings.LY_PROJECT_PATH}')
_LOGGER.info(f'LY_DEV: {_settings.LY_DEV}')
_LOGGER.info(f'LY_BUILD_PATH: {_settings.LY_BUILD_PATH}')
_LOGGER.info(f'LY_BIN_PATH: {_settings.LY_BIN_PATH}')
_LOGGER.info(f'DCCSIG_PATH: {_settings.DCCSIG_PATH}')
_LOGGER.info(f'DCCSI_PYTHON_LIB_PATH: {_settings.DCCSI_PYTHON_LIB_PATH}')
_LOGGER.info(f'DDCCSI_PY_BASE: {_settings.DDCCSI_PY_BASE}')
if _G_TEST_PYSIDE:
try:
import PySide2
except:
# set up Qt/PySide2 access and test
_settings = _config.get_config_settings(setup_ly_pyside=True)
import PySide2
_LOGGER.info(f'PySide2: {PySide2}')
_LOGGER.info(f'QTFORPYTHON_PATH: {_settings.QTFORPYTHON_PATH}')
_LOGGER.info(f'LY_BIN_PATH: {_settings.LY_BIN_PATH}')
_LOGGER.info(f'QT_PLUGIN_PATH: {_settings.QT_PLUGIN_PATH}')
_LOGGER.info(f'QT_QPA_PLATFORM_PLUGIN_PATH: {_settings.QT_QPA_PLATFORM_PLUGIN_PATH}')
_config.test_pyside2()
# --- END -----------------------------------------------------------------
@@ -0,0 +1,305 @@
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Sets up environment for Lumberyard DCC tools and code access
:: Skip initialization if already completed
IF "%DCCSI_ENV_INIT%"=="1" GOTO :END_OF_FILE
echo.
echo _____________________________________________________________________
echo.
echo ~ Setting up Default LY DCC Scripting Interface Environment ...
echo _____________________________________________________________________
echo.
:: Store current dir
%~d0
cd %~dp0
PUSHD %~dp0
IF "%DCCSI_LAUNCHERS_PATH%"=="" (set DCCSI_LAUNCHERS_PATH=%~dp0)
echo DCCSI_LAUNCHERS_PATH = %DCCSI_LAUNCHERS_PATH%
:: add to the PATH
SET PATH=%DCCSI_LAUNCHERS_PATH%;%PATH%
:: This maps up to the \Dev folder
IF "%DEV_REL_PATH%"=="" (set DEV_REL_PATH=..\..\..\..)
echo DEV_REL_PATH = %DEV_REL_PATH%
IF "%LY_PROJECT%"=="" (
ECHO !!LY_PROJECT NOT defined!!
for %%a in (%CD%..\..\..) do set LY_PROJECT=%%~na
)
echo LY_PROJECT = %LY_PROJECT%
:: set up the default project path (dccsi)
CD /D ..\..\
IF "%LY_PROJECT_PATH%"=="" (set LY_PROJECT_PATH=%CD%)
echo LY_PROJECT_PATH = %LY_PROJECT_PATH%
IF "%ABS_PATH%"=="" (set ABS_PATH=%CD%)
echo ABS_PATH = %ABS_PATH%
:: Save current directory and change to target directory
pushd %ABS_PATH%
:: Change to root Lumberyard dev dir
CD /d %LY_PROJECT_PATH%\%DEV_REL_PATH%
set LY_DEV=%CD%
echo LY_DEV = %LY_DEV%
:: Restore original directory
popd
:: dcc scripting interface gem path
set DCCSIG_PATH=%LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface
echo DCCSIG_PATH = %DCCSIG_PATH%
:: Change to root dir
CD /D %DCCSIG_PATH%
:: Constant Vars (Global)
:: global debug (propogates)
IF "%DCCSI_GDEBUG%"=="" (set DCCSI_GDEBUG=false)
echo DCCSI_GDEBUG = %DCCSI_GDEBUG%
:: initiates debugger connection
IF "%DCCSI_DEV_MODE%"=="" (set DCCSI_DEV_MODE=false)
echo DCCSI_DEV_MODE = %DCCSI_DEV_MODE%
:: sets debugger, options: WING, PYCHARM
IF "%DCCSI_GDEBUGGER%"=="" (set DCCSI_GDEBUGGER=WING)
echo DCCSI_GDEBUGGER = %DCCSI_GDEBUGGER%
:: Default level logger will handle
:: CRITICAL:50
:: ERROR:40
:: WARNING:30
:: INFO:20
:: DEBUG:10
:: NOTSET:0
IF "%DCCSI_LOGLEVEL%"=="" (set DCCSI_LOGLEVEL=20)
echo DCCSI_LOGLEVEL = %DCCSI_LOGLEVEL%
set MAYA_PROJECT=%LY_PROJECT_PATH%
echo MAYA_PROJECT = %MAYA_PROJECT%
:: add to the PATH
SET PATH=%DCCSIG_PATH%;%PATH%
:: dcc python api path
set DCCSI_AZPY_PATH=%DCCSIG_PATH%\azpy
echo DCCSI_AZPY_PATH = %DCCSI_AZPY_PATH%
:: per-dcc sdk patj
set DCCSI_SDK_PATH=%DCCSIG_PATH%\SDK
echo DCCSI_SDK_PATH = %DCCSI_SDK_PATH%
set DCCSI_LOG_PATH=%DCCSIG_PATH%\.temp\logs
echo DCCSI_LOG_PATH = %DCCSI_LOG_PATH%
echo.
:: PY version Major
IF "%DCCSI_PY_VERSION_MAJOR%"=="" (set DCCSI_PY_VERSION_MAJOR=3)
echo DCCSI_PY_VERSION_MAJOR = %DCCSI_PY_VERSION_MAJOR%
:: PY version Major
IF "%DCCSI_PY_VERSION_MINOR%"=="" (set DCCSI_PY_VERSION_MINOR=7)
echo DCCSI_PY_VERSION_MINOR = %DCCSI_PY_VERSION_MINOR%
IF "%DCCSI_PY_VERSION_RELEASE%"=="" (set DCCSI_PY_VERSION_RELEASE=5)
echo DCCSI_PY_VERSION_RELEASE = %DCCSI_PY_VERSION_RELEASE%
:: shared location for 64bit python 3.7 DEV location
set DCCSI_PYTHON_PATH=%DCCSIG_PATH%\3rdParty\Python
echo DCCSI_PYTHON_PATH = %DCCSI_PYTHON_PATH%
:: add access to a Lib location that matches the py version (3.7.x)
:: switch this for other python version like maya (2.7.x)
IF "%DCCSI_PYTHON_LIB_PATH%"=="" (set DCCSI_PYTHON_LIB_PATH=%DCCSI_PYTHON_PATH%\Lib\%DCCSI_PY_VERSION_MAJOR%.x\%DCCSI_PY_VERSION_MAJOR%.%DCCSI_PY_VERSION_MINOR%.x\site-packages)
echo DCCSI_PYTHON_LIB_PATH = %DCCSI_PYTHON_LIB_PATH%
:: add to the PATH
SET PATH=%DCCSI_PYTHON_LIB_PATH%;%PATH%
set DCCSI_PYTHON_ROOT=%LY_DEV%\Tools\Python\%DCCSI_PY_VERSION_MAJOR%.%DCCSI_PY_VERSION_MINOR%.%DCCSI_PY_VERSION_RELEASE%
echo DCCSI_PYTHON_ROOT = %DCCSI_PYTHON_ROOT%
:: shared location for Lumberyard 64bit python 3.x location
set DCCSI_PYTHON_INSTALL=%DCCSI_PYTHON_ROOT%\windows
echo DCCSI_PYTHON_INSTALL = %DCCSI_PYTHON_INSTALL%
:: add to the PATH
SET PATH=%DCCSI_PYTHON_INSTALL%;%PATH%
set LY_PY_INTERNAL=%DCCSI_PYTHON_ROOT%\internal\site-packages\windows
echo LY_PY_INTERNAL = %LY_PY_INTERNAL%
:: add to the PATH
SET PATH=%LY_PY_INTERNAL%;%PATH%
:: shared location for 64bit python 3.7 BASE location
set DCCSI_PY_BASE=%DCCSI_PYTHON_INSTALL%\python.exe
echo DCCSI_PY_BASE = %DCCSI_PY_BASE%
:: shared location for 64bit python 3.7 BASE location
set DCCSI_PY_DCCSI=%DCCSI_LAUNCHERS_PATH%\Launch_pyBASE.bat
echo DCCSI_PY_DCCSI = %DCCSI_PY_DCCSI%
:: maya sdk path
set DCCSI_SDK_MAYA_PATH=%DCCSI_SDK_PATH%\Maya
echo DCCSI_SDK_MAYA_PATH = %DCCSI_SDK_MAYA_PATH%
set MAYA_MODULE_PATH=%DCCSI_SDK_MAYA_PATH%;%MAYA_MODULE_PATH%
echo MAYA_MODULE_PATH = %MAYA_MODULE_PATH%
:: Default Maya Version
IF "%DCCSI_MAYA_VERSION%"=="" (set DCCSI_MAYA_VERSION=2020)
echo DCCSI_MAYA_VERSION = %DCCSI_MAYA_VERSION%
:: Maya File Paths, etc
:: https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/Maya/files/Environment-Variables-File-path-variables-htm.html
set MAYA_LOCATION=%ProgramFiles%\Autodesk\Maya%DCCSI_MAYA_VERSION%
echo MAYA_LOCATION = %MAYA_LOCATION%
set MAYA_BIN_PATH=%MAYA_LOCATION%\bin\
echo MAYA_BIN_PATH = %MAYA_BIN_PATH%
:: these improve the boot up time
IF "%MAYA_DISABLE_CIP%"=="" (set MAYA_DISABLE_CIP=1)
echo MAYA_DISABLE_CIP = %MAYA_DISABLE_CIP%
IF "%MAYA_DISABLE_CER%"=="" (set MAYA_DISABLE_CER=1)
echo MAYA_DISABLE_CER = %MAYA_DISABLE_CER%
IF "%MAYA_DISABLE_CLIC_IPM%"=="" (set MAYA_DISABLE_CLIC_IPM=1)
echo MAYA_DISABLE_CLIC_IPM = %MAYA_DISABLE_CLIC_IPM%
IF "%DCCSI_MAYA_SET_CALLBACKS%"=="" (set DCCSI_MAYA_SET_CALLBACKS=false)
echo DCCSI_MAYA_SET_CALLBACKS = %DCCSI_MAYA_SET_CALLBACKS%
:: setting this to 1 should further improve boot time (I think)
::IF "%MAYA_NO_CONSOLE_WINDOW%"=="" (set MAYA_NO_CONSOLE_WINDOW=0)
::echo MAYA_NO_CONSOLE_WINDOW = %MAYA_NO_CONSOLE_WINDOW%
:: shared location for 64bit DCCSI_PY_MAYA python 2.7 DEV location
set DCCSI_PY_MAYA=%MAYA_LOCATION%\bin\mayapy.exe
echo DCCSI_PY_MAYA = %DCCSI_PY_MAYA%
:: azpy Maya plugins access
:: our path
set DCCSI_MAYA_PLUG_IN_PATH=%DCCSI_SDK_MAYA_PATH%\plugins
:: also attached to maya's built-it env var
set MAYA_PLUG_IN_PATH=%DCCSI_MAYA_PLUG_IN_PATH%;MAYA_PLUG_IN_PATH
echo DCCSI_MAYA_PLUG_IN_PATH = %DCCSI_MAYA_PLUG_IN_PATH%
:: azpy Maya shelves
:: our path
set DCCSI_MAYA_SHELF_PATH=%DCCSI_SDK_MAYA_PATH%\Prefs\Shelves
set MAYA_SHELF_PATH=%DCCSI_MAYA_SHELF_PATH%
echo DCCSI_MAYA_SHELF_PATH = %DCCSI_MAYA_SHELF_PATH%
:: azpy Maya icons
:: our path
set DCCSI_MAYA_XBMLANGPATH=%DCCSI_SDK_MAYA_PATH%\Prefs\icons
:: also attached to maya's built-it env var
set XBMLANGPATH=%DCCSI_MAYA_XBMLANGPATH%;%XBMLANGPATH%
echo DCCSI_MAYA_XBMLANGPATH = %DCCSI_MAYA_XBMLANGPATH%
:: azpy root Maya boostrap, userSetup.py access
:: our path
set DCCSI_MAYA_SCRIPT_PATH=%DCCSI_SDK_MAYA_PATH%\Scripts
:: also attached to maya's built-it env var
set MAYA_SCRIPT_PATH=%DCCSI_MAYA_SCRIPT_PATH%;%MAYA_SCRIPT_PATH%
echo DCCSI_MAYA_SCRIPT_PATH = %DCCSI_MAYA_SCRIPT_PATH%
:: azpy Maya Mel scripts
:: our path
set DCCSI_MAYA_SCRIPT_MEL_PATH=%DCCSI_SDK_MAYA_PATH%\Scripts\Mel
:: also attached to maya's built-it env var
set MAYA_SCRIPT_PATH=%DCCSI_MAYA_SCRIPT_MEL_PATH%;%MAYA_SCRIPT_PATH%
echo DCCSI_MAYA_SCRIPT_MEL_PATH = %DCCSI_MAYA_SCRIPT_MEL_PATH%
:: azpy Maya Py scripts
:: our path
set DCCSI_MAYA_SCRIPT_PY_PATH=%DCCSI_SDK_MAYA_PATH%\Scripts\Python
:: also attached to maya's built-it env var
set MAYA_SCRIPT_PATH=%DCCSI_MAYA_SCRIPT_PY_PATH%;%MAYA_SCRIPT_PATH%
echo DCCSI_MAYA_SCRIPT_PY_PATH = %DCCSI_MAYA_SCRIPT_PY_PATH%
:: azpy add all python related paths to PYTHONPATH
::set PYTHONPATH=%DCCSIG_PATH%;%DCCSI_AZPY_PATH%;%DCCSI_SDK_MAYA_PATH%;%DCCSI_MAYA_SCRIPT_PATH%;%DCCSI_MAYA_SCRIPT_PY_PATH%;%PYTHONPATH%
set PYTHONPATH=%LY_PY_INTERNAL%;%DCCSIG_PATH%;%DCCSI_PYTHON_LIB_PATH%;%DCCSI_MAYA_SCRIPT_PATH%;%DCCSI_MAYA_SCRIPT_PY_PATH%;%PYTHONPATH%
echo PYTHONPATH = %PYTHONPATH%
:: build path
IF "%TAG_LY_BUILD_PATH%"=="" (set TAG_LY_BUILD_PATH=windows_vs2019)
echo TAG_LY_BUILD_PATH = %TAG_LY_BUILD_PATH%
IF "%LY_BUILD_PATH%"=="" (set LY_BUILD_PATH=%LY_DEV%\%TAG_LY_BUILD_PATH%)
echo LY_BUILD_PATH = %LY_BUILD_PATH%
:: Substance Designer
:: maya sdk path
set DCCSI_SUBSTANCE_PATH=%DCCSI_SDK_PATH%\Substance
echo DCCSI_SUBSTANCE_PATH = %DCCSI_SUBSTANCE_PATH%
:: https://docs.substance3d.com/sddoc/project-preferences-107118596.html#ProjectPreferences-ConfigurationFile
:: Path to .exe, "C:\Program Files\Allegorithmic\Substance Designer\Substance Designer.exe"
set SUBSTANCE_PATH="%ProgramFiles%\Allegorithmic\Substance Designer"
echo SUBSTANCE_PATH = %SUBSTANCE_PATH%
:: default config
set SUBSTANCE_CFG_PATH=%LY_PROJECT_PATH%\DCCsi_default.sbscfg
echo SUBSTANCE_CFG_PATH = %SUBSTANCE_CFG_PATH%
:: WingIDE version Major
IF "%DCCSI_WING_VERSION_MAJOR%"=="" (set DCCSI_WING_VERSION_MAJOR=7)
echo DCCSI_WING_VERSION_MAJOR = %DCCSI_WING_VERSION_MAJOR%
:: WingIDE version Major
IF "%DCCSI_WING_VERSION_MINOR%"=="" (set DCCSI_WING_VERSION_MINOR=1)
echo DCCSI_WING_VERSION_MINOR = %DCCSI_WING_VERSION_MINOR%
:: put project env variables/paths here
set WINGHOME=%PROGRAMFILES(X86)%\Wing Pro %DCCSI_WING_VERSION_MAJOR%.%DCCSI_WING_VERSION_MINOR%
echo WINGHOME = %WINGHOME%
:: add to the PATH
SET PATH=%WINGHOME%;%PATH%
:: ide and debugger plugs
set DCCSI_PY_DEFAULT=%DCCSI_PY_BASE%
:: add prefered python to the PATH
SET PATH=%DCCSIG_PATH%;%DCCSI_AZPY_PATH%;%DCCSI_PY_DEFAULT%;%PATH%
echo PATH = %PATH%
:: Change to root dir
CD /D %ABS_PATH%
:: if the user has set up a custom env call it
IF EXIST "%~dp0Env_Dev.bat" CALL %~dp0Env_Dev.bat
echo.
echo _____________________________________________________________________
echo.
echo ~ Default DCCsi Environment ...
echo _____________________________________________________________________
echo.
:: Set flag so we don't initialize dccsi environment twice
SET DCCSI_ENV_INIT=1
GOTO END_OF_FILE
:: Return to starting directory
POPD
:END_OF_FILE
@@ -0,0 +1,49 @@
:: Need to set up
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Set up and run LY Python CMD prompt
:: Sets up the DccScriptingInterface_Env,
:: Puts you in the CMD within the dev environment
:: Set up window
TITLE Lumberyard DCC Scripting Interface Cmd
:: Use obvious color to prevent confusion (Grey with Yellow Text)
COLOR 8E
%~d0
cd %~dp0
PUSHD %~dp0
:: Keep changes local
SETLOCAL
CALL %~dp0\Env.bat
echo.
echo _____________________________________________________________________
echo.
echo ~ LY DCC Scripting Interface CMD ...
echo _____________________________________________________________________
echo.
:: Create command prompt with environment
CALL %windir%\system32\cmd.exe
ENDLOCAL
:: Return to starting directory
POPD
:END_OF_FILE
@@ -0,0 +1,73 @@
:: Launches maya wityh a bunch of local hooks for Lumberyard
:: ToDo: move all of this to a .json data driven boostrapping system
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
echo ________________________________
echo ~ calling DccScriptingInterface_Env.bat
%~d0
cd %~dp0
PUSHD %~dp0
:: Keep changes local
SETLOCAL enableDelayedExpansion
:: PY version Major
set DCCSI_PY_VERSION_MAJOR=2
echo DCCSI_PY_VERSION_MAJOR = %DCCSI_PY_VERSION_MAJOR%
:: PY version Major
set DCCSI_PY_VERSION_MINOR=7
echo DCCSI_PY_VERSION_MINOR = %DCCSI_PY_VERSION_MINOR%
:: Default Maya Version
set MAYA_VERSION=2020
echo MAYA_VERSION = %MAYA_VERSION%
:: if a local customEnv.bat exists, run it
IF EXIST "%~dp0Env.bat" CALL %~dp0Env.bat
echo ________________________________
echo Launching Maya %MAYA_VERSION% for LY DCCsi...
::set MAYA_PATH="D:\Program Files\Autodesk\Maya2019"
echo MAYA_PATH = %MAYA_PATH%
:::: Set Maya native project acess to this project
::set MAYA_PROJECT=%LY_PROJECT%
::echo MAYA_PROJECT = %MAYA_PROJECT%
:: DX11 Viewport
Set MAYA_VP2_DEVICE_OVERRIDE=VirtualDeviceDx11
:: Default to the right version of Maya if we can detect it... and launch
IF EXIST "C:\Program Files\Autodesk\Maya%MAYA_VERSION%\bin\maya.exe" (
start "" "C:\Program Files\Autodesk\Maya%MAYA_VERSION%\bin\maya.exe" %*
) ELSE (
Where maya.exe 2> NUL
IF ERRORLEVEL 1 (
echo Maya.exe could not be found
pause
) ELSE (
start "" Maya.exe %*
)
)
:: Return to starting directory
POPD
:END_OF_FILE
exit /b 0
@@ -0,0 +1,93 @@
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Launches Wing IDE and the DccScriptingInterface Project Files
:: version Major
SET PYCHARM_VERSION_YEAR=2020
echo PYCHARM_VERSION_YEAR = %PYCHARM_VERSION_YEAR%
:: version Major
SET PYCHARM_VERSION_MAJOR=2
echo PYCHARM_VERSION_MAJOR = %PYCHARM_VERSION_MAJOR%
@echo off
:: Set up window
TITLE Lumberyard DCC Scripting Interface GEM PyCharm CE %PYCHARM_VERSION_YEAR%.%PYCHARM_VERSION_MAJOR%.%PYCHARM_VERSION_MINOR%
:: Use obvious color to prevent confusion (Grey with Yellow Text)
COLOR 8E
echo.
echo _____________________________________________________________________
echo.
echo ~ Setting up LY DCC SIG PyCharm Dev Env...
echo _____________________________________________________________________
echo.
:: Store current dir
%~d0
cd %~dp0
PUSHD %~dp0
SET ABS_PATH=%~dp0
echo ~ Current Dir, %ABS_PATH%
:: Keep changes local
SETLOCAL
CALL %~dp0\Env.bat
echo.
echo _____________________________________________________________________
echo.
echo ~ Setting up Env for PyCharm CE %PYCHARM_VERSION_YEAR%.%PYCHARM_VERSION_MAJOR%.%PYCHARM_VERSION_MINOR%
echo _____________________________________________________________________
echo.
::"C:\Program Files\JetBrains\PyCharm 2019.1.3\bin"
::"C:\Program Files\JetBrains\PyCharm Community Edition 2018.3.5\bin\pycharm64.exe"
:: put project env variables/paths here
set PYCHARM_HOME=%PROGRAMFILES%\JetBrains\PyCharm %PYCHARM_VERSION_YEAR%.%PYCHARM_VERSION_MAJOR%
echo PYCHARM_HOME = %PYCHARM_HOME%
SET PYCHARM_PROJ=%DCCSIG_PATH%\Solutions
echo PYCHARM_PROJ = %PYCHARM_PROJ%
echo.
echo _____________________________________________________________________
echo.
echo ~ Launching DCCsi Project in PyCharm %PYCHARM_VERSION_YEAR%.%PYCHARM_VERSION_MAJOR% ...
echo _____________________________________________________________________
echo.
IF EXIST "%PYCHARM_HOME%\bin\pycharm64.exe" (
start "" "%PYCHARM_HOME%\bin\pycharm64.exe" "%PYCHARM_PROJ%"
) ELSE (
Where pycharm64.exe 2> NUL
IF ERRORLEVEL 1 (
echo pycharm64.exe could not be found
pause
) ELSE (
start "" pycharm64.exe "%PYCHARM_PROJ%"
)
)
ENDLOCAL
:: Return to starting directory
POPD
:END_OF_FILE
@@ -0,0 +1,63 @@
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Set up and run LY Python CMD prompt
:: Sets up the DccScriptingInterface_Env,
:: Puts you in the CMD within the dev environment
:: Set up window
TITLE Lumberyard DCC Scripting Interface Cmd
:: Use obvious color to prevent confusion (Grey with Yellow Text)
COLOR 8E
%~d0
cd %~dp0
:: Keep changes local
SETLOCAL enableDelayedExpansion
:: This maps up to the \Dev folder
IF "%DEV_REL_PATH%"=="" (set DEV_REL_PATH=..\..\..\..\..\..\)
:: Change to root Lumberyard dev dir
:: Don't use the LY_DEV so we can test that ENVAR!!!
CD /d %DEV_REL_PATH%
set Rel_Dev=%CD%
echo Rel_Dev = %Rel_Dev%
:: Restore original directory
popd
set DCCSI_PYTHON_INSTALL=%Rel_Dev%\Tools\Python\3.7.5\windows
:: add to the PATH
SET PATH=%DCCSI_PYTHON_INSTALL%;%PATH%
set DCCSI_PY_BASE=%DCCSI_PYTHON_INSTALL%\python.exe
echo DCCSI_PY_BASE = %DCCSI_PY_BASE%
echo.
echo _____________________________________________________________________
echo.
echo ~ LY DCC Scripting Interface, Py Min Env CMD ...
echo _____________________________________________________________________
echo.
:: Create command prompt with environment
CALL %windir%\system32\cmd.exe
ENDLOCAL
:: Return to starting directory
POPD
:END_OF_FILE
@@ -0,0 +1,108 @@
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Launches Wing IDE and the DccScriptingInterface Project Files
:: Set up window
TITLE Lumberyard DCC Scripting Interface GEM WingIDE 7x
:: Use obvious color to prevent confusion (Grey with Yellow Text)
COLOR 8E
echo.
echo _____________________________________________________________________
echo.
echo ~ Setting up LY DCCsi WingIDE Dev Env...
echo _____________________________________________________________________
echo.
:: Store current dir
%~d0
cd %~dp0
PUSHD %~dp0
:: Keep changes local
SETLOCAL enableDelayedExpansion
SET ABS_PATH=%~dp0
echo ABS_PATH = %ABS_PATH%
:: WingIDE version Major
set WING_VERSION_MAJOR=7
echo WING_VERSION_MAJOR = %WING_VERSION_MAJOR%
:: WingIDE version Major
set WING_VERSION_MINOR=1
echo WING_VERSION_MINOR = %WING_VERSION_MINOR%
:: note the changed path from IDE to Pro
set WINGHOME=%PROGRAMFILES(X86)%\Wing Pro %WING_VERSION_MAJOR%.%WING_VERSION_MINOR%
echo WINGHOME = %WINGHOME%
:: Constant Vars (Global)
:: global debug (propogates)
IF "%DCCSI_GDEBUG%"=="" (set DCCSI_GDEBUG=True)
echo DCCSI_GDEBUG = %DCCSI_GDEBUG%
:: initiates debugger connection
IF "%DCCSI_DEV_MODE%"=="" (set DCCSI_DEV_MODE=True)
echo DCCSI_DEV_MODE = %DCCSI_DEV_MODE%
:: sets debugger, options: WING, PYCHARM
IF "%DCCSI_GDEBUGGER%"=="" (set DCCSI_GDEBUGGER=WING)
echo DCCSI_GDEBUGGER = %DCCSI_GDEBUGGER%
:: Default level logger will handle
:: CRITICAL:50
:: ERROR:40
:: WARNING:30
:: INFO:20
:: DEBUG:10
:: NOTSET:0
IF "%DCCSI_LOGLEVEL%"=="" (set DCCSI_LOGLEVEL=10)
echo DCCSI_LOGLEVEL = %DCCSI_LOGLEVEL%
CALL %~dp0\Env.bat
echo.
echo _____________________________________________________________________
echo.
echo ~ WingIDE Version %WING_VERSION_MAJOR%.%WING_VERSION_MINOR%
echo _____________________________________________________________________
echo.
SET WING_PROJ=%DCCSIG_PATH%\Solutions\.wing\DCCsi_%WING_VERSION_MAJOR%x.wpr
echo WING_PROJ = %WING_PROJ%
echo.
echo _____________________________________________________________________
echo.
echo ~ Launching %LY_PROJECT% project in WingIDE %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% ...
echo _____________________________________________________________________
echo.
IF EXIST "%WINGHOME%\bin\wing.exe" (
start "" "%WINGHOME%\bin\wing.exe" "%WING_PROJ%"
) ELSE (
Where wing.exe 2> NUL
IF ERRORLEVEL 1 (
echo wing.exe could not be found
pause
) ELSE (
start "" wing.exe "%WING_PROJ%"
)
)
ENDLOCAL
:: Return to starting directory
POPD
:END_OF_FILE
@@ -0,0 +1,60 @@
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Store current directory and change to environment directory so script works in any path.
%~d0
cd %~dp0
PUSHD %~dp0
:: Keep changes local
SETLOCAL enableDelayedExpansion
:: PY version Major
set DCCSI_PY_VERSION_MAJOR=2
echo DCCSI_PY_VERSION_MAJOR = %DCCSI_PY_VERSION_MAJOR%
:: PY version Major
set DCCSI_PY_VERSION_MINOR=7
echo DCCSI_PY_VERSION_MINOR = %DCCSI_PY_VERSION_MINOR%
:: Default Maya Version
set MAYA_VERSION=2019
echo MAYA_VERSION = %MAYA_VERSION%
:: Initialize env
CALL %~dp0\Env.bat
echo ~ Launching LY Dc cScripting Interfacw MayaPy (%MAYA_VERSION%) ...
echo ________________________________________________________________
echo.
:: Start Maya
:: Default to the right version of Maya if we can detect it.
Set MAYA_VP2_DEVICE_OVERRIDE = VirtualDeviceDx11
IF EXIST "%DCCSI_PY_MAYA%" (
CALL "%DCCSI_PY_MAYA%" %*
) ELSE (
Where mayapy.exe 2> NUL
IF ERRORLEVEL 1 (
echo mayapy.exe could not be found
pause
) ELSE (
start "" mayapy.exe %*
)
)
ENDLOCAL
:: Restore previous directory
POPD
@@ -0,0 +1,60 @@
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Store current directory and change to environment directory so script works in any path.
%~d0
cd %~dp0
PUSHD %~dp0
:: Keep changes local
SETLOCAL enableDelayedExpansion
:: PY version Major
set DCCSI_PY_VERSION_MAJOR=2
echo DCCSI_PY_VERSION_MAJOR = %DCCSI_PY_VERSION_MAJOR%
:: PY version Major
set DCCSI_PY_VERSION_MINOR=7
echo DCCSI_PY_VERSION_MINOR = %DCCSI_PY_VERSION_MINOR%
:: Default Maya Version
set MAYA_VERSION=2020
echo MAYA_VERSION = %MAYA_VERSION%
:: Initialize env
CALL %~dp0\Env.bat
echo ~ Launching LY Dc cScripting Interfacw MayaPy (%MAYA_VERSION%) ...
echo ________________________________________________________________
echo.
:: Start Maya
:: Default to the right version of Maya if we can detect it.
Set MAYA_VP2_DEVICE_OVERRIDE = VirtualDeviceDx11
IF EXIST "%DCCSI_PY_MAYA%" (
CALL "%DCCSI_PY_MAYA%" %*
) ELSE (
Where mayapy.exe 2> NUL
IF ERRORLEVEL 1 (
echo mayapy.exe could not be found
pause
) ELSE (
start "" mayapy.exe %*
)
)
ENDLOCAL
:: Restore previous directory
POPD
@@ -0,0 +1,59 @@
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Set up and run LY Python CMD prompt
:: Sets up the DccScriptingInterface_Env,
:: Puts you in the CMD within the dev environment
:: Set up window
TITLE DCCsi (miniconda3)
:: Use obvious color to prevent confusion (Grey with Yellow Text)
COLOR 8E
%~d0
cd %~dp0
PUSHD %~dp0
:: Keep changes local
:: SETLOCAL enableDelayedExpansion
CALL %~dp0\Env.bat
:: These need to be ADDED to any env or launcher that is py3.7+ and needs PySide2 access
:: This bootstraps LUMBERYARDS Qt binaraies and PySide2 packages (which likely won't work in other versions of python)
:: If you set these in the env.bat it will cause some Qt apps like WingIDE from starting correctly
:: Those apps provide their own Qt bins and Pyside packages (Wing, Substance, Maya, etc.)
:: set up Qt/Pyside paths
:: set up PySide2/Shiboken
set QTFORPYTHON_PATH=%LY_DEV%\Gems\QtForPython\3rdParty\pyside2\windows\release
echo QTFORPYTHON_PATH = %QTFORPYTHON_PATH%
:: add to the PATH
SET PATH=%QTFORPYTHON_PATH%;%PATH%
SET PYTHONPATH=%QTFORPYTHON_PATH%;%PYTHONPATH%
set QT_PLUGIN_PATH=%LY_BUILD_PATH%\bin\profile\EditorPlugins
echo QT_PLUGIN_PATH = %QT_PLUGIN_PATH%
:: add to the PATH
SET PATH=%QT_PLUGIN_PATH%;%PATH%
SET PYTHONPATH=%QT_PLUGIN_PATH%;%PYTHONPATH%
set LY_BIN_PATH=%LY_BUILD_PATH%\bin\profile
echo LY_BIN_PATH = %LY_BIN_PATH%
SET PATH=%LY_BIN_PATH%;%PATH%
echo Starting: %DCCSI_PYTHON_INSTALL%\python.exe
call %DCCSI_PYTHON_INSTALL%\python.exe %*
@@ -0,0 +1,65 @@
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Set up and run LY Python CMD prompt
:: Sets up the DccScriptingInterface_Env,
:: Puts you in the CMD within the dev environment
:: Set up window
TITLE DCCsi (miniconda3)
:: Use obvious color to prevent confusion (Grey with Yellow Text)
COLOR 8E
%~d0
cd %~dp0
PUSHD %~dp0
:: Keep changes local
:: SETLOCAL enableDelayedExpansion
CALL %~dp0\Env.bat
:: These need to be ADDED to any env or launcher that is py3.7+ and needs PySide2 access
:: This bootstraps LUMBERYARDS Qt binaraies and PySide2 packages (which likely won't work in other versions of python)
:: If you set these in the env.bat it will cause some Qt apps like WingIDE from starting correctly
:: Those apps provide their own Qt bins and Pyside packages (Wing, Substance, Maya, etc.)
:: set up Qt/Pyside paths
:: set up PySide2/Shiboken
set QTFORPYTHON_PATH=%LY_DEV%\Gems\QtForPython\3rdParty\pyside2\windows\release
echo QTFORPYTHON_PATH = %QTFORPYTHON_PATH%
:: add to the PATH
SET PATH=%QTFORPYTHON_PATH%;%PATH%
SET PYTHONPATH=%QTFORPYTHON_PATH%;%PYTHONPATH%
set QT_PLUGIN_PATH=%LY_BUILD_PATH%\bin\profile\EditorPlugins
echo QT_PLUGIN_PATH = %QT_PLUGIN_PATH%
:: add to the PATH
SET PATH=%QT_PLUGIN_PATH%;%PATH%
SET PYTHONPATH=%QT_PLUGIN_PATH%;%PYTHONPATH%
set LY_BIN_PATH=%LY_BUILD_PATH%\bin\profile
echo LY_BIN_PATH = %LY_BIN_PATH%
SET PATH=%LY_BIN_PATH%;%PATH%
:: Create command prompt with environment
CALL %windir%\system32\cmd.exe
ENDLOCAL
:: Return to starting directory
POPD
:END_OF_FILE
@@ -0,0 +1,67 @@
:: Need to set up
@echo off
REM
REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
REM its licensors.
REM
REM For complete copyright and license terms please see the LICENSE at the root of this
REM distribution (the "License"). All use of this software is governed by the License,
REM or, if provided, by the license below or the license accompanying this file. Do not
REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM
:: Set up window
TITLE Launcher Substance Builder
:: Use obvious color to prevent confusion (Grey with Yellow Text)
COLOR 8E
%~d0
cd %~dp0
PUSHD %~dp0
:: Keep changes local
SETLOCAL enableDelayedExpansion
:: These need to be ADDED to any env or launcher that is py3.7+ and needs PySide2 access
:: This bootstraps LUMBERYARDS Qt binaraies and PySide2 packages (which likely won't work in other versions of python)
:: If you set these in the env.bat it will cause some Qt apps like WingIDE from starting correctly
:: Those apps provide their own Qt bins and Pyside packages (Wing, Substance, Maya, etc.)
:: set up Qt/Pyside paths
:: set up PySide2/Shiboken
set QTFORPYTHON_PATH=%LY_DEV%\Gems\QtForPython\3rdParty\pyside2\windows\release
echo QTFORPYTHON_PATH = %QTFORPYTHON_PATH%
:: add to the PATH
SET PATH=%QTFORPYTHON_PATH%;%PATH%
SET PYTHONPATH=%QTFORPYTHON_PATH%;%PYTHONPATH%
set QT_PLUGIN_PATH=%LY_BUILD_PATH%\bin\profile\EditorPlugins
echo QT_PLUGIN_PATH = %QT_PLUGIN_PATH%
:: add to the PATH
SET PATH=%QT_PLUGIN_PATH%;%PATH%
SET PYTHONPATH=%QT_PLUGIN_PATH%;%PYTHONPATH%
set LY_BIN_PATH=%LY_BUILD_PATH%\bin\profile
echo LY_BIN_PATH = %LY_BIN_PATH%
SET PATH=%LY_BIN_PATH%;%PATH%
:: if a local customEnv.bat exists, run it
IF EXIST "%~dp0Env.bat" CALL %~dp0Env.bat
echo ~ Launching DCCsi Substance Builder ...
echo ________________________________________________________________
echo.
call Launch_pyBASE "%DCCSIG_PATH%\SDK\substance\builder\sb_gui_main.py"
:: Return to starting directory
POPD
:END_OF_FILE
exit /b 0
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:083ab199e273431963fc5f80bb80b7d1b1d428f7b12a5180d7199a7431291982
size 311865
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:083ab199e273431963fc5f80bb80b7d1b1d428f7b12a5180d7199a7431291982
size 311865
@@ -0,0 +1,36 @@
//Maya 2016 Project Definition
workspace -fr "fluidCache" "cache/nCache/fluid";
workspace -fr "images" "images";
workspace -fr "offlineEdit" "scenes/edits";
workspace -fr "furShadowMap" "renderData/fur/furShadowMap";
workspace -fr "iprImages" "renderData/iprImages";
workspace -fr "renderData" "renderData";
workspace -fr "scripts" "scripts";
workspace -fr "fileCache" "cache/nCache";
workspace -fr "eps" "data";
workspace -fr "shaders" "renderData/shaders";
workspace -fr "3dPaintTextures" "sourceimages/3dPaintTextures";
workspace -fr "translatorData" "data";
workspace -fr "mel" "scripts";
workspace -fr "furFiles" "renderData/fur/furFiles";
workspace -fr "OBJ" "data";
workspace -fr "particles" "cache/particles";
workspace -fr "scene" "scenes";
workspace -fr "furEqualMap" "renderData/fur/furEqualMap";
workspace -fr "sourceImages" "sourceimages";
workspace -fr "furImages" "renderData/fur/furImages";
workspace -fr "clips" "clips";
workspace -fr "depth" "renderData/depth";
workspace -fr "movie" "movies";
workspace -fr "audio" "sound";
workspace -fr "bifrostCache" "cache/bifrost";
workspace -fr "autoSave" "autosave";
workspace -fr "mayaAscii" "scenes";
workspace -fr "move" "data";
workspace -fr "sound" "sound";
workspace -fr "diskCache" "data";
workspace -fr "illustrator" "data";
workspace -fr "mayaBinary" "scenes";
workspace -fr "templates" "assets";
workspace -fr "furAttrMap" "renderData/fur/furAttrMap";
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1318f73ca32ec56dfeb0233679504f6fc723081f0cafa8e7e2d0517b878defd1
size 2000893
@@ -0,0 +1,69 @@
//Maya 2016 Project Definition
workspace -fr "fluidCache" "mayaData/cache/nCache/fluid";
workspace -fr "JT_DC" "mayaData/Trans/JT";
workspace -fr "CATIAV4_DC" "mayaData/Trans/CATIAV4";
workspace -fr "images" "mayaData/Images";
workspace -fr "offlineEdit" "ArtSource/Maya";
workspace -fr "STEP_DC" "mayaData/Trans/STEP";
workspace -fr "furShadowMap" "mayaData/renderData/fur/furShadowMap";
workspace -fr "SPF_DCE" "mayaData/Trans/SPF";
workspace -fr "scripts" "mayaData/Scripts";
workspace -fr "CATIAV5_DC" "mayaData/Trans/CATIAV5";
workspace -fr "DAE_FBX" "mayaData/Trans/DAE_FBX";
workspace -fr "shaders" "mayaData/renderData/shaders";
workspace -fr "furFiles" "mayaData/renderData/fur/furFiles";
workspace -fr "OBJ" "mayaData/OBJ";
workspace -fr "FBX export" "mayaData/Trans/FBX_export";
workspace -fr "furEqualMap" "mayaData/renderData/fur/furEqualMap";
workspace -fr "Autodesk Packet File" "mayaData/Trans";
workspace -fr "DAE_FBX export" "mayaData/Trans/DAE_FBX_export";
workspace -fr "SPF_DC" "mayaData/Trans/SPF";
workspace -fr "movie" "mayaData/movies";
workspace -fr "DXF_DCE" "mayaData/Trans/DXF";
workspace -fr "move" "mayaData/move";
workspace -fr "mayaAscii" "ArtSource";
workspace -fr "autoSave" "mayaData";
workspace -fr "sound" "mayaData/Sounds";
workspace -fr "mayaBinary" "ArtSource";
workspace -fr "ZPR_DCE" "mayaData/Trans/ZPR";
workspace -fr "STL_DCE" "mayaData/Trans/STL";
workspace -fr "iprImages" "mayaData/renderData/iprImages";
workspace -fr "PhysX" "mayaData/Trans/Physx";
workspace -fr "DXF_DC" "mayaData/Trans/DXF";
workspace -fr "FBX" "mayaData/Trans/FBX";
workspace -fr "studioImport" "mayaData/Trans";
workspace -fr "UG_DCE" "mayaData/Trans/UG";
workspace -fr "renderData" "mayaData/renderData";
workspace -fr "fileCache" "mayaData/cache/nCache";
workspace -fr "eps" "mayaData/EPS";
workspace -fr "Fbx" "Objects";
workspace -fr "3dPaintTextures" "mayaData/images/3dPaintTextures";
workspace -fr "translatorData" "mayaData";
workspace -fr "mel" "mayaData/Scripts/Mel";
workspace -fr "particles" "mayaData/cache/particles";
workspace -fr "IV_DC" "mayaData/Trans/IV";
workspace -fr "scene" "ArtSource";
workspace -fr "DWG_DCE" "mayaData/Trans/DWG";
workspace -fr "MayaCryExport" "Objects";
workspace -fr "sourceImages" "ArtSource/Textures";
workspace -fr "furImages" "mayaData/renderData/fur/furImages";
workspace -fr "clips" "mayaData/clips";
workspace -fr "PTC_DC" "mayaData/Trans/PTC";
workspace -fr "STL_DC" "mayaData/Trans/STL";
workspace -fr "IPT_DC" "mayaData/Trans/IPT";
workspace -fr "CSB_DC" "mayaData/Trans/CSB";
workspace -fr "SW_DC" "mayaData/Trans/SW";
workspace -fr "depth" "mayaData/renderData/depth";
workspace -fr "audio" "mayaData/Sounds";
workspace -fr "DWG_DC" "mayaData/Trans/DWG";
workspace -fr "bifrostCache" "mayaData/cache/bifrost";
workspace -fr "IGES_DCE" "mayaData/Trans/IGES";
workspace -fr "Alembic" "mayaData/Trans/Alembic";
workspace -fr "illustrator" "mayaData/AI";
workspace -fr "diskCache" "mayaData";
workspace -fr "UG_DC" "mayaData/Trans/UG";
workspace -fr "templates" "mayaData/assets";
workspace -fr "OBJexport" "mayaData/Trans/Obj";
workspace -fr "furAttrMap" "mayaData/renderData/fur/furAttrMap";
workspace -fr "IGES_DC" "mayaData/Trans/IGES";
@@ -0,0 +1,55 @@
{
"description": "",
"materialType": "Materials/Types/StandardPBR.materialtype",
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"ambientOcclusion": {
"factor": 1.0,
"useTexture": true,
"textureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif"
},
"baseColor": {
"color": [ 1.0, 1.0, 1.0 ],
"factor": 1.0,
"useTexture": true,
"textureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif"
},
"emissive": {
"color": [ 1.0, 1.0, 1.0 ],
"intensity": 1.0,
"useTexture": false,
"textureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif"
},
"metallic": {
"factor": 0.0,
"useTexture": false,
"textureMap": ""
},
"roughness": {
"factor": 1.0,
"useTexture": true,
"textureMap": "EngineAssets/TextureMsg/DefaultNoUVs_spec.tif"
},
"specularF0": {
"factor": 0.5,
"useTexture": false,
"textureMap": ""
},
"normal": {
"factor": 1.0,
"useTexture": true,
"textureMap": "EngineAssets/TextureMsg/DefaultNoUVs_ddn.tif"
},
"opacity": {
"doubleSided": false,
"factor": 1.0,
"cutoutAlpha": false,
"cutoutThreshold": 0.5,
"useBaseColorTextureAlpha": false,
"useTexture": false,
"textureMap": ""
}
}
}
@@ -0,0 +1,14 @@
# 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.
#
__all__ = ['atom_mat',
'fbx_to_atom',
'stingraypbs_converter',
'stingraypbs_converter_maya']
@@ -0,0 +1,66 @@
# 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 -------------------------------------------
"""
Module Documentation: To Do
"""
# -------------------------------------------------------------------------
# built-ins
import json
# 3rdParty
from box import Box
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
class AtomMaterial:
def __init__(self, material_file):
'''To Do: document'''
# loading .material Files
self.material_file = material_file
self.input_data = open(self.material_file, "r")
self.material = json.load(self.input_data)
self.mat_box = Box(self.material)
self.input_data.close()
# Texture map dictionary:
self.texture_map = {'ambientOcclusion': 'ambientOcclusion',
'baseColor': 'baseColor',
'emissive': 'emissive',
'metallic': 'metallic',
'roughness': 'roughness',
'specularF0': 'specular',
'normal': 'normal',
'opacity': 'opacity'
}
def load(self, material_file):
input_data = open(material_file, "r")
self.material = json.load(input_data)
self.mat_box = Box(self.material)
input_data.close()
def getBaseMaterial(self):
return self.mat_box.material.baseMaterial
def getMap(self, tex_slot):
return self.mat_box.properties[tex_slot].textureMap
def setMap(self, tex_slot, tex_map):
self.mat_box.properties[tex_slot].textureMap = tex_map
self.mat_box.properties[tex_slot].useTexture = True
self.mat_box.properties[tex_slot].factor = 1.0
def write(self, material_out):
output_data = open(material_out, "w+")
output_data.write(json.dumps(self.mat_box, indent=4))
output_data.close()
# -------------------------------------------------------------------------
@@ -0,0 +1,67 @@
# 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 -------------------------------------------
import simplejson as json
from box import Box
from atom_mat import AtomMaterial as atomMat
"""
The idea behind this script is to convert FBX to glTF in order to take advantage of glTF format
FBX2glTF CLT:
https://github.com/facebookincubator/FBX2glTF
ToDo:
Add FBX2glTF subprocess to the script.
"""
atom_material = atomMat("C:\\atom\\dev\\AtomTest\\Editor\\Scripts\\atom\\maya\\StandardPBR_AllProperties.material")
""" All these path could be in configure file or bootstrapped """
fbx_root = 'C:\\atom\\dev\\Gems\\AtomContent\\AtomDemoContent\\Assets\\Objects\\Peccy\\'
rel_root = "C:\\atom\\dev\\Gems\\AtomContent\\AtomDemoContent\\Assets\\"
texture_root = 'Objects\\Peccy\\'
# -------------------------------------------------------------------------
class FBX:
def __init__(self, fbx_file):
self.fbx_file = fbx_file
self.glTF_file = self.fbx_file.replace("fbx", "gltf")
self.input_data = open(self.glTF_file, "r")
self.glTF_properties = json.load(self.input_data)
self.glTF_box = Box(self.glTF_properties)
self.input_data.close()
def get_material_names(self):
return self.glTF_box.materials
def get_textures(self, index):
return self.glTF_box.images[index]
def create_atom_material(self):
for mat_index in range(len(fbx01.get_material_names())):
baseColorTexture_index = self.get_material_names()[mat_index].pbrMetallicRoughness.baseColorTexture.index
atom_material.setMap(atom_material.texture_map['baseColor'], texture_root +
self.get_textures(baseColorTexture_index).uri)
normalTexture_index = self.get_material_names()[mat_index].normalTexture.index
atom_material.setMap(atom_material.texture_map['normal'], texture_root +
self.get_textures(normalTexture_index).uri)
roughnessTexture_index = self.get_material_names()[mat_index].\
pbrMetallicRoughness.metallicRoughnessTexture.index
atom_material.setMap(atom_material.texture_map['roughness'], texture_root +
self.get_textures(roughnessTexture_index).uri)
atom_material.write(rel_root + "\\Materials\\" + fbx01.get_material_names()[mat_index].name + ".material")
# -------------------------------------------------------------------------
if __name__ == "__main__":
fbx01 = FBX(fbx_root + 'peccy_01.fbx')
fbx01.create_atom_material()
@@ -0,0 +1,121 @@
# 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.
#
import os
import site
from unipath import Path
import click
import glob
# -------------------------------------------------------------------------
def returnStubDir(stub):
_DIRtoLastFile = None
'''Take a file name (stub) and returns the directory of the file (stub)'''
if _DIRtoLastFile is None:
path = os.path.abspath(__file__)
while 1:
path, tail = os.path.split(path)
if (os.path.isfile(os.path.join(path, stub))):
break
if (len(tail) == 0):
path = ""
if _G_DEBUG:
print('~ Debug Message: I was not able to find the '
'path to that file (stub) in a walk-up from currnet path')
break
_DIRtoLastFile = path
return _DIRtoLastFile
# --------------------------------------------------------------------------
# Paths for the quick tests. These could throw a UI or a configuration on it.
_DEV_ROOT = Path(returnStubDir('engineroot.txt')).resolve() #hopefully safe
_REL_ROOT = Path(_DEV_ROOT, 'AtomTest').resolve()
_MAYA_SCRIPTS = Path(_REL_ROOT, 'Editor/Scripts/atom/maya').resolve()
site.addsitedir(_MAYA_SCRIPTS)
from atom_mat import AtomMaterial as atomMAT
_ATOM_MAT_TEMPLATE = atomMAT(Path(_MAYA_SCRIPTS,
'StandardPBR_AllProperties.material').resolve())
_model_asset_dir = Path(_REL_ROOT, 'Objects/Characters/Peccy').resolve()
_atom_mat_path = Path(_REL_ROOT, 'Objects/Characters/Peccy').resolve()
import pymel.core as pm
def converter(_model_asset_dir, _atom_mat_path):
_maya_file = glob.glob(_model_asset_dir + '*.ma')
print(_maya_file)
for maya in range(len(_maya_file)):
pm.openFile(_maya_file[maya], f=True, prompt=False)
set_stingray_properties()
# This is ugly but work.
# To to: remove all of duplications.
def set_stingray_properties():
nodes = pm.ls(dag=1, o=1, s=1)
shade_eng = pm.listConnections(nodes, type=pm.nt.ShadingEngine)
materials = pm.ls(pm.listConnections(shade_eng), materials=1)
mat = []
for i in materials:
if i not in mat:
mat.append(i)
print(mat)
for j in range(len(mat)):
file_node_baseColor = pm.listConnections(mat[j].TEX_color_map)
if (file_node_baseColor and pm.objectType(file_node_baseColor[0]) == 'file'
and pm.getAttr(mat[j].use_color_map)):
tex_baseColor = Path(pm.getAttr(file_node_baseColor[0].fileTextureName)).norm().replace(_REL_ROOT, "")
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['baseColor'], tex_baseColor)
# else:
# _baseColor = pm.getAttr(mat[j].base_color)
# _ATOM_MAT_TEMPLATE.setColor(_ATOM_MAT_TEMPLATE.texture_map['baseColor'], _baseColor)
# print(mat[j])
# print(baseColor)
file_node_normal = pm.listConnections(mat[j].TEX_normal_map)
if (file_node_normal and pm.objectType(file_node_normal[0]) == 'file'
and pm.getAttr(mat[j].use_normal_map)):
tex_normal = Path(pm.getAttr(file_node_normal[0].fileTextureName)).norm().replace(_REL_ROOT, "")
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['normal'], tex_normal)
file_node_metallic = pm.listConnections(mat[j].TEX_metallic_map)
if (file_node_metallic and pm.objectType(file_node_metallic[0]) == 'file'
and pm.getAttr(mat[j].use_metallic_map)):
tex_metallic = Path(pm.getAttr(file_node_metallic[0].fileTextureName)).norm().replace(_REL_ROOT, "")
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['metallic'], tex_metallic)
file_node_roughness = pm.listConnections(mat[j].TEX_roughness_map)
if (file_node_roughness and pm.objectType(file_node_roughness[0]) == 'file'
and pm.getAttr(mat[j].use_roughness_map)):
file_node_roughness = pm.listConnections(mat[j].TEX_roughness_map)
tex_roughness = Path(pm.getAttr(file_node_roughness[0].fileTextureName)).norm().replace(_REL_ROOT, "")
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['roughness'], tex_roughness)
file_node_ao = pm.listConnections(mat[j].TEX_ao_map)
if (file_node_ao and pm.objectType(file_node_ao[0]) == 'file'
and pm.getAttr(mat[j].use_ao_map)):
tex_ao = Path(pm.getAttr(file_node_ao[0].fileTextureName)).norm().replace(_REL_ROOT, "")
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['ambientOcclusion'], tex_ao)
_ATOM_MAT_TEMPLATE.write(_REL_ROOT + "\\Materials\\" + str(mat[j])+".material")
@click.command()
@click.option('--maya', default=_model_asset_dir, help='Maya file folder')
@click.option('--output', default=_atom_mat_path, help='Atom Material output path')
def stingrayPBS_converter(maya, output):
click.echo(converter(maya, output))
if __name__ == '__main__':
stingrayPBS_converter()
@@ -0,0 +1,117 @@
# 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 -------------------------------------------
import os
import site
from unipath import Path
import maya.cmds as cmds
# -------------------------------------------------------------------------
def returnStubDir(stub, start_path):
_DIRtoLastFile = None
'''Take a file name (stub) and returns the directory of the file (stub)'''
if _DIRtoLastFile is None:
path = os.path.abspath(start_path)
while 1:
path, tail = os.path.split(path)
if (os.path.isfile(os.path.join(path, stub))):
break
if (len(tail) == 0):
path = ""
if _G_DEBUG:
print('~ Debug Message: I was not able to find the '
'path to that file (stub) in a walk-up from currnet path')
break
_DIRtoLastFile = path
return _DIRtoLastFile
# --------------------------------------------------------------------------
# Paths for the quick tests. These could throw a UI or a configuration on it.
_ASSET_PATH = Path(cmds.file(q=True, sn=True)).parent.resolve()
_DEV_ROOT = Path(returnStubDir('engineroot.txt', _ASSET_PATH)).resolve() # hopefully safe
_REL_ROOT = Path(_DEV_ROOT, 'AtomTest').resolve()
_MAYA_SCRIPTS = Path(_REL_ROOT, 'Editor/Scripts/atom/maya').resolve()
site.addsitedir(_MAYA_SCRIPTS)
from atom_mat import AtomMaterial as atomMAT
_ATOM_MAT_TEMPLATE = atomMAT(Path(_MAYA_SCRIPTS,
'StandardPBR_AllProperties.material').resolve())
import pymel.core as pm
class StingrayPBS(object):
def __init__(self):
# Append material from selected object(S)
nodes = pm.ls(dag=1, o=1, s=1, sl=1)
shade_eng = pm.listConnections(nodes, type=pm.nt.ShadingEngine)
material = pm.ls(pm.listConnections(shade_eng), materials=1)
self.mat = []
for i in material:
if i not in self.mat:
self.mat.append(i)
# Make a StringrayPBS instance
strpbs = StingrayPBS()
# This is ugly but work.
# To to: remove all of duplications.
for i in range(len(strpbs.mat)):
file_node_baseColor = pm.listConnections(strpbs.mat[i].TEX_color_map)
if (file_node_baseColor and pm.objectType(file_node_baseColor[0]) == 'file'
and pm.getAttr(strpbs.mat[i].use_color_map)):
tex_baseColor = Path(pm.getAttr(file_node_baseColor[0].fileTextureName)).resolve()
tex_baseColor = _REL_ROOT.rel_path_to(tex_baseColor)
tex_baseColor = tex_baseColor.replace('\\', '/')
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['baseColor'], tex_baseColor)
# else:
# _baseColor = pm.getAttr(strpbs.mat[i].base_color)
# _ATOM_MAT_TEMPLATE.setColor(_ATOM_MAT_TEMPLATE.texture_map['baseColor'], _baseColor)
# print(strpbs.mat[i])
# print(baseColor)
file_node_normal = pm.listConnections(strpbs.mat[i].TEX_normal_map)
if (file_node_normal and pm.objectType(file_node_normal[0]) == 'file'
and pm.getAttr(strpbs.mat[i].use_normal_map)):
tex_normal = Path(pm.getAttr(file_node_normal[0].fileTextureName)).resolve()
tex_normal = _REL_ROOT.rel_path_to(tex_normal)
tex_normal = tex_normal.replace('\\', '/')
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['normal'], tex_normal)
file_node_metallic = pm.listConnections(strpbs.mat[i].TEX_metallic_map)
if (file_node_metallic and pm.objectType(file_node_metallic[0]) == 'file'
and pm.getAttr(strpbs.mat[i].use_metallic_map)):
tex_metallic = Path(pm.getAttr(file_node_metallic[0].fileTextureName)).resolve()
tex_metallic = _REL_ROOT.rel_path_to(tex_metallic)
tex_metallic = tex_metallic.replace('\\', '/')
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['metallic'], tex_metallic)
file_node_roughness = pm.listConnections(strpbs.mat[i].TEX_roughness_map)
if (file_node_roughness and pm.objectType(file_node_roughness[0]) == 'file'
and pm.getAttr(strpbs.mat[i].use_roughness_map)):
file_node_roughness = pm.listConnections(strpbs.mat[i].TEX_roughness_map)
tex_roughness = Path(pm.getAttr(file_node_roughness[0].fileTextureName)).resolve()
tex_roughness = _REL_ROOT.rel_path_to(tex_roughness)
tex_roughness = tex_roughness.replace('\\', '/')
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['roughness'], tex_roughness)
file_node_ao = pm.listConnections(strpbs.mat[i].TEX_ao_map)
if (file_node_ao and pm.objectType(file_node_ao[0]) == 'file'
and pm.getAttr(strpbs.mat[i].use_ao_map)):
tex_ao = Path(pm.getAttr(file_node_ao[0].fileTextureName)).resolve()
tex_ao = _REL_ROOT.rel_path_to(tex_ao)
tex_ao = tex_ao.replace('\\', '/')
_ATOM_MAT_TEMPLATE.setMap(_ATOM_MAT_TEMPLATE.texture_map['ambientOcclusion'], tex_ao)
_ATOM_MAT_TEMPLATE.write(Path(_ASSET_PATH, "{}.material".format(str(strpbs.mat[i]))).resolve())
@@ -0,0 +1,35 @@
# 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 -------------------------------------------
"""
Module Documentation:
DccScriptingInterface:: SDK//maya//scripts//constants.py
This module is mainly a bunch of commony used constants, and default strings
So we can make an update here once that is used elsewhere
"""
# -------------------------------------------------------------------------
# built-ins
# none
# -- External Python modules
# -- DCCsi Extension Modules
#import azpy
# -- maya imports
# none
# -------------------------------------------------------------------------
OBJ_DCCSI_MAINMENU = 'LyDCCsiMainMenu'
TAG_DCCSI_MAINMENU = 'DCCsi (LY:Atom)'
@@ -0,0 +1,204 @@
# 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 -------------------------------------------
"""
Module Documentation:
DccScriptingInterface:: SDK//maya//scripts//set_callbacks.py
This module manages a set of predefined callbacks for maya
"""
# -------------------------------------------------------------------------
# -- Standard Python modules
import os
import sys
import logging as _logging
# -- External Python modules
from box import Box
# maya imports
import maya.cmds as mc
import maya.api.OpenMaya as om
# -- DCCsi Extension Modules
from azpy.constants import *
import azpy.maya
azpy.maya.init() # <-- should have already run?
import azpy.maya.callbacks.event_callback_handler as azEvCbH
import azpy.maya.callbacks.node_message_callback_handler as azNdMsH
# Node Message Callback Setup
import azpy.maya.callbacks.on_shader_rename as oSR
from set_defaults import set_defaults
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
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, True)
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, True)
_MODULENAME = r'DCCsi.SDK.Maya.Scripts.set_callbacks'
_LOGGER = azpy.initialize_logger(_MODULENAME, default_log_level=int(20))
_LOGGER.debug('Invoking:: {0}.'.format({_MODULENAME}))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# global scope callbacks, set up set and initialize all to None
# To Do: should callback initialization use data-driven settings?
# To Do: should we move callback initialization to a sub-module?
# To Do: move the callback key like 'NewSceneOpened' here (instead of None)
# ^ this would provide ability to loop through and replace key with CB object
_G_callbacks = Box(box_dots=True) # global scope container
_G_masterkey = 'DCCsi_callbacks'
_G_callbacks[_G_masterkey] = True # required master key
# -------------------------------------------------------------------------
def init_callbacks(_callbacks=_G_callbacks):
# store as a dict (Box is a fancy dict)
_callbacks[_G_masterkey] = True # required master key
# signature dict['callback key'] = ('CallBack'(type), func, callbackObj)
_callbacks['on_new_file'] = ['NewSceneOpened', set_defaults, None]
_callbacks['new_scene_fix_paths'] = ['NewSceneOpened', install_fix_paths, None]
_callbacks['post_scene_fix_paths'] = ['PostSceneRead', install_fix_paths, None]
_callbacks['workspace_changed'] = ['workspaceChanged', update_workspace, None]
_callbacks['quit_app'] = ['quitApplication', uninstall_callbacks, None]
# nodeMessage style callbacks
# fire a function
_func_00 = oSR.on_shader_rename_rename_shading_group
# using a nodeMessage callback trigger
_cb_00 = om.MNodeMessage.addNameChangedCallback
# all nodeMessage type callbacks can use 'nodeMessageType' key
_callbacks['shader_rename'] = ['nodeMessageType', (_func_00, _cb_00), None]
return _callbacks
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def uninstall_callbacks():
"""Bulk uninstalls hte globally defined set of callbacks:
_G_callbacks"""
global _G_callbacks
_LOGGER.debug('uninstall_callbacks() fired')
for key, value in _G_callbacks:
if value[2] is not None: # have a cb
value[2].uninstall() # so uninstall it
else:
_LOGGER.warning('No callback in: key {0}, value:{1}'
''.format(key, value))
_G_callbacks = None
_LOGGER.info('DCCSI CALLBACKS UNINSTALLED ... EXITING')
return _G_callbacks
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def install_callbacks(_callbacks=_G_callbacks):
"""Bulk installs the globally defined set of callbacks:
_G_callbacks"""
_LOGGER.debug('install_callback_set() fired')
_callbacks = init_callbacks(_callbacks)
# we initialized the box with this so pop it
if 'box_dots' in _callbacks:
_callbacks.pop('box_dots')
# don't pass anything but carefully considered dict
if _G_masterkey in _callbacks:
_masterkey = _callbacks.pop(_G_masterkey)
else:
_LOGGER.error('No master key, use a correct dictionary')
#To Do: implement error handling and return codes
return _callbacks[None]
for key, value in _G_callbacks.items():
# we popped the master key should the rest should be safe
if value[0] != 'nodeMessageType':
# set callback up
_cb = azEvCbH.EventCallbackHandler(value[0],
value[1])
# ^ installs by default
# stash it back into managed dict
value[2] = _cb
# value[2].install()
else:
# set up callback, value[1] should be tupple(func, trigger)
_cb = azNdMsH.NodeMessageCallbackHandler(value[1][0],
value[1][1])
# ^ installs by default
# stash it back into managed dict
value[2] = _cb
# value[2].install()
return _callbacks
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def install_fix_paths(foo=None):
"""Installs and triggers a fix paths module.
This can repair broken reference paths in shaders"""
global _fix_paths
_fix_paths = None
_LOGGER.debug('install_fix_paths() fired')
# if we don't have it already, this function is potentially triggered
# by a callback, so we don't need to keep importing it.
try:
_fix_paths
reload(_fix_paths)
except Exception as e:
try:
import fixPaths as _fix_paths
except Exception as e:
# To Do: not implemented yet
_LOGGER.warning('NOT IMPLEMENTED: {0}'.format(e))
# if we have it, use it
if _fix_paths:
return _fix_paths.main()
else:
# To Do: implement error handling and return codes
return 1
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def update_workspace(foo=None):
"""Forces and update of the workspace (workspace.mel)"""
_LOGGER.debug('update_workspace() fired')
result = mc.workspace(update=True)
return result
# -------------------------------------------------------------------------
# install and init callbacks on an import obj
_G_callbacks = install_callbacks(_G_callbacks)
# ==========================================================================
# Module Tests
#==========================================================================
if __name__ == '__main__':
_G_callbacks = install_callbacks(_G_callbacks)
@@ -0,0 +1,96 @@
# 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 -------------------------------------------
"""
Module Documentation:
DccScriptingInterface:: SDK//maya//scripts//set_pref_defaults.py
This module manages a predefined set of prefs for maya
"""
# -------------------------------------------------------------------------
# -- Standard Python modules
import os
import sys
# -- External Python modules
# -- DCCsi Extension Modules
import azpy
from azpy.constants import *
# -- maya imports
import maya.cmds as mc
import maya.mel as mm
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
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)
_MODULENAME = r'DCCsi.SDK.Maya.Scripts.set_defaults'
_LOGGER = azpy.initialize_logger(_MODULENAME, default_log_level=int(20))
_LOGGER.debug('Invoking:: {0}.'.format({_MODULENAME}))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def set_defaults(units='meter'):
"""This method will make defined settings changes to Maya prefs,
to better configure maya to work with Lumberyard"""
# To Do: make this data-driven env/settings, game teams should be able
# to opt out and/or set their prefered configuration.
_LOGGER.debug('set_defaults_lumberyard() fired')
# set up default units ... this should be moved to bootstrap config
_LOGGER.info('Default, 1 Linear Game Unit in Lumberyard == 1 Meter'
' in Maya content. Setting default linear units to Meters'
' (user can change to other units in the preferences)')
result = mc.currentUnit(linear=units)
# set up grid defaults
_LOGGER.info('Setting Grid defaults, to match default unit scale.'
'(user can change grid config manually')
try:
mc.grid(size=32, spacing=1, divisions=10)
except Exception as e:
_LOGGER.warning('{0}'.format(e))
# viewFit
_LOGGER.info('Changing default mc.viewFit')
try:
mc.viewFit()
except Exception as e:
_LOGGER.warning('{0}'.format(e))
# some mel commands
_LOGGER.info('Changing sersp camera clipping planes')
try:
mm.eval(str(r'setAttr "perspShape.nearClipPlane" 0.01;'))
mm.eval(str(r'setAttr "perspShape.farClipPlane" 1000;'))
except Exception as e:
_LOGGER.warning('{0}'.format(e))
# set up fixPaths
_LOGGER.info('~ Setting up fixPaths in default scene')
return 0
# -------------------------------------------------------------------------
@@ -0,0 +1,91 @@
# 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 -------------------------------------------
"""
Module Documentation:
DccScriptingInterface:: SDK//maya//scripts//set_menu.py
This module creates and manages a DCCsi mainmenu
"""
# -------------------------------------------------------------------------
# -- Standard Python modules
# none
# -- External Python modules
# none
# -- DCCsi Extension Modules
import azpy
from constants import OBJ_DCCSI_MAINMENU
from constants import TAG_DCCSI_MAINMENU
# -- maya imports
import pymel.core as pm
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
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)
_MODULENAME = r'DCCsi.SDK.Maya.Scripts.set_menu'
_LOGGER = azpy.initialize_logger(_MODULENAME, default_log_level=int(20))
_LOGGER.debug('Invoking:: {0}.'.format({_MODULENAME}))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def menu_cmd_test():
_LOGGER.info('test_func(), is TESTING main menu')
return
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def set_main_menu(obj_name=OBJ_DCCSI_MAINMENU, label=TAG_DCCSI_MAINMENU):
_main_window = pm.language.melGlobals['gMainWindow']
_menu_obj = obj_name
_menu_label = label
# check if it already exists and remove (so we don't duplicate)
if pm.menu(_menu_obj, label=_menu_label, exists=True, parent=_main_window):
pm.deleteUI(pm.menu(_menu_obj, e=True, deleteAllItems=True))
# create the main menu object
_custom_tools_menu = pm.menu(_menu_obj,
label=_menu_label,
parent=_main_window,
tearOff=True)
# make a dummpy sub-menu
pm.menuItem(label='Menu Item Stub',
subMenu=True,
parent=_custom_tools_menu,
tearOff=True)
# make a dummy menu item to test
pm.menuItem(label='Test', command=pm.Callback(menu_cmd_test))
return _custom_tools_menu
# ==========================================================================
# Run as LICENSE
#==========================================================================
if __name__ == '__main__':
_custom_menu = set_main_menu()
@@ -0,0 +1,326 @@
# 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 -------------------------------------------
from __future__ import unicode_literals
"""
This module fullfils the maya bootstrap pattern as described in their docs
https://tinyurl.com/y2aoz8es
Pattern is similar to Lumberyard Editor\\Scripts\\bootstrap.py
For now the proper way to initiate Maya boostrapping the DCCsi, is to use
the provided env and launcher bat files.
If you are developing for the DCCsi you can use this launcher to start Maya:
DccScriptingInterface\Launchers\Windows\Launch_Maya_2020.bat"
To Do: https://jira.agscollab.com/browse/ATOM-5861
"""
__project__ = 'DccScriptingInterface'
# it is really hard to debug userSetup bootstrapping
# this enables some rudimentary logging for debugging
_BOOT_INFO = True
# -------------------------------------------------------------------------
# built in's
import os
import sys
import site
import inspect
import traceback
import logging as _logging
# -- DCCsi Extension Modules
import azpy
from azpy.constants import *
from azpy.env_base import _BASE_ENVVAR_DICT
# -- maya imports
import maya.cmds as cmds
import maya.mel as mel
#from pymel.all import *
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
from azpy 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)
#_DCCSI_DEV_MODE = True # force true for debugger testing
_ORG_TAG = r'Amazon::Lumberyard'
_APP_TAG = r'DCCsi'
_TOOL_TAG = r'SDK.Maya.Scripts.userSetup'
_TYPE_TAG = r'entrypoint' # bootstrap
_MODULENAME = str('{0}.{1}'.format(_APP_TAG, _TOOL_TAG))
_LOGGER = azpy.initialize_logger(_MODULENAME, default_log_level=int(20))
_LOGGER.info('Initializing: {0}.'.format({_MODULENAME}))
_LOGGER.info('DCCSI_GDEBUG: {0}.'.format({_G_DEBUG}))
_LOGGER.info('DCCSI_DEV_MODE: {0}.'.format({_DCCSI_DEV_MODE}))
# flag to turn off setting up callbacks, until they are fully implemented
# To Do: consider making it a settings option to define and enable/disable
_G_LOAD_CALLBACKS = True # couple bugs, couple NOT IMPLEMENTED
_LOGGER.info('DCCSI_MAYA_SET_CALLBACKS: {0}.'.format({_G_LOAD_CALLBACKS}))
# early attach WingIDE debugger (can refactor to include other IDEs later)
if _DCCSI_DEV_MODE:
from azpy.test.entry_test import connect_wing
foo = connect_wing()
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# To Do REMOVE this block and replace with dev module
# debug prints, To Do: this should be moved to bootstrap config
#_G_DEBUGGER = os.getenv(ENVAR_DCCSI_GDEBUGGER, "WING")
#if _DCCSI_DEV_MODE:
#if _G_DEBUGGER == "WING":
#_LOGGER.info('{0}'.format('-' * 74))
#_LOGGER.info('Developer Debug Mode: {0}, Basic debugger: {1}'.format(_G_DEBUG, _G_DEBUGGER))
#try:
#_LOGGER.info('Attempting to start basic WING debugger')
#import azpy.lmbr.test
#_LOGGER.info('Package Imported: azpy.test')
#ouput = azpy.entry_test.main(verbose=False,
#connectDebugger=True,
#returnOuput=_G_DEBUG)
#_LOGGER.info(ouput)
#pass
#except Exception as e:
#_LOGGER.info("Error: azpy.test, entry_test (didn't perform)")
#_LOGGER.info("Exception: {0}".format(e))
#pass
#elif _G_DEBUGGER == "PYCHARM":
## https://github.com/juggernate/PyCharm-Maya-Debugging
#_LOGGER.info('{0}'.format('-' * 74))
#_LOGGER.info('Developer Debug Mode: {0}, Basic debugger: {1}'.format(_G_DEBUG, _G_DEBUGGER))
#sys.path.append('C:\Program Files\JetBrains\PyCharm 2019.1.3\debug-eggs\pydevd-pycharm.egg')
#try:
#_LOGGER.info('Attempting to start basic PYCHARM debugger')
## Inside Maya Python Console (Tip: add to a shelf button for quick access)
#import pydevd
#_LOGGER.info('Package Imported: pydevd')
#pydevd.settrace('localhost', port=7720, suspend=False)
#_LOGGER.info('PYCHARM Debugger Attach Success!!!')
## To disconnect run:
## pydevd.stoptrace()
#pass
#except Exception as e:
#_LOGGER.info("Error: pydevd.settrace (didn't perform)")
#_LOGGER.info("Exception: {0}".format(e))
#pass
#else:
#pass
## -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# validate access to the DCCsi and it's Lib site-packages
# bootstrap site-packages by version
from azpy.constants import PATH_DCCSI_PYTHON_LIB_PATH
try:
os.path.exists(PATH_DCCSI_PYTHON_LIB_PATH)
site.addsitedir(PATH_DCCSI_PYTHON_LIB_PATH)
_LOGGER.info('azpy 3rdPary site-packages: is: {0}'.format(PATH_DCCSI_PYTHON_LIB_PATH))
except Exception as e:
_LOGGER.error('ERROR: {0}, {1}'.format(e, PATH_DCCSI_PYTHON_LIB_PATH))
raise e
# 3rdparty
from unipath import Path
from box import Box
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# Maya is frozen
#_MODULE_PATH = Path(__file__)
# https://tinyurl.com/y49t3zzn
# module path when frozen
_MODULE_FILEPATH = os.path.abspath(inspect.getfile(inspect.currentframe()))
_MODULE_PATH = os.path.dirname(_MODULE_FILEPATH)
if _BOOT_INFO:
_LOGGER.debug('Boot: CWD: {}'.format(os.getcwd()))
_LOGGER.debug('Frozen: _MODULE_FILEPATH: {}'.format(_MODULE_FILEPATH))
_LOGGER.debug('Frozen: _MODULE_PATH: {}'.format(_MODULE_PATH))
_LOGGER.debug('Module __name__: {}'.format(__name__))
# root: INFO: Module __name__: __main__
_LOGGER.info('_MODULENAME: {}'.format(_MODULENAME))
# -------------------------------------------------------------------------
# check some env var tags (fail if no, likely means no proper code access)
_STR_ERROR_ENVAR = "Envar 'key' does not exist in base_env: {0}"
_DCCSI_SDK_PATH = None
try:
_DCCSI_SDK_PATH = _BASE_ENVVAR_DICT[ENVAR_DCCSI_SDK_PATH]
except Exception as e:
_LOGGER.critical(_STR_ERROR_ENVAR.format(_BASE_ENVVAR_DICT[ENVAR_DCCSI_SDK_PATH]))
_LY_PROJECT_PATH = None
try:
_LY_PROJECT_PATH = _BASE_ENVVAR_DICT[ENVAR_LY_PROJECT_PATH]
except Exception as e:
_LOGGER.critical(_STR_ERROR_ENVAR.format(_BASE_ENVVAR_DICT[ENVAR_LY_PROJECT_PATH]))
# check some env var tags (fail if no, likely means no proper code access)
_LY_DEV = _BASE_ENVVAR_DICT[ENVAR_LY_DEV]
_LY_DCCSIG_PATH = _BASE_ENVVAR_DICT[ENVAR_DCCSIG_PATH]
_LY_DCCSI_LOG_PATH = _BASE_ENVVAR_DICT[ENVAR_DCCSI_LOG_PATH]
_LY_AZPY_PATH = _BASE_ENVVAR_DICT[ENVAR_DCCSI_AZPY_PATH]
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# To Do: implement data driven config
# Currently not used, but will be where we store the ordered dict
# which is parsed from the project bootstrapping config files.
_G_app_config = {}
# global scope maya callbacks container
_G_callbacks = Box(box_dots=True) # global scope container
# used to store fixPaths in the global scope
_fix_paths = None
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# add appropriate common tools paths to the maya environment variables
def startup():
"""Early starup execution before mayautils.executeDeferred().
Some things like UI and plugins should be defered to avoid failure"""
_LOGGER.info('startup() fired')
# get known paths
_KNOWN_PATHS = site._init_pathinfo()
if os.path.isdir(_DCCSI_SDK_PATH):
site.addsitedir(_DCCSI_SDK_PATH, _KNOWN_PATHS)
try:
import azpy.test
_LOGGER.info('SUCCESS, import azpy.test')
except Exception as e:
_LOGGER.warning('startup(), could not import azpy.test')
_LOGGER.info('startup(), COMPLETE')
return 0
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# verify Shared\Python exists and add it as a site dir. Begin imports and config.
def post_startup():
"""Allows for a defered execution startup sequence"""
_LOGGER.info('post_startup() fired')
# plugins, To Do: these should be moved to bootstrapping config
try:
maya.cmds.loadPlugin("dx11Shader")
except Exception as e:
_LOGGER.error(e) # not a hard failure
# Lumberyard DCCsi environment ready or error out.
try:
import azpy.maya
_LOGGER.info('Python module imported: azpy.maya')
except Exception as e:
_LOGGER.error(e)
_LOGGER.error(traceback.print_exc())
return 1
# Dccsi azpy maya ready or error out.
try:
azpy.maya.init()
_LOGGER.info('SUCCESS, azpy.maya.init(), code accessible.')
except Exception as e:
_LOGGER.error(e)
_LOGGER.error(traceback.print_exc())
return 1
# callbacks, To Do: these should also be moved to the bootstrapping config
# Defered startup after the Ui is running.
_G_callbacks = Box(box_dots=True) # this just ensures a global scope container
if _G_LOAD_CALLBACKS:
from set_callbacks import _G_callbacks
# ^ need to hold on to this as the install repopulate set
# this ensures the fixPaths callback is loaded
# even when the other global callbacks are disabled
from set_callbacks import install_fix_paths
install_fix_paths()
# set the project workspace
#_LY_PROJECT_PATH = _BASE_ENVVAR_DICT[ENVAR_LY_PROJECT_PATH]
_project_workspace = os.path.join(_LY_PROJECT_PATH, TAG_MAYA_WORKSPACE)
if os.path.isfile(_project_workspace):
try:
# load workspace
maya.cmds.workspace(_LY_PROJECT_PATH, openWorkspace=True)
_LOGGER.info('Loaded workspace file: {0}'.format(_project_workspace))
maya.cmds.workspace(_LY_PROJECT_PATH, update=True)
except Exception as e:
_LOGGER.error(e)
else:
_LOGGER.warning('Workspace file not found: {1}'.format(_LY_PROJECT_PATH))
# Set up Lumberyard, maya default setting
from set_defaults import set_defaults
set_defaults()
# Setup UI tools
if not maya.cmds.about(batch=True):
_LOGGER.info('Add UI dependent tools')
# wrap in a try, because we haven't implmented it yet
try:
mel.eval(str(r'source "{}"'.format(TAG_LY_DCC_MAYA_MEL)))
except Exception as e:
_LOGGER.error(e)
# manage custom menu in a sub-module
from set_menu import set_main_menu
set_main_menu()
# To Do: manage custom shelf in a sub-module
_LOGGER.info('post_startup(), COMPLETE')
_LOGGER.info('DCCsi Bootstrap, COMPLETE')
return 0
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if __name__ == '__main__':
try:
# Early startup config.
startup()
# This allows defered action post boot (atfer UI is active)
from maya.utils import executeDeferred
post = executeDeferred(post_startup)
except Exception as e:
traceback.print_exc()
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:861729900e8539e8c1b7e501dc7c507aeccfc307199cbfa729276e20d9e60f4f
size 16797018
@@ -0,0 +1,69 @@
# 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 -------------------------------------------
import OpenImageIO as oiio
def convert(src):
try:
rgba = oiio.ImageBuf(src)
spec = get_image_spec(rgba)
# Normal output ------>
rgb = oiio.ImageBufAlgo.channels(rgba, (0, 1, 2))
normal_output = src.replace('ddna', 'Normal')
# Roughness output ------>
alpha = oiio.ImageBufAlgo.channels(rgba, (3,))
roughness = oiio.ImageBufAlgo.invert(alpha)
roughness_output = normal_output.replace('Normal', 'Roughness')
write_image(rgba, normal_output, spec['format'])
write_image(roughness, roughness_output, spec['format'])
# logging.info('Output Normal Map: {}'.format(normal_output))
# logging.info('Output Roughness Map: {}'.format(roughness_output))
except Exception as e:
logging.info('OIIO error in image conversion: {}'.format(e))
return None
def get_image_spec(target_image):
spec = target_image.spec()
info = {'resolution': (spec.width, spec.height, spec.x, spec.y), 'channels': spec.channelnames,
'format': str(spec.format)}
if spec.channelformats :
info['channelformats'] = str(spec.channelformats)
info['alpha channel'] = str(spec.alpha_channel)
info['z channel'] = str(spec.z_channel)
info['deep'] = str(spec.deep)
for i in range(len(spec.extra_attribs)):
if type(spec.extra_attribs[i].value) == str:
info[spec.extra_attribs[i].name] = spec.extra_attribs[i].value
else:
info[spec.extra_attribs[i].name] = spec.extra_attribs[i].value
return info
def write_image(image, filename, image_format):
if not image.has_error:
image.set_write_format(image_format)
image.write(filename)
if image.has_error:
print("Error writing", filename, ":", image.geterror())
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
# run a test
convert('AA_Gun_01_ddna.tif')
# validate()
@@ -0,0 +1,88 @@
# 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.
#
import bpy
import collections
import json
def get_shader_information():
"""
Queries all materials and corresponding material attributes and file textures in the Blender scene.
:return:
"""
# TODO - link file texture location to PBR material plugs- finding it difficult to track down how this is achieved
# in the Blender Python API documentation and/or in forums
materials_count = 1
shader_types = get_blender_shader_types()
materials_dictionary = {}
for target_mesh in [o for o in bpy.data.objects if type(o.data) is bpy.types.Mesh]:
material_information = collections.OrderedDict(DccApplication='Blender', AppliedMesh=target_mesh,
SceneName=bpy.data.filepath, MaterialAttributes={},
FileConnections={})
for target_material in target_mesh.data.materials:
material_information['MaterialName'] = target_material.name
shader_attributes = {}
shader_file_connections = {}
for node in target_material.node_tree.nodes:
socket = node.inputs[0]
print('NODE: {}'.format(node))
print('Socket: {}'.format(socket))
for material_input in node.inputs:
attribute_name = material_input.name
try:
attribute_value = material_input.default_value
print('Name: [{}] [{}] ValueType ::::::> {}'.format(attribute_name, attribute_value,
type(attribute_value)))
material_information['MaterialAttributes'].update({attribute_name: str(attribute_value)})
except Exception as e:
pass
print('\n')
if node.type == 'TEX_IMAGE':
material_information['FileConnections'].update({str(node): str(node.image.filepath)})
if node.name in shader_types.keys():
material_information['MaterialType'] = shader_types[node.name]
# material_information['MaterialAttributes'] = shader_attributes
materials_dictionary['Material_{}'.format(materials_count)] = material_information
materials_count += 1
print('_________________________________________________________________\n')
return materials_dictionary
def get_blender_shader_types():
"""
This returns all the material types present in the Blender scene
:return:
"""
shader_types = {}
ddir = lambda data, filter_str: [i for i in dir(data) if i.startswith(filter_str)]
get_nodes = lambda cat: [i for i in getattr(bpy.types, cat).category.items(None)]
cycles_categories = ddir(bpy.types, "NODE_MT_category_SH_NEW")
for cat in cycles_categories:
if cat == 'NODE_MT_category_SH_NEW_SHADER':
for node in get_nodes(cat):
shader_types[node.label] = node.nodetype
return shader_types
materials_dictionary = get_shader_information()
#print('Materials Dictionary:')
#print(materials_dictionary)
#parsed = json.loads(str(materials_dictionary))
#print(json.dumps(parsed, indent=4, sort_keys=True))
@@ -0,0 +1,55 @@
# 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 -------------------------------------------
import click
import os
import main as app_main
@click.version_option('1.0.0')
@click.option('--output', default='PBR', help='Lumberyard material type. Current options: [pbr_basic]')
@click.argument('operands', type=click.STRING, nargs=-1)
@click.command(context_settings=dict(ignore_unknown_options=True))
def main(output, operands):
target_files = []
for index, operand in enumerate(operands):
entry_path = os.path.abspath(str(operand))
if os.path.isdir(entry_path):
for directory_path, directory_names, file_names in os.walk(entry_path):
for file_name in file_names:
if is_valid_file(file_name):
target_files.append(os.path.join(entry_path, file_name))
else:
if is_valid_file(operand):
target_files.append(operand)
if len(target_files):
app_main.launch_material_converter('standalone', output, target_files)
def is_valid_file(file_name):
"""
Allows only supported DCC application files by extensions
:param file_name: The name of the file.
:return:
"""
target_extensions = 'ma mb fbx blend max'.split(' ')
if file_name.split('.')[-1] in target_extensions:
return True
return False
if __name__ == '__main__':
main()
@@ -0,0 +1,68 @@
# 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 -------------------------------------------
import logging
logging.basicConfig(level=logging.DEBUG)
def get_maya_material_mapping(name, material_type, file_connections):
"""
Helps map found material DCC attribute values/file connections with Lumberyard materials.
:param name: Material name from within Maya
:param material_type: Maya Material type to match values to (i.e. Stingray PBS, aiStandardSurface(Arnold)
:param file_connections: List of all connected texture files from Maya
:return: Key value pairs for attributes/file textures assigned as Lumberyard material values
"""
material_properties = {}
if material_type == 'StingrayPBS':
logging.debug('Mapping StingrayPBS')
maps = 'color, metallic, roughness, normal, emissive, ao, opacity'.split(', ')
naming_exceptions = {'color': 'baseColor', 'ao': 'ambientOcclusion'}
for m in maps:
texture_attribute = 'TEX_{}_map'.format(m)
for tex in file_connections.keys():
if tex.find(texture_attribute) != -1:
key = m if m not in naming_exceptions else naming_exceptions.get(m)
logging.debug('Key, Value: {} {}.{}'.format(key, name, texture_attribute))
material_properties[key] = {'useTexture': 'true',
'textureMap': file_connections.get(
'{}.{}'.format(name, texture_attribute))}
elif material_type == 'aiStandardSurface':
logging.debug('Mapping AiStandardSurface')
# TODO- Occlusion is based on a more difficult setup- there is no standard channel. Set this up as time permits
maps = 'baseColor, metalness, specularRoughness, normal, emissionColor, opacity'.split(', ')
naming_exceptions = {'metalness': 'metallic', 'specularRoughness': 'roughness', 'emissionColor': 'emissive'}
for m in maps:
key = m if m not in naming_exceptions.keys() else naming_exceptions.get(m)
texture_attribute = m
for tex in file_connections.keys():
if tex.find(texture_attribute) != -1:
logging.debug('Key, Value: {} {}.{}'.format(key, name, texture_attribute))
material_properties[key] = {'useTexture': 'true',
'textureMap': file_connections.get(
'{}.{}'.format(name, texture_attribute))}
else:
pass
return material_properties
def get_blender_material_mapping(name, material_type, file_connections):
pass
def get_max_material_mapping(name, material_type, file_connections):
pass
@@ -0,0 +1,68 @@
# 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 -------------------------------------------
from PySide2 import QtWidgets, QtCore
from PySide2.QtCore import Signal
class DragAndDrop(QtWidgets.QWidget):
drop_update = QtCore.Signal(list)
drop_over = QtCore.Signal(bool)
def __init__(self, frame_color=None, highlight=None, parent=None):
super(DragAndDrop, self).__init__(parent)
self.urls = []
self.frame_color = frame_color
self.frame_highlight = highlight
self.setContentsMargins(0, 0, 0, 0)
self.setAcceptDrops(True)
self.drag_and_drop_frame = QtWidgets.QFrame(self)
self.drag_and_drop_frame.setGeometry(0, 0, 5000, 5000)
self.drag_and_drop_frame.setStyleSheet('background-color:rgb({});'.format(self.frame_color))
def dragEnterEvent(self, e):
if e.mimeData().hasUrls:
e.accept()
self.drop_over.emit(True)
if self.frame_highlight:
self.drag_and_drop_frame.setStyleSheet('background-color:rgb({});'.format(self.frame_highlight))
else:
e.ignore()
def dragLeaveEvent(self, e):
self.drop_over.emit(False)
if self.frame_highlight:
self.drag_and_drop_frame.setStyleSheet('background-color:rgb({});'.format(self.frame_color))
def dragMoveEvent(self, e):
if e.mimeData().hasUrls:
e.accept()
else:
e.ignore()
def dropEvent(self, e):
if e.mimeData().hasUrls:
e.setDropAction(QtCore.Qt.CopyAction)
e.accept()
for url in e.mimeData().urls():
file_name = str(url.toLocalFile())
self.urls.append(file_name)
self.drop_update.emit(self.urls)
if self.frame_highlight:
self.drag_and_drop_frame.setStyleSheet('background-color:rgb({});'.format(self.frame_color))
else:
e.ignore()
@@ -0,0 +1,21 @@
# 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.
#
import MaxPlus
import sys
def get_material_information():
for mesh_object in MaxPlus.Core.GetRootNode().Children:
print('Object---> {}'.format(mesh_object))
get_material_information()
@@ -0,0 +1,172 @@
# 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.
from PySide2 import QtCore
import maya.standalone
maya.standalone.initialize(name='python')
import maya.cmds as mc
import collections
import logging
import json
import sys
import os
for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler)
logging.basicConfig(level=logging.INFO,
format='%(name)s - %(levelname)s - %(message)s',
datefmt='%m-%d %H:%M',
filename='output.log',
filemode='w')
class MayaMaterials(QtCore.QObject):
def __init__(self, files_list, materials_count, parent=None):
super(MayaMaterials, self).__init__(parent)
self.files_list = files_list
self.current_scene = None
self.materials_dictionary = {}
self.materials_count = int(materials_count)
self.get_material_information()
def get_material_information(self):
"""
Main entry point for the material information extraction. Because this class is run
in Standalone mode as a subprocess, the list is passed as a string- some parsing/measures
need to be taken in order to separate values that originated as a list before passed.
:return: A dictionary of all of the materials gathered. Sent back to main UI through stdout
"""
for target_file in file_list:
self.current_scene = os.path.abspath(target_file.replace('\'', ''))
mc.file(self.current_scene, open=True, force=True)
self.set_material_descriptions()
json.dump(self.materials_dictionary, sys.stdout)
@staticmethod
def get_materials(target_mesh):
"""
Gathers a list of all materials attached to each mesh's shader
:param target_mesh: The target mesh to pull attached material information from.
:return: List of unique material values attached to the mesh passed as an argument.
"""
shading_group = mc.listConnections(target_mesh, type='shadingEngine')
materials = mc.ls(mc.listConnections(shading_group), materials=1)
return list(set(materials))
@staticmethod
def get_shader(material_name):
"""
Convenience function for obtaining the shader that the specified material (as an argument)
is attached to.
:param material_name: Takes the material name as an argument to get associated shader object
:return:
"""
connections = mc.listConnections(material_name, type='shadingEngine')[0]
shader_name = '{}.surfaceShader'.format(connections)
shader = mc.listConnections(shader_name)[0]
return shader
def get_shader_information(self, shader, material_mesh):
"""
Helper function for extracting shader/material attributes used to form the DCC specific dictionary
of found material values for conversion.
:param shader: The target shader object to analyze
:param material_mesh: The material mesh needs to be passed to search for textures attached to it.
:return: Complete set (in the form of two dictionaries) of file connections and material attribute values
"""
shader_file_connections = {}
materials = self.get_materials(material_mesh)
for material in materials:
material_files = [x for x in mc.listConnections(material, plugs=1, source=1) if x.startswith('file')]
for file_name in material_files:
file_texture = mc.getAttr('{}.fileTextureName'.format(file_name.split('.')[0]))
if os.path.basename(file_texture).split('.')[-1] != 'dds':
key_name = mc.listConnections(file_name, plugs=1, source=1)[0]
shader_file_connections[key_name] = file_texture
shader_attributes = {}
for shader_attribute in mc.listAttr(shader, s=True, iu=True):
try:
shader_attributes[str(shader_attribute)] = str(mc.getAttr('{}.{}'.format(shader, shader_attribute)))
except Exception as e:
logging.error('MayaAttributeError: {}'.format(e))
return shader_file_connections, shader_attributes
def set_material_dictionary(self, material_name, material_type, material_mesh):
"""
When a unique material has been found, this creates a dictionary entry with all relevant material values. This
includes material attributes as well as attached file textures. Later in the process this information is
leveraged when creating the Lumberyard material definition.
:param material_name: The name attached to the material
:param material_type: Specific type of material (Arnold, Stingray, etc.)
:param material_mesh: Mesh that the material is applied to
:return:
"""
self.materials_count += 1
shader = self.get_shader(material_name)
shader_file_connections, shader_attributes = self.get_shader_information(shader, material_mesh)
material_dictionary = collections.OrderedDict(MaterialName=material_name, MaterialType=material_type,
DccApplication='Maya', AppliedMesh=material_mesh,
FileConnections=shader_file_connections,
SceneName=str(self.current_scene),
MaterialAttributes=shader_attributes)
material_name = 'Material_{}'.format(self.materials_count)
self.materials_dictionary[material_name] = material_dictionary
logging.info('\n\n:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n'
'MATERIAL DEFINITION: {} \n'
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n{}'.format(
self.materials_dictionary[material_name]['MaterialType'],
json.dumps(self.materials_dictionary[material_name], indent=4)))
def set_material_descriptions(self):
"""
This function serves as the clearinghouse for all analyzed materials passing through the system.
It will determine whether or not the found material has already been processed, or if it needs to
be added to the final material dictionary. In the event that an encountered material has already
been processed, this function creates a register of all meshes it is applied to in the 'AppliedMesh'
attribute.
:return:
"""
scene_geo = mc.ls(v=True, geometry=True)
for target_mesh in scene_geo:
material_list = self.get_materials(target_mesh)
for material_name in material_list:
material_type = mc.nodeType(material_name)
if material_type != 'lambert':
material_listed = [x for x in self.materials_dictionary
if self.materials_dictionary[x]['MaterialName'] == material_name]
if not material_listed:
self.set_material_dictionary(str(material_name), str(material_type), str(target_mesh))
else:
mesh_list = self.materials_dictionary[material_name].get('AppliedMesh')
if not isinstance(mesh_list, list):
self.materials_dictionary[str(material_name)]['AppliedMesh'] = [mesh_list, target_mesh]
else:
mesh_list.append(target_mesh)
# ++++++++++++++++++++++++++++++++++++++++++++++++#
# Maya Specific Shader Mapping #
# ++++++++++++++++++++++++++++++++++++++++++++++++#
file_list = sys.argv[1:-1]
count = sys.argv[-1]
instance = MayaMaterials(file_list, count)
@@ -0,0 +1,157 @@
# 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.
#
from PySide2.QtCore import QAbstractItemModel, QModelIndex, Qt
class MaterialsModel(QAbstractItemModel):
def __init__(self, headers, data, parent=None):
super(MaterialsModel, self).__init__(parent)
self.rootItem = TreeNode(headers)
self.parents = [self.rootItem]
self.indentations = [0]
self.create_data(data)
def create_data(self, data, indent=-1):
"""
Recursive loop that structures Model data into tree form.
:param data: Row information.
:param indent: Column information. This helps to facilitate the creation of nested rows.
:return:
"""
if type(data) == dict:
indent += 1
position = 4 * indent
for key, value in data.items():
if position > self.indentations[-1]:
if self.parents[-1].childCount() > 0:
self.parents.append(self.parents[-1].child(self.parents[-1].childCount() - 1))
self.indentations.append(position)
else:
while position < self.indentations[-1] and len(self.parents) > 0:
self.parents.pop()
self.indentations.pop()
parent = self.parents[-1]
parent.insertChildren(parent.childCount(), 1, parent.columnCount())
parent.child(parent.childCount() - 1).setData(0, key)
value_string = str(value) if type(value) != dict else str('')
parent.child(parent.childCount() - 1).setData(1, value_string)
try:
self.create_data(value, indent)
except RuntimeError:
pass
@staticmethod
def get_attribute_value(search_string, search_column):
""" Convenience function for quickly accessing row information based on attribute keys. """
for childIndex in range(search_column.childCount()):
child_item = search_column.child(childIndex)
child_value = child_item.itemData
if child_value[0] == search_string:
return child_value[1]
return None
def index(self, row, column, index=QModelIndex()):
""" Returns the index of the item in the model specified by the given row, column and parent index """
if not self.hasIndex(row, column, index):
return QModelIndex()
if not index.isValid():
item = self.rootItem
else:
item = index.internalPointer()
child = item.child(row)
if child:
return self.createIndex(row, column, child)
return QModelIndex()
def parent(self, index):
"""
Returns the parent of the model item with the given index If the item has no parent,
an invalid QModelIndex is returned
"""
if not index.isValid():
return QModelIndex()
item = index.internalPointer()
if not item:
return QModelIndex()
parent = item.parentItem
if parent == self.rootItem:
return QModelIndex()
else:
return self.createIndex(parent.childNumber(), 0, parent)
def rowCount(self, index=QModelIndex()):
"""
Returns the number of rows under the given parent. When the parent is valid it means that
rowCount is returning the number of children of parent
"""
if index.isValid():
parent = index.internalPointer()
else:
parent = self.rootItem
return parent.childCount()
def columnCount(self, index=QModelIndex()):
""" Returns the number of columns for the children of the given parent """
return self.rootItem.columnCount()
def data(self, index, role=Qt.DisplayRole):
""" Returns the data stored under the given role for the item referred to by the index """
if index.isValid() and role == Qt.DisplayRole:
return index.internalPointer().data(index.column())
elif not index.isValid():
return self.rootItem.data(index.column())
def headerData(self, section, orientation, role=Qt.DisplayRole):
""" Returns the data for the given role and section in the header with the specified orientation """
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.rootItem.data(section)
class TreeNode(object):
def __init__(self, data, parent=None):
self.parentItem = parent
self.itemData = data
self.children = []
def child(self, row):
return self.children[row]
def childCount(self):
return len(self.children)
def childNumber(self):
if self.parentItem is not None:
return self.parentItem.children.index(self)
def columnCount(self):
return len(self.itemData)
def data(self, column):
return self.itemData[column]
def insertChildren(self, position, count, columns):
if position < 0 or position > len(self.children):
return False
for row in range(count):
data = [v for v in range(columns)]
item = TreeNode(data, self)
self.children.insert(position, item)
def parent(self):
return self.parentItem
def setData(self, column, value):
if column < 0 or column >= len(self.itemData):
return False
self.itemData[column] = value
@@ -0,0 +1,135 @@
# 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 -------------------------------------------
"""Empty Doc String""" # To Do: add documentation
# -------------------------------------------------------------------------
# built-ins
import sys
import os
import site
import importlib.util
#import logging as _logging
# if running in py2.7 we won't have access to pathlib yet until we boostrap
# the DCCsi
_MODULE_PATH = os.path.realpath(__file__) # To Do: what if frozen?
_DCCSIG_PATH = os.path.normpath(os.path.join(_MODULE_PATH, '../../../..'))
_DCCSIG_PATH = os.getenv('DCCSIG_PATH', _DCCSIG_PATH)
site.addsitedir(_DCCSIG_PATH)
# print(_DCCSIG_PATH)
# Lumberyard DCCsi site extensions
from pathlib import Path
# set up global space, logging etc.
import azpy
from azpy.env_bool import env_bool
from azpy.constants import ENVAR_DCCSI_GDEBUG
from azpy.constants import ENVAR_DCCSI_DEV_MODE
# these are for module debugging, set to false on submit
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = 'DCCsi.SDK.substance.builder.bootstrap'
_log_level = int(20)
if _G_DEBUG:
_log_level = int(10)
_LOGGER = azpy.initialize_logger(_PACKAGENAME,
log_to_file=True,
default_log_level=_log_level)
_LOGGER.debug('Starting up: {0}.'.format({_PACKAGENAME}))
_LOGGER.debug('_DCCSIG_PATH: {}'.format(_DCCSIG_PATH))
_LOGGER.debug('_G_DEBUG: {}'.format(_G_DEBUG))
_LOGGER.debug('_DCCSI_DEV_MODE: {}'.format(_DCCSI_DEV_MODE))
if _DCCSI_DEV_MODE:
from azpy.test.entry_test import connect_wing
foo = connect_wing()
# To Do: now that we have figured out the pattern and this is working
# we should consider initializing this earlier and reduce code lines?
# we can go ahead and just make sure the the DCCsi env is set
# config is SO generic this ensures we are importing a specific one
_spec_dccsi_config = importlib.util.spec_from_file_location("dccsi.config",
Path(_DCCSIG_PATH,
"config.py"))
_dccsi_config = importlib.util.module_from_spec(_spec_dccsi_config)
_spec_dccsi_config.loader.exec_module(_dccsi_config)
from dynaconf import settings
try:
from PySide2.QtWidgets import QApplication
except:
_dccsi_config.init_ly_pyside(settings.LY_DEV) # init for standalone
# running in the editor if the QtForPython Gem is enabled
# you should already have access and shouldn't need to set up
settings.setenv() # initialize the dynamic env and settings
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# substance automation toolkit (aka pysbs)
# to do: move this into SDK\Substance using per-app dynaconf config extension
from azpy.constants import PATH_PROGRAMFILES_X64
# this could be moved into a constants file (where?)
_PYSBS_DIR_PATH = Path(PATH_PROGRAMFILES_X64,
'Allegorithmic',
'Substance Automation Toolkit',
'Python API',
'install').resolve()
os.environ["DYNACONF_QPYSBS_DIR_PATH"] = str(_PYSBS_DIR_PATH)
os.environ["PYSBS_DIR_PATH"] = str(_PYSBS_DIR_PATH)
# standard paths we may use downstream
# To Do: move these into a dynaconf config extension specific to this tool?
from azpy.constants import ENVAR_LY_DEV
_LY_DEV = Path(os.getenv(ENVAR_LY_DEV,
settings.LY_DEV)).resolve()
from azpy.constants import ENVAR_LY_PROJECT_PATH
_LY_PROJECT_PATH = Path(os.getenv(ENVAR_LY_PROJECT_PATH,
settings.LY_PROJECT_PATH)).resolve()
from azpy.constants import ENVAR_DCCSI_SDK_PATH
_DCCSI_SDK_PATH = Path(os.getenv(ENVAR_DCCSI_SDK_PATH,
settings.DCCSIG_SDK_PATH)).resolve()
# build some reuseable path parts for the substance builder
_PROJECT_ASSETS_PATH = Path(_LY_PROJECT_PATH, 'Assets').resolve()
_PROJECT_MATERIALS_PATH = Path(_PROJECT_ASSETS_PATH, 'Materials').resolve()
# -------------------------------------------------------------------------
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == "__main__":
"""Run this file as main"""
_LOGGER.info('_LY_DEV: {}'.format(_LY_DEV))
_LOGGER.info('_LY_PROJECT_PATH: {}'.format(_LY_PROJECT_PATH))
_LOGGER.info('_DCCSI_SDK_PATH: {}'.format(_DCCSI_SDK_PATH))
_LOGGER.info('_PYSBS_DIR_PATH: {}'.format(_PYSBS_DIR_PATH))
_LOGGER.info('_PROJECT_ASSETS_PATH: {}'.format(_PROJECT_ASSETS_PATH))
_LOGGER.info('_PROJECT_MATERIALS_PATH: {}'.format(_PROJECT_MATERIALS_PATH))
if _G_DEBUG:
_dccsi_config.test_pyside2() # runs a small PySdie2 test
# remove the logger
del _LOGGER
# ---- END ---------------------------------------------------------------
@@ -0,0 +1,89 @@
#!wing
#!version=7.0
##################################################################
# Wing project file #
##################################################################
[project attributes]
debug.launch-configs = (2,
{'launch-GeaM41WYMGA1sEfm': ({'shared': True},
{'buildcmd': ('project',
None),
'env': ('custom',
[u'']),
'name': u'DCCSI_PY_MAYA',
'pyexec': ('custom',
u'${DCCSI_PY_MAYA}'),
'pypath': ('project',
[]),
'pyrunargs': ('project',
'-u'),
'runargs': u'',
'rundir': ('project',
u'')}),
'launch-WUN9lgYK6qYU7qE9': ({'shared': True},
{'buildcmd': ('project',
None),
'env': ('custom',
[u'']),
'name': u'DCCSI_PY_BASE',
'pyexec': ('custom',
u'${DCCSI_PY_BASE}'),
'pypath': ('project',
[]),
'pyrunargs': ('project',
'-u'),
'runargs': u'',
'rundir': ('project',
u'')}),
'launch-fAzXtHnoGUQ6FYXE': ({'shared': True},
{'buildcmd': ('project',
None),
'env': ('project',
[u'']),
'name': 'DCCSI_PY_DCCSI',
'pyexec': ('custom',
u'${DCCSI_PY_DCCSI}'),
'pypath': ('project',
[]),
'pyrunargs': ('project',
'-u'),
'runargs': u'',
'rundir': ('project',
u'')}),
'launch-oobMrvXFf1SwtYBg': ({'shared': True},
{'buildcmd': ('project',
None),
'env': ('custom',
[u'']),
'name': u'DCCSI_PY_DEFAULT',
'pyexec': ('custom',
u'${DCCSI_PY_DEFAULT}'),
'pypath': ('project',
[]),
'pyrunargs': ('project',
'-u'),
'runargs': u'',
'rundir': ('project',
u'')})})
proj.directory-list = [{'dirloc': loc('../..'),
'excludes': (),
'filter': u'*',
'include_hidden': True,
'recursive': True,
'watch_for_changes': True}]
proj.file-type = 'shared'
proj.home-dir = loc('../..')
proj.launch-config = {loc('../../SDK/Atom/Scripts/Python/DCC_Materials/maya_materials_export.py'): ('c'\
'ustom',
(u'',
'launch-GeaM41WYMGA1sEfm')),
loc('../../azpy/__init__.py'): ('custom',
(u'',
'launch-oobMrvXFf1SwtYBg')),
loc('../../azpy/env_base.py'): ('project',
(u'',
'launch-GeaM41WYMGA1sEfm')),
loc('../../azpy/maya/callbacks/node_message_callback_handler.py'): ('c'\
'ustom',
(u'',
'launch-GeaM41WYMGA1sEfm'))}
@@ -0,0 +1,25 @@
*.ilk
*.suo
*.user
*.o
*.temp
*.bootstrap.digests
*.log
*.exp
*.vssettings
*.exportlog
*.mayaSwatches
*.ma.swatches
*.dds
*.bak
*.bak2
Solutions
BinTemp
*.options
*.pyc
*.db
Cache
AssetProcessor_tmp.exe
Builders_Temp
Bin64vc*
$tmp*
@@ -0,0 +1,69 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.3dsmax.__init__"""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.3dsmax'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
__all__ = []
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def init():
"""If the 3dsmax api is required for a package/module to import,
then it should be initialized and added here so general imports
don't fail"""
# __all__.append()
# Make sure we can import the native apis
import pymxs
import MaxPlus
# Importing local packages/modules
pass
# -------------------------------------------------------------------------
del _LOGGER
@@ -0,0 +1,274 @@
# 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 -------------------------------------------
__copyright__ = "Copyright 2021, Amazon"
__credits__ = ["Jonny Galloway", "Ben Black"]
__license__ = "EULA"
__version__ = "0.0.1"
__status__ = "Prototype"
# --------------------------------------------------------------------------
# standard imports
import sys
import errno
import os
import os.path
import site
import re
import logging as _logging
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
_ORG_TAG = 'Amazon_Lumberyard'
_APP_TAG = 'DCCsi'
_TOOL_TAG = 'azpy'
_TYPE_TAG = 'module'
_PACKAGENAME = _TOOL_TAG
__all__ = ['initialize_logger',
'config_utils', 'render',
'constants', 'return_stub', 'synthetic_env',
'env_base', 'env_bool', 'test', 'dev',
'lumberyard', 'marmoset'] #'blender', 'maya', 'substance', 'houdini']
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# _ROOT_LOGGER = _logging.getLogger() # only use this if debugging
# https://stackoverflow.com/questions/56733085/how-to-know-the-current-file-path-after-being-frozen-into-an-executable-using-cx/56748839
#os.chdir(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
# -------------------------------------------------------------------------
# global space
# we need to set up basic access to the DCCsi
_MODULE_PATH = os.path.realpath(__file__) # To Do: what if frozen?
_DCCSIG_PATH = os.path.normpath(os.path.join(_MODULE_PATH, '../..'))
_DCCSIG_PATH = os.getenv('DCCSIG_PATH', _DCCSIG_PATH)
site.addsitedir(_DCCSIG_PATH)
# azpy
import azpy.return_stub as return_stub
import azpy.env_bool as env_bool
import azpy.constants as constants
import azpy.config_utils as config_utils
_G_DEBUG = env_bool.env_bool(constants.ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool.env_bool(constants.ENVAR_DCCSI_DEV_MODE, False)
# for py2.7 (Maya) we provide this, so we must assume some bootstrapping
# has occured, see DccScriptingInterface\\config.py (_DCCSI_PYTHON_LIB_PATH)
if sys.version_info.major >= 3:
import pathlib
else: # py2.x
import pathlib2 as pathlib # python 2 backport
# its mkdir() function supposedly supports exist_ok
# ^ but in practice still seems to bark
# TypeError: mkdir() got an unexpected keyword argument 'exist_ok'
if _G_DEBUG:
print('DCCsi debug breadcrumb, pathlib is: {}'.format(pathlib))
from pathlib import Path
# to be continued...
# get/set the project name
_LY_DEV = os.getenv(constants.ENVAR_LY_DEV,
config_utils.get_stub_check_path(in_path=os.getcwd(),
check_stub='engineroot.txt'))
# get/set the project name
_LY_PROJECT_TAG = os.getenv(constants.ENVAR_LY_PROJECT,
config_utils.get_current_project(_LY_DEV))
# project cache log dir path
_DCCSI_LOG_PATH = Path(os.getenv(constants.ENVAR_DCCSI_LOG_PATH,
Path(_LY_DEV,
'Cache',
_LY_PROJECT_TAG,
'pc', 'user', 'log', 'logs')))
for handler in _logging.root.handlers[:]:
_logging.root.removeHandler(handler)
# very basic root logger for early debugging, flip to while 1:
while 0:
_logging.basicConfig(level=_logging.DEBUG,
format=constants.FRMT_LOG_LONG,
datefmt='%m-%d %H:%M')
_logging.debug('azpy.rootlogger> root logger set up for debugging') # root logger
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def makedirs(folder, *args, **kwargs):
"""a makedirs for py2.7 support"""
try:
return os.makedirs(folder, exist_ok=True, *args, **kwargs)
except TypeError:
# Unexpected arguments encountered
pass
try:
# Should work is TypeError was caused by exist_ok, eg., Py2
return os.makedirs(folder, *args, **kwargs)
except OSError as e:
if e.errno != errno.EEXIST:
raise
if os.path.isfile(folder):
# folder is a file, raise OSError just like os.makedirs() in Py3
raise
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
class FileExistsError(Exception):
"""Implements a stand-in Exception for py2.7"""
def __init__(self, message, errors):
# Call the base class constructor with the parameters it needs
super(FileExistsError, self).__init__(message)
# Now for your custom code...
self.errors = errors
if sys.version_info.major < 3:
FileExistsError = FileExistsError
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def initialize_logger(name,
log_to_file=False,
default_log_level=_logging.NOTSET):
"""Start a azpy logger"""
_logger = _logging.getLogger(name)
_logger.propagate = False
if not _logger.handlers:
_log_level = int(os.getenv('DCCSI_LOGLEVEL', default_log_level))
if _G_DEBUG:
_log_level = int(10) # force when debugging
print('_log_level: {}'.format(_log_level))
if _log_level:
ch = _logging.StreamHandler(sys.stdout)
ch.setLevel(_log_level)
formatter = _logging.Formatter(constants.FRMT_LOG_LONG)
ch.setFormatter(formatter)
_logger.addHandler(ch)
_logger.setLevel(_log_level)
else:
_logger.addHandler(_logging.NullHandler())
# optionally add the log file handler (off by default)
if log_to_file:
_logger.info('DCCSI_LOG_PATH: {}'.format(_DCCSI_LOG_PATH))
try:
# exist_ok, isn't available in py2.7 pathlib
# because it doesn't exist for os.makedirs
# pathlib2 backport used instead (see above)
if sys.version_info.major >= 3:
_DCCSI_LOG_PATH.mkdir(parents=True, exist_ok=True)
else:
makedirs(str(_DCCSI_LOG_PATH.resolve())) # py2.7
except FileExistsError:
# except FileExistsError: doesn't exist in py2.7
_logger.debug("Folder is already there")
else:
_logger.debug("Folder was created")
_log_filepath = Path(_DCCSI_LOG_PATH, '{}.log'.format(name))
try:
_log_filepath.touch(mode=0o666, exist_ok=True)
except FileExistsError:
_logger.debug("Log file is already there: {}".format(_log_filepath))
else:
_logger.debug("Log file was created: {}".format(_log_filepath))
if _log_filepath.exists():
file_formatter = _logging.Formatter(constants.FRMT_LOG_LONG)
file_handler = _logging.FileHandler(str(_log_filepath))
file_handler.setLevel(_logging.DEBUG)
file_handler.setFormatter(file_formatter)
_logger.addHandler(file_handler)
return _logger
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# set up logger with both console and file _logging
if _G_DEBUG:
_LOGGER = initialize_logger(_PACKAGENAME, log_to_file=True)
else:
_LOGGER = initialize_logger(_PACKAGENAME, log_to_file=False)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# some simple logger tests
# evoke the filehandlers and test writting to the log file
if _G_DEBUG:
_LOGGER.info('Forced Info! for {0}.'.format({_PACKAGENAME}))
_LOGGER.error('Forced ERROR! for {0}.'.format({_PACKAGENAME}))
# debug breadcrumbs to check this module and used paths
_LOGGER.debug('MODULE_PATH: {}'.format(_MODULE_PATH))
_LOGGER.debug('LY_DEV_PATH: {}'.format(_LY_DEV))
_LOGGER.debug('DCCSI_PATH: {}'.format(_DCCSIG_PATH))
_LOGGER.debug('LY_PROJECT_TAG: {}'.format(_LY_PROJECT_TAG))
_LOGGER.debug('DCCSI_LOG_PATH: {}'.format(_DCCSI_LOG_PATH))
# -------------------------------------------------------------------------
def test_imports(_all=__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER):
# If in dev mode this will test imports of __all__
_logger.debug("~ Import triggered from: {0}".format(_pkg))
import importlib
for pkgStr in _all:
try:
# this is py2.7 compatible
# in py3.5+, we can use importlib.util instead
importlib.import_module('.' + pkgStr, _pkg)
_logger.debug("~ Imported module: {0}".format(pkgStr))
except Exception as e:
_logger.warning('~ {0}'.format(e))
_logger.warning("~ {0} :: ImportFail".format(pkgStr))
return False
return True
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
_LOGGER.debug('Testing Imports: {0}'.format(_PACKAGENAME))
test_imports(__all__)
# -------------------------------------------------------------------------
del _LOGGER
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
_G_DEBUG = True
_DCCSI_DEV_MODE = True
if _G_DEBUG:
print(_DCCSIG_PATH)
test_imports()
@@ -0,0 +1,69 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.blender.__init__"""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.blender'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
#_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
__all__ = []
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def init():
"""If the blender bpy api is required for a package/module to import,
then it should be initialized and added here so general imports
don't fail"""
# __all__.append()
# Make sure we can import the native apis
import bpy
# Importing local packages/modules
pass
# -------------------------------------------------------------------------
del _LOGGER
@@ -0,0 +1,202 @@
# 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 -------------------------------------------
import sys
import os
import re
import site
import logging as _logging
from pathlib import Path # note: we provide this in py2.7
# so using it here suggests some boostrapping has occured before using azpy
# --------------------------------------------------------------------------
_PACKAGENAME = 'azpy.config_utils'
FRMT_LOG_LONG = "[%(name)s][%(levelname)s] >> %(message)s (%(asctime)s; %(filename)s:%(lineno)d)"
_logging.basicConfig(level=_logging.INFO,
format=FRMT_LOG_LONG,
datefmt='%m-%d %H:%M')
_LOGGER = _logging.getLogger(_PACKAGENAME)
_LOGGER.debug('Initializing: {0}.'.format({_PACKAGENAME}))
__all__ = ['get_os', 'return_stub', 'get_stub_check_path',
'get_dccsi_config', 'get_current_project']
# note: this module should reamin py2.7 compatible (Maya) so no f'strings
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def get_os():
"""returns lumberyard dir names used in python path"""
if sys.platform.startswith('win'):
os_folder = "windows"
elif sys.platform.startswith('darwin'):
os_folder = "mac"
elif sys.platform.startswith('linux'):
os_folder = "linux_x64"
else:
message = str("DCCsi.azpy.config_utils.py: "
"Unexpectedly executing on operating system '{}'"
"".format(sys.platform))
raise RuntimeError(message)
return os_folder
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def return_stub_dir(stub_file='dccsi_stub'):
_dir_to_last_file = None
'''Take a file name (stub_file) and returns the directory of the file (stub_file)'''
# To Do: refactor to use pathlib object oriented Path
if _dir_to_last_file is None:
path = os.path.abspath(__file__)
while 1:
path, tail = os.path.split(path)
if (os.path.isfile(os.path.join(path, stub_file))):
break
if (len(tail) == 0):
path = ""
_LOGGER.debug('I was not able to find the path to that file '
'({}) in a walk-up from currnet path'
''.format(stub_file))
break
_dir_to_last_file = path
return _dir_to_last_file
# --------------------------------------------------------------------------
# -------------------------------------------------------------------------
def get_stub_check_path(in_path=os.getcwd(), 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 = Path(in_path).absolute()
while 1:
test_path = Path(path, check_stub)
if test_path.is_file():
return Path(test_path).parent
else:
path, tail = (path.parent, path.name)
if (len(tail) == 0):
return None
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# settings.setenv() # doing this will add the additional DYNACONF_ envars
def get_dccsi_config(dccsi_dirpath=return_stub_dir()):
"""Convenience method to set and retreive settings directly from module."""
# we can go ahead and just make sure the the DCCsi env is set
# config is SO generic this ensures we are importing a specific one
_module_tag = "dccsi.config"
_dccsi_path = Path(dccsi_dirpath, "config.py")
if _dccsi_path.exists():
if sys.version_info.major >= 3:
import importlib # note: py2.7 doesn't have importlib.util
import importlib.util
#from importlib import util
_spec_dccsi_config = importlib.util.spec_from_file_location(_module_tag,
str(_dccsi_path.resolve()))
_dccsi_config = importlib.util.module_from_spec(_spec_dccsi_config)
_spec_dccsi_config.loader.exec_module(_dccsi_config)
_LOGGER.debug('Executed config: {}'.format(_spec_dccsi_config))
else: # py2.x
import imp
_dccsi_config = imp.load_source(_module_tag, str(_dccsi_path.resolve()))
_LOGGER.debug('Imported config: {}'.format(_spec_dccsi_config))
return _dccsi_config
else:
return None
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def get_current_project(dev_folder=get_stub_check_path()):
"""Uses regex in lumberyard Dev\\bootstrap.cfg to retreive project tag str"""
boostrap_filepath = Path(dev_folder, "bootstrap.cfg")
if boostrap_filepath.exists():
bootstrap = open(str(boostrap_filepath), "r")
game_project_regex = re.compile(r"^sys_game_folder\s*=\s*(.*)")
for line in bootstrap:
game_folder_match = game_project_regex.match(line)
if game_folder_match:
_LOGGER.debug('Project is: {}'.format(game_folder_match.group(1)))
return game_folder_match.group(1)
return None
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def bootstrap_dccsi_py_libs(dccsi_dirpath=return_stub_dir()):
"""Builds and adds local site dir libs based on py version"""
from azpy.constants import STR_DCCSI_PYTHON_LIB_PATH # a path string constructor
_DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath,
sys.version_info[0],
sys.version_info[1])
if os.path.exists(_DCCSI_PYTHON_LIB_PATH):
_LOGGER.debug('Performed site.addsitedir({})'.format(_DCCSI_PYTHON_LIB_PATH))
site.addsitedir(_DCCSI_PYTHON_LIB_PATH) # PYTHONPATH
return _DCCSI_PYTHON_LIB_PATH
else:
message = "Doesn't exist: {}".format(_DCCSI_PYTHON_LIB_PATH)
_LOGGER.error(message)
raise NotADirectoryError(message)
# -------------------------------------------------------------------------
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
# happy print
_LOGGER.info("# {0} #".format('-' * 72))
_LOGGER.info('~ config_utils.py ... Running script as __main__')
_LOGGER.info("# {0} #".format('-' * 72))
_LOGGER.info('Current Work dir: {0}'.format(os.getcwd()))
_LOGGER.info('OS: {}'.format(get_os()))
_LOGGER.info('DCCSIG_PATH: {}'.format(return_stub_dir('dccsi_stub')))
_config = get_dccsi_config()
_LOGGER.info('DCCSI_CONFIG_PATH: {}'.format(_config))
_LOGGER.info('LY_DEV: {}'.format(get_stub_check_path('engineroot.txt')))
_LOGGER.info('LY_PROJECT: {}'.format(get_current_project(get_stub_check_path('engineroot.txt'))))
_LOGGER.info('DCCSI_PYTHON_LIB_PATH: {}'.format(bootstrap_dccsi_py_libs(return_stub_dir('dccsi_stub'))))
# custom prompt
sys.ps1 = "[azpy]>>"
@@ -0,0 +1,330 @@
# 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 -------------------------------------------
"""
Module Documentation:
DccScriptingInterface:: azpy//constants.py
This module is mainly a bunch of commony used constants, and default strings
So we can make an update here once that is used elsewhere.
< To Do: Further document module here>
"""
# -------------------------------------------------------------------------
# built-ins
import os
import sys
import site
import logging as _logging
# for this module to perform standalone
# we need to set up basic access to the DCCsi
_MODULE_PATH = os.path.realpath(__file__) # To Do: what if frozen?
_DCCSIG_PATH = os.path.normpath(os.path.join(_MODULE_PATH, '../..'))
_DCCSIG_PATH = os.getenv('DCCSIG_PATH', _DCCSIG_PATH)
site.addsitedir(_DCCSIG_PATH)
# azpy module
#import azpy.constants as cnst
from azpy.config_utils import return_stub_dir
import azpy.env_bool as env_bool
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# This is the first set of defined constants (and we use them here)
ENVAR_DCCSI_GDEBUG = str('DCCSI_GDEBUG')
ENVAR_DCCSI_DEV_MODE = str('DCCSI_DEV_MODE')
ENVAR_DCCSI_GDEBUGGER = str('DCCSI_GDEBUGGER')
ENVAR_DCCSI_LOGLEVEL = str('DCCSI_LOGLEVEL')
# Log formating
FRMT_LOG_LONG = "[%(name)s][%(levelname)s] >> %(message)s (%(asctime)s; %(filename)s:%(lineno)d)"
FRMT_LOG_SHRT = "[%(asctime)s][%(name)s][%(levelname)s] >> %(message)s"
# global space
_G_DEBUG = env_bool.env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool.env_bool(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = 'azpy.constants'
_log_level = int(20)
if _G_DEBUG:
_log_level = int(10)
_logging.basicConfig(level=_log_level,
format=FRMT_LOG_LONG,
datefmt='%m-%d %H:%M')
_LOGGER = _logging.getLogger(_PACKAGENAME)
_LOGGER.debug('Initializing: {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# String Literals
BITDEPTH64 = str('64bit')
# string literals
STR_CROSSBAR = str('{0}'.format('-' * 74))
STR_CROSSBAR_RL = str('{0}\r'.format(STR_CROSSBAR))
STR_CROSSBAR_NL = str('{0}\n'.format(STR_CROSSBAR))
# some common str tags
TAG_DEFAULT_COMPANY = str('Amazon.Lumberyard')
TAG_DEFAULT_PROJECT = str('DccScriptingInterface')
TAG_MOCK_PROJECT = str('MockProject')
TAG_DIR_LY_DEV = str('dev')
TAG_DIR_DCCSI_AZPY = str('azpy')
TAG_DIR_DCCSI_SDK = str('SDK')
TAG_DIR_LY_BUILD = str('windows_vs2019')
TAG_QT_PLUGIN_PATH = str('QT_PLUGIN_PATH')
# filesystem markers, stub file names.
STUB_LY_DEV = str('engineroot.txt')
STUB_LY_ROOT_PROJECT = str('ly_project_stub')
STUB_LY_ROOT_DCCSI = str('dccsi_stub')
STUB_LY_DCCSI_AZPY = str('dccsi_azpy_stub')
STUB_LY_DCCSI_SDK = str('dccsi_sdk_stub')
# config string consts, Meta Qualifiers
QUALIFIER_COMMENT = str('_meta_COMMENT')
QUALIFIER_TEMPLATE = str('_meta_{0}_TEMPLATE')
# config string consts, Section Qualifiers
QUALIFIER_EXAMPLE_SECTION = str('_Example_Block_')
QUALIFIER_INFO_SECTION = str('Info_Block')
QUALIFIER_GLOBAL_SECTION = str('Global_Block')
QUALIFIER_DEFAULT_ENV_SECTION = str('Default_Env_Block')
QUALIFIER_SERVICES_SECTION = str('Services_Block')
# config string consts, value, root and flags
QUALIFIER_VALUE = str('value')
QUALIFIER_ROOTPATH = str('rootPath')
QUALIFIER_ENVROOT = str('envRoot')
QUALIFIER_FLAGS = str('flags')
# config action flags
# the presence of a flag descriptor following a value block specifies a use case
FLAG_PATH_ADDPYTHONSITEDIR = str('addPySiteDir')
FLAG_PATH_ADDSYSPATH = str('addSysPath')
FLAG_PATH_SETSYSPATH = str('setSysPath')
FLAG_VAR_ADDENV = str('addEnv')
FLAG_VAR_SETENV = str('setEnv')
FLAG_PATH_ABSOLUTE = str('absolute')
FLAG_PATH_RELATIVE = str('relative')
FLAG_PROJECT_RELATIVE = str('project_relative')
FLAG_PATH_ROOT = str('root')
FLAG_PATH_BLOCKROOT = str('blockRoot')
# some common paths
PATH_PROGRAMFILES_X86 = str(os.environ['PROGRAMFILES(X86)'])
PATH_PROGRAMFILES_X64 = str(os.environ['PROGRAMFILES'])
# base env var key as str
ENVAR_COMPANY = str('COMPANY')
ENVAR_LY_PROJECT = str('LY_PROJECT')
ENVAR_LY_PROJECT_PATH = str('LY_PROJECT_PATH')
ENVAR_LY_DEV = str('LY_DEV')
ENVAR_DCCSIG_PATH = str('DCCSIG_PATH')
ENVAR_DCCSI_AZPY_PATH = str('DCCSI_AZPY_PATH')
ENVAR_DCCSI_SDK_PATH = str('DCCSI_SDK_PATH')
ENVAR_LY_BUILD_DIR_NAME = str('LY_BUILD_DIR_NAME')
ENVAR_LY_BUILD_PATH = str('LY_BUILD_PATH')
ENVAR_QT_PLUGIN_PATH = TAG_QT_PLUGIN_PATH
ENVAR_QTFORPYTHON_PATH = str('QTFORPYTHON_PATH')
ENVAR_LY_BIN_PATH = str('LY_BIN_PATH')
ENVAR_DCCSI_LOG_PATH = str('DCCSI_LOG_PATH')
ENVAR_DCCSI_LAUNCHERS_PATH = str('DCCSI_LAUNCHERS_PATH')
ENVAR_DCCSI_PY_VERSION_MAJOR = str('DCCSI_PY_VERSION_MAJOR')
ENVAR_DCCSI_PY_VERSION_MINOR = str('DCCSI_PY_VERSION_MINOR')
ENVAR_DCCSI_PYTHON_PATH = str('DCCSI_PYTHON_PATH')
ENVAR_DCCSI_PYTHON_LIB_PATH = str('DCCSI_PYTHON_LIB_PATH')
ENVAR_DCCSI_PYTHON_INSTALL = str('DCCSI_PYTHON_INSTALL')
ENVAR_WINGHOME = str('WINGHOME')
ENVAR_DCCSI_WING_VERSION_MAJOR = str('DCCSI_WING_VERSION_MAJOR')
ENVAR_DCCSI_WING_VERSION_MINOR = str('DCCSI_WING_VERSION_MINOR')
ENVAR_DCCSI_PY_BASE = str('DCCSI_PY_BASE')
ENVAR_DCCSI_PY_DCCSI = str('DCCSI_PY_DCCSI')
ENVAR_DCCSI_PY_MAYA = str('DCCSI_PY_MAYA')
ENVAR_DCCSI_PY_DEFAULT = str('DCCSI_PY_DEFAULT')
ENVAR_DCCSI_MAYA_VERSION = str('DCCSI_MAYA_VERSION')
ENVAR_MAYA_LOCATION = str('MAYA_LOCATION')
ENVAR_DCCSI_SDK_MAYA_PATH = str('DCCSI_SDK_MAYA_PATH')
ENVAR_MAYA_MODULE_PATH = str('MAYA_MODULE_PATH')
ENVAR_MAYA_BIN_PATH = str('MAYA_BIN_PATH')
ENVAR_DCCSI_MAYA_PLUG_IN_PATH = str('DCCSI_MAYA_PLUG_IN_PATH')
ENVAR_MAYA_PLUG_IN_PATH = str('MAYA_PLUG_IN_PATH')
ENVAR_DCCSI_MAYA_SHELF_PATH = str('DCCSI_MAYA_SHELF_PATH')
ENVAR_MAYA_SHELF_PATH = str('MAYA_SHELF_PATH')
ENVAR_DCCSI_MAYA_XBMLANGPATH = str('DCCSI_MAYA_XBMLANGPATH')
ENVAR_XBMLANGPATH = str('XBMLANGPATH')
ENVAR_DCCSI_MAYA_SCRIPT_MEL_PATH = str('DCCSI_MAYA_SCRIPT_MEL_PATH')
ENVAR_DCCSI_MAYA_SCRIPT_PY_PATH = str('DCCSI_MAYA_SCRIPT_PY_PATH')
ENVAR_MAYA_SCRIPT_PATH = str('MAYA_SCRIPT_PATH')
ENVAR_DCCSI_MAYA_SET_CALLBACKS = str('DCCSI_MAYA_SET_CALLBACKS')
TAG_LY_DCC_MAYA_MEL = 'dccsi_setup.mel'
TAG_MAYA_WORKSPACE = 'workspace.mel'
# dcc scripting interface common and default paths
PATH_LY_DEV = str(return_stub_dir(STUB_LY_DEV))
PATH_DCCSIG_PATH = str(return_stub_dir(STUB_LY_ROOT_DCCSI))
PATH_DCCSI_AZPY_PATH = str(return_stub_dir(STUB_LY_DCCSI_AZPY))
PATH_DCCSI_SDK_PATH = str('{0}\\{1}'.format(PATH_DCCSIG_PATH, TAG_DIR_DCCSI_SDK))
# logging into the cache
PATH_DCCSI_LOG_PATH = str('{LY_DEV}\\Cache\\{LY_PROJECT}\\pc\\user\\log\\logs')
# dev \ <build> \
STR_CONSTRUCT_LY_BUILD_PATH = str('{0}\\{1}')
PATH_LY_BUILD_PATH = str(STR_CONSTRUCT_LY_BUILD_PATH.format(PATH_LY_DEV,
TAG_DIR_LY_BUILD))
# ENVAR_QT_PLUGIN_PATH = TAG_QT_PLUGIN_PATH
STR_QTPLUGIN_DIR = str('{0}\\bin\\profile\\EditorPlugins')
STR_QTFORPYTHON_PATH = str('{0}\\Gems\\QtForPython\\3rdParty\\pyside2\\windows\\release')
STR_LY_BIN_PATH = str('{0}\\bin\\profile')
PATH_LY_BUILD_PATH = str('{0}\\{1}'.format(PATH_LY_DEV, TAG_DIR_LY_BUILD))
PATH_QTFORPYTHON_PATH = str(STR_QTFORPYTHON_PATH.format(PATH_LY_DEV))
PATH_QT_PLUGIN_PATH = str(STR_QTPLUGIN_DIR).format(PATH_LY_BUILD_PATH)
PATH_LY_BIN_PATH = str(STR_LY_BIN_PATH).format(PATH_LY_BUILD_PATH)
# py path string, parts, etc.
TAG_DEFAULT_PY = str('Launch_pyBASE.bat')
# config file stuff
FILENAME_DEFAULT_CONFIG = str('DCCSI_config.json')
#python and site-dir
TAG_DCCSI_PY_VERSION_MAJOR = str(3)
TAG_DCCSI_PY_VERSION_MINOR = str(7)
TAG_DCCSI_PY_VERSION_RELEASE = str(5)
TAG_PYTHON_EXE = str('python.exe')
TAG_TOOLS_DIR = str('Tools\\Python')
TAG_PLATFORM = str('windows')
STR_CONSTRUCT_DCCSI_PYTHON_INSTALL = str('{0}\\{1}\\{2}.{3}.{4}\\{5}')
PATH_DCCSI_PYTHON_PATH = str(STR_CONSTRUCT_DCCSI_PYTHON_INSTALL.format(PATH_LY_DEV,
TAG_TOOLS_DIR,
TAG_DCCSI_PY_VERSION_MAJOR,
TAG_DCCSI_PY_VERSION_MINOR,
TAG_DCCSI_PY_VERSION_RELEASE,
TAG_PLATFORM))
PATH_DCCSI_PY_BASE = str('{0}\\{1}').format(PATH_DCCSI_PYTHON_PATH, TAG_PYTHON_EXE)
PATH_DCCSI_PY_DEFAULT = PATH_DCCSI_PY_BASE
# bootstrap site-packages by version
TAG_PY_MAJOR = str(sys.version_info.major) # future proof
TAG_PY_MINOR = str(sys.version_info.minor)
STR_DCCSI_PYTHON_LIB_PATH = str('{0}\\3rdParty\\Python\\Lib\\{1}.x\\{1}.{2}.x\\site-packages')
PATH_DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(PATH_DCCSIG_PATH,
TAG_PY_MAJOR,
TAG_PY_MINOR)
# default path strings (and afe associated attributes)
TAG_DEFAULT_WING_MAJOR_VER = str(7)
TAG_DEFAULT_WING_MINOR_VER = str(1)
TAG_WING_IDE = str('\\Wing IDE ') # old, pre 7
TAG_WING_PRO = str('\\Wing Pro ') # new 7+
STR_CONSTRUCT_WING_PATH = str('{progX86}{wing_tag}{major}.{minor}')
PATH_DEFAULT_WINGHOME = str('{0}{1}{2}.{3}'
''.format(PATH_PROGRAMFILES_X86,
TAG_WING_PRO,
TAG_DEFAULT_WING_MAJOR_VER,
TAG_DEFAULT_WING_MINOR_VER))
PATH_SAT_INSTALL_PATH = str('{0}\\{1}\\{2}\\{3}\\{4}'
''.format(PATH_PROGRAMFILES_X64,
'Allegorithmic',
'Substance Automation Toolkit',
'Python API',
'install'))
# -------------------------------------------------------------------------
###########################################################################
# 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
# this is a top level module and to reduce cyclical azpy imports
# it only has a basic logger configured, add log to console
_handler = _logging.StreamHandler(sys.stdout)
_handler.setLevel(_logging.DEBUG)
_formatter = _logging.Formatter(FRMT_LOG_LONG)
_handler.setFormatter(_formatter)
_LOGGER.addHandler(_handler)
# happy print
_LOGGER.info(STR_CROSSBAR)
_LOGGER.info('~ constants.py ... Running script as __main__')
_LOGGER.info(STR_CROSSBAR)
# this is just a debug developer convenience print (for testing acess)
import pkgutil
_LOGGER.info('Current working dir: {0}'.format(os.getcwd()))
search_path = ['.'] # set to None to see all modules importable from sys.path
all_modules = [x[1] for x in pkgutil.iter_modules(path=search_path)]
_LOGGER.info('All Available Modules in working dir: {0}'.format(all_modules))
# test anything procedurally generated
_LOGGER.info('Testing procedural env paths ...')
from pathlib import Path
_stash_dict = {}
_stash_dict['LY_DEV'] = Path(PATH_LY_DEV)
_stash_dict['DCCSIG_PATH'] = Path(PATH_DCCSIG_PATH)
_stash_dict['DCCSI_AZPY_PATH'] = Path(PATH_DCCSI_AZPY_PATH)
_stash_dict['DCCSI_SDK_PATH'] = Path(PATH_DCCSI_SDK_PATH)
_stash_dict['DCCSI_PYTHON_PATH'] = Path(PATH_DCCSI_PYTHON_PATH)
_stash_dict['DCCSI_PY_BASE'] = Path(PATH_DCCSI_PY_BASE)
_stash_dict['DCCSI_PYTHON_LIB_PATH'] = Path(PATH_DCCSI_PYTHON_LIB_PATH)
_stash_dict['LY_BUILD_PATH'] = Path(PATH_LY_BUILD_PATH)
_stash_dict['LY_BIN_PATH'] = Path(PATH_LY_BIN_PATH)
_stash_dict['QTFORPYTHON_PATH'] = Path(PATH_QTFORPYTHON_PATH)
_stash_dict['QT_PLUGIN_PATH'] = Path(PATH_QT_PLUGIN_PATH)
_stash_dict['SAT_INSTALL_PATH'] = Path(PATH_SAT_INSTALL_PATH)
# ---------------------------------------------------------------------
# py 2 and 3 compatible iter
def get_items(dict_object):
for key in dict_object:
yield key, dict_object[key]
for key, value in get_items(_stash_dict):
# check if path exists
try:
value.exists()
_LOGGER.info('{0}: {1}'.format(key, value))
except Exception as e:
_LOGGER.warning('FAILED PATH: {}'.format(e))
# custom prompt
sys.ps1 = "[azpy]>>"
@@ -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__ = ['ide', 'utils']
@@ -0,0 +1,140 @@
# 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 -------------------------------------------
from __future__ import unicode_literals
# -------------------------------------------------------------------------
'''
Module: <DCCsi>\azpy\shared\common\base_env.py
This module packs the most basic set of environment variables.
Easy access IF you know the environment is setup.
We assume these are already set up in the envionment.
The str() tag for each ENVAR is defined in azpy.shared.common.constants
Allowing those str('tag') to easily be changed in a single location.
If they are paths for code acess we assume they were put on the sys path.
'''
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
__author__ = 'HogJonny'
__project__ = 'DccScriptingInterface'
# -------------------------------------------------------------------------
# built in's
import os
import sys
import json
import logging as _logging
# 3rd Party
from box import Box
from pathlib import Path
# Lumberyard extensions
from azpy.constants import *
from azpy.shared.common.core_utils import return_stub
from azpy.shared.common.core_utils import get_stub_check_path
from azpy.shared.common.envar_utils import get_envar_default
from azpy.shared.common.envar_utils import set_envar_defaults
from azpy.shared.common.envar_utils import Validate_Envar
# -------------------------------------------------------------------------
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.env_base'
_LOGGER = _logging.getLogger(_PACKAGENAME)
_LOGGER.debug('Initializing: {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
# set up base totally non-functional defauls (denoted with $<ENVAR>)
# if something hasn't been set, it will stay '$<envar>'
_BASE_ENVVAR_DICT = Box(ordered_box=True)
# project tag
_BASE_ENVVAR_DICT[ENVAR_LY_PROJECT] = '${0}'.format(ENVAR_LY_PROJECT)
# paths
_BASE_ENVVAR_DICT[ENVAR_LY_DEV] = Path('${0}'.format(ENVAR_LY_DEV))
_BASE_ENVVAR_DICT[ENVAR_LY_PROJECT_PATH] = Path('${0}'.format(ENVAR_LY_PROJECT_PATH))
_BASE_ENVVAR_DICT[ENVAR_DCCSIG_PATH] = Path('${0}'.format(ENVAR_DCCSIG_PATH))
_BASE_ENVVAR_DICT[ENVAR_DCCSI_LOG_PATH] = Path('${0}'.format(ENVAR_DCCSI_LOG_PATH))
_BASE_ENVVAR_DICT[ENVAR_DCCSI_AZPY_PATH] = Path('${0}'.format(ENVAR_DCCSI_AZPY_PATH))
_BASE_ENVVAR_DICT[ENVAR_DCCSI_SDK_PATH] = Path('${0}'.format(ENVAR_DCCSI_SDK_PATH))
# dev env flags
_BASE_ENVVAR_DICT[ENVAR_DCCSI_GDEBUG] = '${0}'.format(ENVAR_DCCSI_GDEBUG)
_BASE_ENVVAR_DICT[ENVAR_DCCSI_DEV_MODE] = '${0}'.format(ENVAR_DCCSI_DEV_MODE)
_BASE_ENVVAR_DICT[ENVAR_DCCSI_GDEBUGGER] = '${0}'.format(ENVAR_DCCSI_GDEBUGGER)
# default python dist
_BASE_ENVVAR_DICT[ENVAR_DCCSI_PY_VERSION_MAJOR] = '${0}'.format(ENVAR_DCCSI_PY_VERSION_MAJOR)
_BASE_ENVVAR_DICT[ENVAR_DCCSI_PY_VERSION_MINOR] = '${0}'.format(ENVAR_DCCSI_PY_VERSION_MINOR)
_BASE_ENVVAR_DICT[ENVAR_DCCSI_PYTHON_PATH] = '${0}'.format(ENVAR_DCCSI_PYTHON_PATH)
_BASE_ENVVAR_DICT[ENVAR_DCCSI_PYTHON_LIB_PATH] = '${0}'.format(ENVAR_DCCSI_PYTHON_LIB_PATH)
# try to fetch and set the base values from the environment
# this makes sure all envars set, are resolved on import
_BASE_ENVVAR_DICT = set_envar_defaults(_BASE_ENVVAR_DICT)
# If they are not set in the environment they should reamin the default
# value assigned above in the pattern $<SOME_ENVAR>
# -------------------------------------------------------------------------
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
# srun simple tests?
test = True
# happy print
_LOGGER.info("# {0} #".format('-' * 72))
_LOGGER.info('~ config_utils.py ... Running script as __main__')
_LOGGER.info("# {0} #\r".format('-' * 72))
# print(setEnvarDefaults(), '\r') #<-- not necissary, already called
# print(BASE_ENVVAR_VALUES, '\r')
_LOGGER.info('Pretty print: _BASE_ENVVAR_DICT')
print(json.dumps(_BASE_ENVVAR_DICT,
indent=4, sort_keys=False,
ensure_ascii=False), '\r')
# retreive a Path type key from the Box
foo = _BASE_ENVVAR_DICT[ENVAR_LY_DEV]
_LOGGER.info('~ foo is: {0}'.format(type(foo), foo))
# simple tests
_ENV_TAG = 'LY_DEV'
foo = get_envar_default(_ENV_TAG)
_LOGGER.info("~ Results of getVar on tag, '{0}':'{1}'\r".format(_ENV_TAG, foo))
envar_value = Validate_Envar(envar=_ENV_TAG)
_LOGGER.info('~ Repr is: {0}\r'.format(str(repr(envar_value))))
_LOGGER.info("~ Results of ValidateEnvar(envar='{0}')=='{1}'\r".format(_ENV_TAG, envar_value))
# custom prompt
sys.ps1 = "[azpy]>>"
@@ -0,0 +1,30 @@
# 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 -------------------------------------------
import os
# -- envar util ----------------------------------------------------------
# not putting this in the env_util.py to reduce cyclical importing
def env_bool(envar, default=False):
"""cast a env bool to a python bool"""
envar_test = os.getenv(envar, default)
# check 'False', 'false', and '0' since all are non-empty
# env comes back as string and normally coerced to True.
if envar_test in ('True', 'true', '1'):
return True
elif envar_test in ('False', 'false', '0'):
return False
else:
return envar_test
# -------------------------------------------------------------------------
@@ -0,0 +1,69 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.houdini.__init__"""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.houdini'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
#_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
__all__ = []
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def init():
"""If the houdini api is required for a package/module to import,
then it should be initialized and added here so general imports
don't fail"""
# __all__.append()
# Make sure we can import the native apis
import hou
# Importing local packages/modules
pass
# -------------------------------------------------------------------------
del _LOGGER
@@ -0,0 +1,70 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.lumberyard.__init__
All Lumberyard render related packages/modules should live here."""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.lumberyard'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
__all__ = []
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def init():
"""If the lumberyard azlmbr api is required for a package/module to
import, then it should be initialized and added here so general imports
don't fail"""
# __all__.append()
# Make sure we can import the native apis
#import <some atom api>
# Importing local packages/modules
pass
# -------------------------------------------------------------------------
del _LOGGER
@@ -0,0 +1,69 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.houdini.__init__"""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.marmoset'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
__all__ = []
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def init():
"""If the marmoset api is required for a package/module to import,
then it should be initialized and added here so general imports
don't fail"""
# __all__.append()
# Make sure we can import the native apis
import mset
# Importing local packages/modules
pass
# -------------------------------------------------------------------------
del _LOGGER
@@ -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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.maya.__init__"""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
__all__ = []
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def init():
"""If the maya api 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 maya.cmds as mc
import maya.api.OpenMaya as om
__all__.append('callbacks')
__all__.append('helpers')
__all__.append('toolbits')
# Importing local packages/modules
pass
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
del _LOGGER
@@ -0,0 +1,41 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.maya.callbacks.__init__"""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya.callbacks'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
__all__ = ['event_callback_handler',
'node_message_callback_handler',
'on_shader_rename']
del _LOGGER
#--------------------------------------------------------------------------
@@ -0,0 +1,226 @@
# 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 -------------------------------------------
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# <DCCsi>\\azpy\\maya\\\callbacks\\event_callback_handler.py
# Maya event callback handler
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
"""
Module Documentation:
<DCCsi>:: azpy//maya//callbacks//event_callback_handler.py
.. module:: event_callback_handler
:synopsis: Simple event based callback_event handler
using maya.api.OpenMaya (api2)
.. :note: nothing mundane to declare
.. :attention: callbacks should be uninstalled on exit
.. :warning: maya may crash on exit if callbacks are not uninstalled
.. Usage:
def test_func(*arg):
_logging.debug("~ test_func ccallbackEvent fired! arg={0}"
"".format(arg))
#register an event based based callback event
cb = EventCallbackHandler('NameChanged', test_func)
.. Reference:
The following call will return all the available events that can be
passed into the EventCallbackHandler.
import maya.api.OpenMaya as openmaya
openmaya.MEventMessage.getEventNames()
Important ones for quick reference are:
quitApplication
SelectionChanged
NameChanged
SceneSaved
NewSceneOpened
SceneOpened
PostSceneRead
workspaceChanged
.. moduleauthor:: Amazon Lumberyard
"""
#--------------------------------------------------------------------------
# -- Standard Python modules
import os
# -- External Python modules
# -- Lumberyard 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
# -- Maya Modules
import maya.api.OpenMaya as openmaya
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# -- Misc Global Space Definitions
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya.callbacks.event_callback_handler'
_LOGGER = azpy.initialize_logger(_PACKAGENAME, default_log_level=int(20))
_LOGGER.debug('Invoking:: {0}.'.format({_PACKAGENAME}))
# --------------------------------------------------------------------------
# =========================================================================
# First Class
# =========================================================================
class EventCallbackHandler(object):
"""
A simple Maya event based callback_event handler class
:ivar callback_event: stores event type trigger for a maya callback_event
:vartype event: for example, 'NameChanged'
:ivar this_function: stores this_function to call when callback_event is triggered
:vartype this_function: for example,
cb = EventCallbackHandler(callback_event='NameChanged',
this_function=test_func)
"""
# --BASE-METHODS-------------------------------------------------------
# --constructor-
def __init__(self, callback_event, this_function, install=True):
"""
initializes a callback_event object
"""
# callback_event id storage
self._callback_id = None
# state tracker
self._message_id_set = None
# the callback_event event trigger
self._callback_event = callback_event
# the thing to do on callback_event
self._function = this_function
if install:
self.install()
# --properties---------------------------------------------------------
@property
def callback_id(self):
return self._callback_id
@property
def callback_event(self):
return self._callback_event
@property
def this_function(self):
return self._this_function
# --method-------------------------------------------------------------
def install(self):
"""
installs this callback_event for event, which makes it active
"""
add_event_method = openmaya.MEventMessage.addEventCallback
# when called, check if it's already installed
if self._callback_id:
_LOGGER.warning("EventCallback::{0}:{1}, is already installed"
"".format(self._callback_event,
self._function.__name__))
return False
# else try to install it
try:
self._callback_id = add_event_method(self._callback_event,
self._function)
except Exception as e:
_LOGGER.error("Failed to install EventCallback::'{0}:{1}'"
"".format(self._callback_event,
self._function.__name__))
self._message_id_set = False
else:
_LOGGER.debug("Installing EventCallback::{0}:{1}"
"".format(self._callback_event,
self._function.__name__))
self._message_id_set = True
return self._callback_id
# --method-------------------------------------------------------------
def uninstall(self):
"""
uninstalls this callback_event for the event, deactivates
"""
remove_event_callback = openmaya.MEventMessage.removeCallback
if self._callback_id:
try:
remove_event_callback(self._callback_id)
except Exception as e:
_LOGGER.error("Couldn't remove EventCallback::{0}:{1}"
"".format(self._callback_event,
self._function.__name__))
self._callback_id = None
self._message_id_set = None
_LOGGER.debug("Uninstalled the EventCallback::{0}:{1}"
"".format(self._callback_event,
self._function.__name__))
return True
else:
_LOGGER.warning("EventCallback::{0}:{1}, not currently installed"
"".format(self._callback_event,
self._function.__name__))
return False
# --method-------------------------------------------------------------
def __del__(self):
"""
if object is deleted, the callback_event is uninstalled
"""
self.uninstall()
# -------------------------------------------------------------------------
#==========================================================================
# Class Test
#==========================================================================
if __name__ == "__main__":
def test_func(*arg):
print("~ test_func callback_event fired! arg={0}"
"".format(arg))
cb = EventCallbackHandler('NameChanged', test_func)
cb.install()
# callback_event is active
#cb.uninstall()
## callback_event not active
@@ -0,0 +1,289 @@
# 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 -------------------------------------------
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# <DCCsi>\\azpy\\maya\\\callbacks\\node_message_callback_handler.py
# Maya node message callback handler
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
"""
.. module:: node_message_callback_handler
:synopsis: this module contains code related to mNodeName message based callbacks in Maya
.. moduleauthor:: Amazon Lumberyard
.. :note: nothing mundane to declare
.. :attention: callbacks should be uninstalled on exit
.. :warning: maya may crash on exit if callbacks are not uninstalled
.. Usage:
< To Do >
.. Version:
0.1.0 | prototype
.. History:
< To Do >
.. Reference:
MNodeMessage
This class is used to register callbacks for dependency mNodeName messages of specific dependency nodes.
http://download.autodesk.com/us/maya/2011help/API/class_m_node_message.html
There are 4 add thisCallback methods which will add callbacks for the following types of messages:
Attribute Changed
Attribute Added or Removed
Node Dirty
Name Changed
If we import OpenMaya,
import maya.api.OpenMaya as om
from maya.api.OpenMaya import MNodeMessage as mNM
The valid callbacks for usage are:
mNM.addAttributeChangedCallback
mNM.addAttributeAddedOrRemovedCallback
mNM.addNodeDirtyCallback
mNM.addNodeDirtyPlugCallback
mNM.addNameChangedCallback
mNM.addNodeAboutToDeleteCallback
mNM.addNodePreRemovalCallback
mNM.addNodeDestroyedCallback
mNM.addKeyableChangeOverride
"""
# --------------------------------------------------------------------------
# -- Standard Python modules
import os
# -- External Python modules
# -- Lumberyard 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
# -- Maya Modules --
import maya.api.OpenMaya as om
import maya.cmds as mc
#--------------------------------------------------------------------------
# -------------------------------------------------------------------------
# -- Misc Global Space Definitions
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya.callbacks.event_callback_handler'
_LOGGER = azpy.initialize_logger(_PACKAGENAME, default_log_level=int(20))
_LOGGER.debug('Invoking:: {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
# =========================================================================
# First Class
# =========================================================================
class NodeMessageCallbackHandler(object):
"""
< To Do: document Class >
"""
# --BASE-METHODS-------------------------------------------------------
# --constructor-
def __init__(self,
this_function,
this_callback,
mNodeName=None, # keep maya camel case formatting?
install=True,
*args, **kwargs):
"""
initializes a this_callback object
"""
# this_callback id storage
self._callback_type_id = None
# state tracker
self._message_id_set = None
# the this_callback event trigger
self._this_callback = this_callback
# the thing to do on this_callback
self._function = this_function
# this handlers object mNodeName
# passing in a null MObject (ie, without a name as an argument)
# registers the this_callback to get all name changes in the scene
# if you wanted to monitor a specific object's name changes
# you could pass a name to the MObject
if mNodeName is None:
self._m_object = om.MObject()
else:
self._m_object = om.MObject(mNodeName)
# install / activate this callback
if install:
self.install()
#----------------------------------------------------------------------
#--properties----------------------------------------------------------
@property
def callback_id(self):
return self._callback_type_id
@property
def this_callback(self):
return self._this_callback
@property
def this_function(self):
return self._this_function
#--properties----------------------------------------------------------
# --method-------------------------------------------------------------
def install(self):
"""
installs this this_callback for event, which makes it active
"""
# when called, check if it's already installed
if self._callback_type_id:
_LOGGER.warning("NodeMessageCallback::{0}:{1}, is already installed"
"".format(self._this_callback,
self._function.__name__))
return False
# else try to install it
try:
self._callback_type_id = self._this_callback(self._m_object,
self._function)
except Exception as e:
_LOGGER.error("Failed to install NodeMessageCallback::'{0}:{1}'"
"".format(self._this_callback,
self._function.__name__))
self._message_id_set = False
else:
_LOGGER.debug("Installing NodeMessageCallback::{0}:{1}"
"".format(self._this_callback,
self._function.__name__))
self._message_id_set = True
return self._callback_type_id
#----------------------------------------------------------------------
# --method-------------------------------------------------------------
def uninstall(self):
"""
uninstalls this thisCallback for the event, deactivates
"""
if self._callback_type_id:
try:
om.MMessage.removeCallback(self._callback_type_id)
except Exception as e:
_LOGGER.error("Couldn't remove NodeMessageCallback::{0}:{1}"
"".format(self._this_callback,
self._function.__name__))
self._callback_type_id = None
self._message_id_set = None
_LOGGER.debug("Uninstalled the NodeMessageCallback::{0}:{1}"
"".format(self._this_callback,
self._function.__name__))
return True
else:
_LOGGER.warning("NodeMessageCallback::{0}:{1}, not currently installed"
"".format(self._this_callback,
self._function.__name__))
return False
#----------------------------------------------------------------------
# --method-------------------------------------------------------------
def __del__(self):
"""
if object is deleted, the thisCallback is uninstalled
"""
self.uninstall()
#----------------------------------------------------------------------
# -------------------------------------------------------------------------
# =========================================================================
# Public Functions
# =========================================================================
# --First Function---------------------------------------------------------
def testNameChanged(*args):
# get node
try:
mNode = args[0]
except Exception as e:
mNode = None
_LOGGER.debug('\t~ no node')
_LOGGER.debug('\t~ warning: {0}'.format(e))
# get old name
try:
oldName = args[1]
except Exception as e:
oldName = None
_LOGGER.debug('\t~ no oldName')
_LOGGER.debug('\t~ warning: {0}'.format(e))
# convert the MObject to a dep mNode
try:
depNode = om.MFnDependencyNode(mNode)
except Exception as e:
depNode = None
_LOGGER.debug('\t~ no depNode')
_LOGGER.debug('\t~ warning: {0}'.format(e))
if oldName == (u""): oldName = 'null'
# get node type
try:
nodeType = depNode.typeName()
except Exception as e:
nodeType = None
_LOGGER.debug('\t~ no nodeType')
_LOGGER.debug('\t~ warning: {0}'.format(e))
# get node name
try:
nodeName = depNode.name()
except Exception as e:
nodeName = None
_LOGGER.debug('\t~ no nodeType')
_LOGGER.debug('\t~ warning: {0}'.format(e))
_LOGGER.debug('----\ntestNameChangedCallback')
_LOGGER.debug('newName: {0}'.format(nodeName))
_LOGGER.debug('oldName: {0}'.format(oldName))
_LOGGER.debug('nodeType: {0}'.format(nodeType))
return depNode
# -------------------------------------------------------------------------
#==========================================================================
# Run as LICENSE
#==========================================================================
if __name__ == '__main__':
name_changed_callback = om.MNodeMessage.addNameChangedCallback
ncbh = NodeMessageCallbackHandler(name_changed_callback,
testNameChanged)
@@ -0,0 +1,220 @@
# 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 -------------------------------------------
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# <DCCsi>\\azpy\\maya\\\callbacks\\on_shader_rename.py
# Maya node message callback handler
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
"""
.. module:: on_shader_rename
:synopsis: when a node name change fires off a callback, if that callback
is registered to this function the node will be passed in. If the node
is a shader node, we will find that shaders shadingGroup and give it a
similar name.
.. moduleauthor:: Amazon Lumberyard
.. :note: nothing mundane to declare
.. :attention: callbacks should be uninstalled on exit
.. :warning: maya may crash on exit if callbacks are not uninstalled
.. Usage:
when a rename node callback is fired, the node information is passed
to the function on_shader_rename(*args) as a tuple
args[0] is OpenMaya.MObject, which is the object
args[1] is the node previous name
args[2] None (not sure what else could get passed in here)
We get the dependancy node
depNode = om.MFnDependencyNode(arg[0])
We can check the node type
nodeType = mc.nodeType( depNode.name(), api=True )
If it's shader type the we are looking for, we can then find it's
shading engine (shadingGroup), we are looking for u"kPluginHardwareShader"
which is a dx11Shader (and possibly related hardware shader types)
if nodeType == "kPluginHardwareShader":
sG = findShadingGroup(depNode)
The function findShadingGroup(materialDepNode), will search the shaders
plugs for a om.MFn.kShadingEngine, if found it will return that node
Then we rename that node: sG.setName('{0}SG'.format(depNode.name()))
.. Version:
0.1.0 | prototype
.. History:
< To Do >
.. Reference:
< To Do >
"""
# --------------------------------------------------------------------------
# -- Standard Python modules
import os
# -- External Python modules
# -- Lumberyard 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
# -- Maya Modules
import maya.api.OpenMaya as om
import maya.cmds as mc
# -------------------------------------------------------------------------
# --------------------------------------------------------------------------
# -- Misc Global Space Definitions
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya.callbacks.on_shader_rename'
_LOGGER = azpy.initialize_logger(_PACKAGENAME, default_log_level=int(20))
_LOGGER.debug('Invoking:: {0}.'.format({_PACKAGENAME}))
# --------------------------------------------------------------------------
# =========================================================================
# Public Functions
# =========================================================================
# --First Function---------------------------------------------------------
def find_shading_group(materialDepNode):
""" To Do: Document"""
# before moving on, let's see if we can figure out if this is a material
# since we KNOW currently we are working with a specific type (dx11)
# we can already know what we are looking for: u"kPluginHardwareShader"
node_type = mc.nodeType(materialDepNode.name(), api=True) # ==> "kPluginObjectSet"
# if it's the right type, let;s move on
if node_type == "kPluginHardwareShader":
#plugs = om.MPlugArray()
#otherside = om.MPlugArray()
#the_shading_grp = om.MFnDependencyNode()
# gather the nodes connections
plugs = materialDepNode.getConnections()
the_shading_grp = None
# loop through connections to look for shadingGroup
for j in range(0, len(plugs)):
if plugs[j].isConnected:
otherside = plugs[j].connectedTo(False, True)
for i in range(0, len(otherside)):
if otherside[i].node().hasFn(om.MFn.kShadingEngine):
the_shading_grp = om.MFnDependencyNode(otherside[i].node())
# if we want this guys name, it's: theShadingGroup.name()
return the_shading_grp
else:
return None
# -------------------------------------------------------------------------
# --Second Function--------------------------------------------------------
def on_shader_rename_rename_shading_group(*args):
"""
When NameChangedCallback fires,
If the node being renamed is a dx11Shader (kPluginHardwareShader),
Find the shagingGroup and rename it to match
"""
# get node
try:
mNode = args[0] # matched maya camelCase
except Exception as e:
mNode = None
# convert the MObject to a dep mNode
if mNode:
depNode = om.MFnDependencyNode(mNode)
else:
depNode = None
# get node name
if depNode:
nodeName = depNode.name()
else:
nodeName = None
# this seems to return nothing in this situation
# https://tinyurl.com/y2uf66sh
# I would expect this to return: "shader/surface"
if nodeName:
classifications = mc.getClassification(nodeName)
# To Do: figure this out ^
# before moving on, let's see if we can figure out if this is a material
# since we KNOW currently we are working with a specific type (dx11)
# we can already know what we are looking for: u"kPluginHardwareShader"
if nodeName:
try:
nodeType = mc.nodeType(nodeName, api=True) # ==> "kPluginObjectSet"
except:
nodeType = None
# storage container
sG = None
# if it's the right type, let;s move on
if nodeType == "kPluginHardwareShader":
# get old name
try:
oldName = args[1]
except Exception as e:
oldName = None
_LOGGER.warning('no oldName: {0}'.format(e))
if oldName == (u""):
oldName = 'null'
# get the shadingGroup
sG = find_shading_group(depNode)
# now rename that node, to match <nodeName>SG
if sG:
try:
sG.setName('{0}SG'.format(nodeName))
except Exception as e:
sG = None
_LOGGER.warning('could not renameNode: {0}'.format(e))
else:
return None
# -------------------------------------------------------------------------
#==========================================================================
# Module Tests
#==========================================================================
if __name__ == '__main__':
name_change_cb = om.MNodeMessage.addNameChangedCallback
from .node_message_callback_handler import NodeMessageCallbackHandler
ncbh = NodeMessageCallbackHandler(name_change_cb,
on_shader_rename_rename_shading_group)
@@ -0,0 +1,39 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.maya.helpers.__init__"""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya.callbacks'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
__all__ = ['undo_context', 'utils']
del _LOGGER
# --------------------------------------------------------------------------
@@ -0,0 +1,119 @@
# 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 -------------------------------------------
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# <DCCsi>\\azpy\\maya\\\callbacks\\node_message_callback_handler.py
# Maya node message callback handler
# Reference: Rob Galanakis, Tech-artists.org
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
"""
This module creates a simple Class object for managing Maya Undo Chunking.
"""
# -------------------------------------------------------------------------
# -- Standard Python modules
import os
from functools import wraps
# -- External Python modules
# -- Lumberyard Extension Modules
from azpy import initialize_logger
from azpy.env_bool import env_bool
from azpy.constants import ENVAR_DCCSI_GDEBUG
from azpy.constants import ENVAR_DCCSI_DEV_MODE
# -- Maya Modules --
import maya.cmds as mc
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# -- Misc Global Space Definitions
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya.helpers.undo_context'
_LOGGER = initialize_logger(_PACKAGENAME, default_log_level=int(20))
_LOGGER.debug('Invoking:: {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
# =========================================================================
# First Class
# =========================================================================
class UndoContext(object):
"""
This Class creates a undo context chunk
"""
def __enter__(self):
mc.undoInfo(openChunk=True)
def __exit__(self, *exc_info):
mc.undoInfo(closeChunk=True)
# -------------------------------------------------------------------------
# =========================================================================
# Undo Decorator ... makes a whole function call undoable
# =========================================================================
def undo(func, autoUndo=False):
"""
Puts the wrapped `func` into a single Maya Undo action,
then undoes it when the function enters the finally: block
"""
@wraps(func)
def _undofunc(*args, **kwargs):
try:
# start an undo chunk
mc.undoInfo( openChunk = True )
return func( *args, **kwargs )
finally:
# after calling the func, end the undo chunk and undo
mc.undoInfo( closeChunk = True )
if autoUndo:
mc.undo()
return _undofunc
# -------------------------------------------------------------------------
# =========================================================================
# Public Functions
# =========================================================================
# --First Function---------------------------------------------------------
def test():
"""test() example undo context """
## This is how you call to the UndoContext()
with UndoContext():
# Do a couple things, in a block
# undo should step backwards clearing all of them at once
mc.polySphere(sx=10, sy=15, r=20)
mc.move( 1, 1, 1 )
mc.move( 5, y=True )
# -------------------------------------------------------------------------
#==========================================================================
# Module Tests
#==========================================================================
if __name__ == "__main__" :
test()
@@ -0,0 +1,394 @@
# 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.maya utility module
"""
# -------------------------------------------------------------------------
# built in's
# none
# 3rd Party
# none
# Lumberyard extensions
from azpy import initialize_logger
from azpy.env_bool import env_bool
from azpy.constants import ENVAR_DCCSI_GDEBUG
from azpy.constants import ENVAR_DCCSI_DEV_MODE
# maya imports
import maya.cmds as cmds
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# -- Misc Global Space Definitions
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya.helpers.undo_context'
_LOGGER = initialize_logger(_PACKAGENAME, default_log_level=int(20))
_LOGGER.debug('Invoking:: {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# Initiate the Wing IDE debug connection.
if _G_DEBUG:
#import azpy.dev.connectDebugger as lyDevConnnect
# lyDevConnnect()
pass
# -------------------------------------------------------------------------
# =========================================================================
# First Class
# =========================================================================
class Selection(object):
'''
Custom Class to handle selection data as well as helper commands
to use/parse the selection data
'''
component_prefixes = {0: 'vtx', 1: 'e', 2: 'f', 3: 'map', 4: 'vtxFace'}
#----------------------------------------------------------------------
def __init__(self):
self.selection = dict()
self._populate_selection_data()
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def _populate_cpv_data(self):
'''
Color per-vertex data
Populates a dictionary:
color/alpha key -> vtxFace list
'''
for obj in self.selection.keys():
rgba_dict = dict()
if not cmds.listRelatives( obj, shapes = True ) :
self.selection[obj].append( rgba_dict )
continue
selection_list = []
selection_list = self.get_vtx_face_list( obj )
if len(selection_list) == 0:
# build attribute fetch
attrTag = '{0}.{1}'.format( obj, "vtxFace[*][*]")
# objects vtxFaceList
obj_vtx_faces = cmds.polyListComponentConversion(attrTag,
toVertexFace=True)
selection_list = cmds.ls( obj_vtx_faces,
long = True,
flatten = True )
for vtx_face in selection_list:
# get color RGB values
try:
# query the color
color_list = cmds.polyColorPerVertex( vtx_face,
query = True,
colorRGB = True)
except:
# if no color, assign balck
cmds.polyColorPerVertex( obj,
colorRGB = [0,0,0],
alpha = True)
color_list = cmds.polyColorPerVertex(vtx_face,
query=True,
colorRGB=True)
# and get alpha values
alpha = cmds.polyColorPerVertex(vtx_face,
query = True,
alpha = True)
# tuple up color and alpha
rgba = ( color_list[0], color_list[1], color_list[2], alpha[0] )
if rgba not in rgba_dict :
rgba_dict[rgba] = []
rgba_dict[rgba].append( vtx_face )
self.selection[obj].append( rgba_dict )
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def _make_component_dict(self, component_list):
'''Populates a dictionary of selected components of the given type'''
component = dict()
if not component_list:
return component
for comp in component_list :
# parent of this dag node
par = cmds.listRelatives( comp, parent = True, fullPath = True)[0]
# get transform
transform = cmds.listRelatives( par, parent = True, fullPath = True)[0]
# To Do: explain what this does
comp_num = comp.split('[')[-1].split(']')[0]
if transform not in component:
component[transform] = []
component[transform].append(comp)
return component
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def _fill_with_component_dict(self, component_type):
'''
Wrapper class for making a component dictionary
Takes in a component type:
http://download.autodesk.com/us/maya/2011help/CommandsPython/filterExpand.html
'''
sel_objs = []
component_dict = dict()
components_from_type = cmds.filterExpand(expand=True,
fullPath=True,
selectionMask=component_type)
# pack component dict
component_dict = self._make_component_dict( components_from_type )
try:
sel_objs += self.selection.keys()
except:
pass
try:
sel_objs += component_dict.keys()
except:
pass
sel_objs = set(sel_objs)
for obj in sel_objs:
if obj not in self.selection.keys() :
self.selection[obj] = []
if obj in component_dict:
self.selection[obj].append( component_dict[obj] )
else:
self.selection[obj].append( None )
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def _populate_selection_data(self):
'''Main population method for filling the class with all the selection data'''
#Vertices - Edges - Faces - UVs - VtxFace - Color To VtxFace
#Final Selection Dictionary Map
sel_objs = []
try:
sel_objs += cmds.ls( selection = True, transforms = True, long = True )
except:
pass
try:
sel_objs += cmds.ls( hilite = True, long = True )
except:
pass
sel_objs = set( sel_objs )
for obj in sel_objs :
self.selection[obj] = []
self._fill_with_component_dict(31) # Polygon Vertices
self._fill_with_component_dict(32) # Polygon Edges
self._fill_with_component_dict(34) # Polygon Face
self._fill_with_component_dict(35) # Polygon UVs
self._fill_with_component_dict(70) # Polygon Vertex Face
self._populate_cpv_data()
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def store_selection(self):
'''Takes current selection and populates the class with the selection data'''
self.selection = dict()
self._populate_selection_data()
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def prettyprint(self):
'''Pretty Print method to inspect the selection data'''
crossbar_str = '{0}'.format('*' * 75)
print ( crossbar_str )
print ( '~ Begin Selection Data Output...' )
for key, value in self.selection.items() :
print key
#This is less explict but allows for expansion easier, lets test it out for a while
for itemSet in value:
print ' ', itemSet
#print ' vtx - ', value[0]
#print ' edg - ', value[1]
#print ' face - ', value[2]
#print ' UV - ', value[3]
#print ' vtx-face - ', value[4]
#print ' colorDict - ', value[5]
print ( crossbar_str )
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def select(self, obj, component_type, clear_selection=True, add_value=False):
'''Allow easy reselection of specific selection data'''
cmds.select( clear = clear_selection )
if self.selection[obj][component_type] != None :
cmds.hilite( obj )
cmds.select(self.selection[obj][component_type], add=add_value)
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def restore_selection(self):
'''Restores the selection back to how it was when the class populated its selection data'''
cmds.select( clear = True)
for obj in self.selection.keys() :
cmds.select( obj, add = True )
self.select( obj, 0, 0, add_value = True )
self.select( obj, 1, 0, add_value = True )
self.select( obj, 2, 0, add_value = True )
self.select( obj, 3, 0, add_value = True )
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def get_vtx_face_list(self, obj):
'''Turns all current selection data into a vtxFace selection list'''
selection_list = set()
# To Do: explain what this does
for index in xrange(0, 2) :
sel_part = self.selection[obj][index]
try:
sel = cmds.polyListComponentConversion( sel_part, toVertexFace = True)
selection_list.update( cmds.ls( sel, long = True, flatten = True) )
except:
pass
# To Do: explain what this does
try:
selection_list.update( self.selection[obj][4] )
except:
pass
return list(selection_list)
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def get_first_mesh(self):
'''Returns the first mesh it finds in the selection list'''
for item in self.selection.keys() :
if cmds.listRelatives( item, shanpes = True ) :
return item
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def get_component_list(self, obj, component_index=0):
if self.selection[obj][component_index] == None : # Return all
component_tag = '{0}.{1}[*]'.format(obj, self.component_prefixes[component_index])
return cmds.ls( component_tag, long = True, flatten = True )
else:
return self.selection[obj][component_index]
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def get_component_index(self, obj, component_index=0):
index_list = []
if self.selection[obj][component_index] :
for comp in self.selection[obj][component_index] :
component_number = comp.split('[')[-1].split(']')[0]
index_list.append(component_number)
return index_list
#----------------------------------------------------------------------
#----------------------------------------------------------------------
def get_inverse_component_index(self, obj, component_index=0):
''''''
index_list = []
full_component_list = []
if self.selection[obj][component_index] :
working = self.selection[obj][component_index]
sel_component_list = cmds.ls(working, long=True, flatten=True)
component_tag = '{0}.{1}[*]'.format(obj, self.component_prefixes[component_index])
full_component_list = cmds.ls( component_tag, long = True, flatten = True)
for comp in [comp for comp in full_component_list if comp not in sel_component_list ] :
component_number = comp.split('[')[-1].split(']')[0]
index_list.append(component_number)
return index_list
#----------------------------------------------------------------------
# -------------------------------------------------------------------------
#==========================================================================
# Class Test
#==========================================================================
if __name__ == '__main__':
# get a selection object
sel = Selection()
# to do: this needs some tests?
@@ -0,0 +1,40 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.maya.toolbits.__init__"""
mport os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya.toolbits'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
__all__ = ['detach']
del _LOGGER
#--------------------------------------------------------------------------
@@ -0,0 +1,124 @@
# 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 -------------------------------------------
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# <DCCsi>\\azpy\\maya\\\toolbits\\detach.py
# Maya event callback handler
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
'''
Module Documentation:
DccScriptingInterface\\azpy\\maya\\\toolbits\\detach.py
Implements a clean detach in maya
'''
# -------------------------------------------------------------------------
# built in's
# none
# 3rd Party
# none
# Lumberyard extensions
import azpy
import azpy.helpers.decorators.wrapper
#from azpy.helpers.decorators.wrapper import wrapper
# Maya Imports
import maya.mc as mc
# -------------------------------------------------------------------------
# global space debug flag
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.maya.toolbits.detatch'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
#@wrapper
def clean_detach(detachType=0, args=None, name=None,
deletHistoyIn=False, deleteHistoryOut=True):
'''
Helper Function to aid in detaching faces from any obj
or duplicating those faces without harming the orignal
'''
sel = azpy.maya.helpers.utils.Selection()
for obj in sel.selection.keys():
print("~ cleanDetach:: Working on: {0}".format(obj))
# set up / open the maya undo context
with azpy.maya.helpers.UndoContext():
if deletHistoyIn:
mc.delete( obj, constructionHistory = True)
obShortName = mc.ls( obj, shortNames = True)[0]
fubName = '{0}_detWrk0'.format(obShortName)
#newObj = mc.duplicate( obj, renameChildren = True, name = fubName)[0]
newObj = mc.duplicate( obj, name = fubName)[0]
mc.makeIdentity( newObj, apply = True, translate = True,
rotate = True, scale = True)
mc.delete( newObj, constructionHistory = True)
newObj = mc.parent(newObj, obj)
newObj = mc.ls( newObj, long = True)[0]
if sel.selection[obj][2] == None:
continue
# Continue detachin
faceList = []
for faceNum in sel.get_inverse_component_index(obj,2):
faceList.append( '{0}.f[{1}]'.format( newObj, str(faceNum) ) )
mc.delete(faceList)
if detachType == 0 :
mc.delete( sel.selection[obj][2] )
if name:
newObj = mc.rename( newObj, name )
#mc.delete(obj, constructionHistory = True)
if deleteHistoryOut:
mc.delete(newObj, constructionHistory = True)
mc.select( clear = True )
mc.select( newObj, toggle = True )
obj = mc.ls( obj, long = True)[0]
newObj = mc.ls( newObj, long = True)[0]
return obj, newObj
# -------------------------------------------------------------------------
@@ -0,0 +1,72 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.render.__init__
This package generically uses 'render' to refer to Atom (which is a code name.)
All Atom render related packages/modules should live here."""
import os
import azpy
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.render'
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
__all__ = []
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def init():
"""If the atom render api is required for a package/module to import,
then it should be initialized and added here so general imports
don't fail"""
# __all__.append()
# Make sure we can import the native apis
# import <some atom api>
# Importing local packages/modules
pass
# -------------------------------------------------------------------------
del _LOGGER
@@ -0,0 +1,88 @@
# 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 -------------------------------------------
# --------------------------------------------------------------------------
import os
import sys
import logging as _logging
# --------------------------------------------------------------------------
# -------------------------------------------------------------------------
# global space debug flag
# not using azpy.constants here to help avoid cyclical imports lower
from azpy.env_bool import env_bool
# have to avoid importing these from constants
# because we can end up with cyclical import issues
# need to figure out a better solution later so we don't duplicate everywhere
ENVAR_DCCSI_GDEBUG = str('DCCSI_GDEBUG')
ENVAR_DCCSI_DEV_MODE = str('DCCSI_DEV_MODE')
# global space
_G_DEBUG = os.getenv(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = os.getenv(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.return_stub'
_LOGGER = _logging.getLogger(_PACKAGENAME)
_LOGGER.debug('Initializing: {0}.'.format({_PACKAGENAME}))
__all__ = ['return_stub']
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def return_stub(stub):
_dir_to_last_file = None
'''Take a file name (stub) and returns the directory of the file (stub)'''
if _dir_to_last_file is None:
path = os.path.abspath(__file__)
while 1:
path, tail = os.path.split(path)
if (os.path.isfile(os.path.join(path, stub))):
break
if (len(tail) == 0):
path = ""
if _G_DEBUG:
print('~ Debug Message: I was not able to find the '
'path to that file (stub) in a walk-up from currnet path')
break
_dir_to_last_file = path
return _dir_to_last_file
# --------------------------------------------------------------------------
###########################################################################
# 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.
# happy print
print("# {0} #".format('-' * 72))
print('~ find_stub.py ... Running script as __main__')
print("# {0} #\r".format('-' * 72))
print('~ Current Work dir: {0}'.format(os.getcwd()))
print('~ Dev\: {0}'.format(return_stub('engineroot.txt')))
# custom prompt
sys.ps1 = "[azpy]>>"
@@ -0,0 +1,53 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.shared.__init__"""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.shared'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
__all__ = ['common', 'ui']
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
del _LOGGER
@@ -0,0 +1,53 @@
# 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 -------------------------------------------
# The __init__.py files help guide import statements without automatically
# importing all of the modules
"""azpy.shared.common.__init__"""
import os
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.shared.common'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
#
__all__ = ['core_utils', 'envar_utils']
#
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
from azpy import test_imports
_LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME))
test_imports(__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER)
# -------------------------------------------------------------------------
del _LOGGER
@@ -0,0 +1,518 @@
# 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 -------------------------------------------
from __future__ import unicode_literals
# from builtins import str
# A patch to make this module work in Python3 (hopefully still works in Py27)
try:
unicode = unicode
except NameError:
# 'unicode' is undefined, must be Python3
str = str
unicode = str
bytes = bytes
basestring = (str, bytes)
else:
# 'unicode' exists, must be Python2
str = str
unicode = unicode
bytes = str
basestring = basestring
# -------------------------------------------------------------------------
'''
Module Documentation:
DccScriptingInterface\\azpy\\shared\\common\\core_utils.py
A set of utility functions
<to do: further document this module>
To Do:
https://jira.agscollab.com/browse/ATOM-5859
'''
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# built in's
import os
import sys
import site
import fnmatch
# 3rd Party
from unipath import Path
from progress.spinner import Spinner
# Lumberyard extensions
from azpy.constants import *
from azpy import initialize_logger
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# global space debug flag
from azpy 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 = __name__
if _PACKAGENAME is '__main__':
_PACKAGENAME = 'azpy.shared.common.core_utils'
import azpy
_LOGGER = azpy.initialize_logger(_PACKAGENAME)
_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
# --------------------------------------------------------------------------
def gather_paths_of_type_from_dir(in_path=str('c:\\'),
extension=str('*.py'),
return_path_list=list(),
use_spinner=False):
'''Walks from in_path and returns list of directories that contain the
file type matching the extension'''
if use_spinner:
spinner = Spinner('Finding: {0}\r'.format(extension))
# recursive function for finding paths
dir_contents = os.listdir(in_path)
complete = False
while complete != True:
found = None
for item in dir_contents:
# found a dir to search
if os.path.isdir((in_path + "/" + item)):
return_path_list = gather_paths_of_type_from_dir((in_path + "/" + item),
extension,
return_path_list)
# found a path
elif os.path.isfile:
if fnmatch.fnmatch(item, extension):
found = True
if found:
return_path_list.append(dir_trim_following_slash(to_unix_path(os.path.abspath(in_path))))
if use_spinner:
spinner.next()
complete = True
return return_path_list
# --------------------------------------------------------------------------
# ------------------------------------------------------------------------
def dir_trim_following_slash(current_path_str):
'''removes the trailing slash from a path str'''
safe_path = current_path_str
if current_path_str.endswith('/'):
safe_path = current_path_str[0:-1]
if current_path_str.endswith('\\'):
safe_path = current_path_str[0:-1]
return safe_path
# --------------------------------------------------------------------------
# ------------------------------------------------------------------------
def to_unix_path(current_path_str):
'''converts path string to use unix slashes'''
_LOGGER.debug('to_unix_path({0})'.format(current_path_str))
safe_path = current_path_str.replace('\\', '/')
return safe_path
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
def we_are_frozen():
# All of the modules are built-in to the interpreter, e.g., by py2exe
return hasattr(sys, "frozen")
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
def module_path():
encoding = sys.getfilesystemencoding()
if we_are_frozen():
return os.path.dirname(unicode(sys.executable, encoding))
return os.path.dirname(__file__)
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
def get_stub_check_path(in_path, checkStub='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
'''
from unipath import Path
path = Path(in_path).absolute()
while 1:
testPath = Path(path, checkStub)
if testPath.isfile():
return Path(testPath)
else:
path, tail = (path.parent, path.name)
if (len(tail) == 0):
return None
# --------------------------------------------------------------------------
# -------------------------------------------------------------------------
def reorder_sys_paths(known_sys_paths):
"""Reorders new directories to the front"""
new_sys_path = []
for item in list(sys.path):
item = Path(item)
if item.lower() not in known_sys_paths:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path
known_sys_paths = site._init_pathinfo()
return known_sys_paths
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def check_path_exists(in_path):
"""Will bark if path does not exist"""
check = os.path.exists(in_path)
if check:
_LOGGER.info('~ Path EXISTS: {0}\r'.format(in_path))
else:
_LOGGER.info('~ Path does not exist: {0}\r'.format(in_path))
return check
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def path_split_all(in_path):
'''Splits the in_path to all of it's parts'''
all_path_parts = []
while 1:
parts = os.path.split(path)
if parts[0] == path: # sentinel for absolute paths
all_path_parts.insert(0, parts[0])
break
elif parts[1] == path: # sentinel for relative paths
all_path_parts.insert(0, parts[1])
break
else:
path = parts[0]
all_path_parts.insert(0, parts[1])
return all_path_parts
# -------------------------------------------------------------------------
# --------------------------------------------------------------------------
def synthetic_property(inst, name, value, read_only=False):
'''
This is a convenience method for OOP
synthesizes the creation of property attr with convenience methods:
x.attrbute # the @property (and setter)
x._attribute # attribute storage (private)
x.getAttribute() # retreive attribute
x.setAttribute() # set attribute (only created if not 'read only')
x.delAttribute() # delete the attribute from object
'''
cls = type(inst)
storage_name = '_{0}'.format(name)
getter_name = 'get{0}{1}'.format(name[0].capitalize(), name[1:])
setter_name = 'set{0}{1}'.format(name[0].capitalize(), name[1:])
deleter_name = 'del{0}{1}'.format(name[0].capitalize(), name[1:])
setattr(inst, storage_name, value)
# We always define the getter
def custom_getter(self):
return getattr(self, storage_name)
# Add the Getter
if not hasattr(inst, getter_name):
setattr(cls, getter_name, custom_getter)
# Handle Read Only
if read_only:
if not hasattr(inst, name):
setattr(cls, name, property(fget=getattr(cls, getter_name, None)
or custom_getter,
fdel=getattr(cls, getter_name, None)))
else:
# We only define the setter if we aren't read only
def custom_setter(self, state):
setattr(self, storage_name, state)
if not hasattr(inst, setter_name):
setattr(cls, setter_name, custom_setter)
member = None
if hasattr(cls, name):
# we need to try to update the property fget, fset,
# fdel incase the class has defined its own custom functions
member = getattr(cls, name)
if not isinstance(member, property):
raise ValueError('Member "{0}" for class "{1}" exists and is not a property.'
''.format(name, cls.__name__))
# Regardless if the class has the property or not we still try to set it with
setattr(cls, name, property(fget=getattr(member, 'fget', None)
or getattr(cls, getter_name, None)
or custom_getter,
fset=getattr(member, 'fset', None)
or getattr(cls, setter_name, None)
or custom_setter,
fdel=getattr(member, 'fdel', None)
or getattr(cls, getter_name, None)))
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
def find_arg(arg_pos_index=None, arg_tag=None, remove_kwarg=None,
in_args=None, in_kwargs=None, default_value=None):
"""
# finds and returns an arg...
# if a positional index is given arg_pos_index=0, it checks args first
# if a arg_tag is given, it checks kwargs
# If remove_kwarg=True, it will remove the found arg from kwargs
# * I actually want/need to do this often
#
# a set kwarg will ALWAYS take precident over positional arg!!!
#
# return outArg, args, kwargs <-- get back modified kwargs!
#
# proper usage:
#
# found_arg, args, kwargs = find_arg(0, 'name',)
"""
if arg_pos_index != None:
if not isinstance(arg_pos_index, int):
raise TypeError('remove_kwarg: accepts a index integer!\r'
'got: {0}'.format(remove_kwarg))
# positional args ... check the position
if len(in_args) > 0:
try:
found_arg = in_args[arg_pos_index]
except:
pass
# check kwargs ... a set kwarg will ALWAYS take precident over
# positional arg!!!
try:
found_arg
except:
found_arg = in_kwargs.get(arg_tag, default_value) # defaults to None
if remove_kwarg:
if arg_tag in in_kwargs:
del in_kwargs[arg_tag]
# if we didn't find the arg/kwarg, the defualt return will be None
return found_arg, in_kwargs
# -------------------------------------------------------------------------
# --------------------------------------------------------------------------
def set_synth_arg_kwarg(inst, arg_pos_index, arg_tag, in_args, in_kwargs,
remove_kwarg=True, default_value=None, set_anyway=True):
"""
Uses find_arg and sets a property on a object.
Special args:
set_anyway <-- if the object has the property already, set it
"""
# find the argument, or set to default value
found_arg, in_kwargs = find_arg(arg_pos_index, arg_tag, remove_kwarg,
in_args, in_kwargs,
default_value)
# make sure the object doesn't arealdy have this property
try:
hasattr(inst, arg_tag) # <-- check if property exists
if set_anyway:
try:
setattr(inst, arg_tag, found_arg) # <-- try to set
except Exception as e:
raise e
except:
try:
found_arg = synthetic_property(inst, arg_tag, found_arg)
except Exception as e:
raise e
return found_arg, in_kwargs
# --------------------------------------------------------------------------
# -------------------------------------------------------------------------
def walk_up_dir(in_path, dir_tag='foo'):
'''
Mimic something like os.walk, but walks up the directory tree
Walks Up from the in_path looking for a dir with the name dir_tag
in_path: the path to start in
dir_tag: the name of diretory above us we are looking for
returns None if the directory named dir_tag is not found
'''
from unipath import Path
path = Path(Path(__file__).absolute())
while 1:
# hmmm, will this break on unix paths?
# what about case sensitivity?
dir_base_name = Path(path.norm_case()).name()
if (dir_base_name == dir_tag):
break
path, tail = (path.parent(), path.name())
if (len(tail) == 0):
return None
return path
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
def return_stub(stub):
'''Take a file name (stub) and returns the directory of the file (stub)'''
from unipath import Path
dir_last_file = None
if dir_last_file is None:
path = Path(__file__).absolute()
while 1:
path, tail = (path.parent, path.name)
newpath = Path(path, stub)
if newpath.isfile():
break
if (len(tail) == 0):
path = ""
_LOGGER.debug('~ Debug Message: I was not able to find the '
'path to that file (stub) in a walk-up from currnet path')
break
dir_last_file = path
return dir_last_file
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
# direct call for testing methods functions
if __name__ == "__main__":
'''To Do: Document'''
# constants for shared use.
_G_DEBUG = True
# happy _LOGGER.info
_LOGGER.info("# {0} #".format('-' * 72))
_LOGGER.info('~ constants.py ... Running script as __main__')
_LOGGER.info("# {0} #\r".format('-' * 72))
cwd = Path(os.getcwd())
# This grabs pythons known paths
_KNOWN_SITEDIR_PATHS = list(sys.path) # this appears to give me a somehow malformed syspath?
_KNOWN_SITEDIR_PATHS = site._init_pathinfo()
# this is just a debug developer convenience _LOGGER.info (for testing acess)
if _G_DEBUG:
import pkgutil
_LOGGER.info('Current working dir: {0}'.format(cwd))
search_path = ['.'] # set to None to see all modules importable from sys.path
all_modules = [x[1] for x in pkgutil.iter_modules(path=search_path)]
_LOGGER.info('All Available Modules in working dir: {0}\r'.format(all_modules))
# test toUnixPath
# assumes the current working directory (cwd) is <ly>\\dev\\Gems\\DccScriptingInterface
test_path = Path(cwd, 'LyPy', 'si_shared', 'common', 'core_utils.py')
safeTest = to_unix_path(test_path)
_LOGGER.info("Unix format: '{0}'".format(safeTest))
_LOGGER.info('')
# test dirTrimFollowingSlash
short_path = Path(cwd)
_LOGGER.info("Original: '{0}'".format(short_path))
short_path = to_unix_path(short_path)
_LOGGER.info("Unix: '{0}'".format(short_path))
trimTest = dir_trim_following_slash(short_path)
_LOGGER.info("Trimmed: '{0}'".format(trimTest))
_LOGGER.info('')
# test gather_paths_of_type_from_dir
extTest = '*.py'
fileList = gather_paths_of_type_from_dir(os.getcwd(), extTest, use_spinner=True)
_LOGGER.info('Found {0}: {1}'.format(extTest, len(fileList)))
_LOGGER.info('')
# test weAreFrozen
# none
# test modulePath
modulePathTest = module_path()
_LOGGER.info("This Module: '{0}'".format(modulePathTest))
modulePathTest = to_unix_path(modulePathTest)
_LOGGER.info("This module unix: '{0}'".format(modulePathTest))
_LOGGER.info('')
# test checkstub_getpath
stubTest = get_stub_check_path(__file__)
_LOGGER.info("Stub Path: '{0}'".format(stubTest))
# reorderSysPaths test
pkgTestPath = Path(cwd, 'LyPy', 'si_shared', 'packagetest')
site.addsitedir(pkgTestPath)
anotherTestPath = Path(cwd, 'LyPy', 'si_shared', 'dev')
site.addsitedir(anotherTestPath)
# pass in the previous list we retreived earlier
_KNOWN_SITEDIR_PATHS = reorder_sys_paths(_KNOWN_SITEDIR_PATHS) # I think this is broken,
# I get back this as one of the paths:
# G:\depot\gallowj_PC1_lrgWrlds\dev\Gems\DccScriptingInterface\Shared\Python\LyPyCommon\PYTHONPATH
_LOGGER.info('done')
pass
# checkPathExists test
# pathSplitAll test
# walkUp test
# test synthesize
# to do: write test
# test findArg
# to do: write test
# test setSynthArgKwarg
# to do: write test

Some files were not shown because too many files have changed in this diff Show More