text: # coding:utf-8
  import re
  
  import copy
  # noinspection PyUnresolvedReferences
  from maya import cmds, OpenMaya, OpenMayaUI
  
  from LxBasic import bscMethods
  
  from LxGraphic import grhCfg
  
  from . import maBscCfg
  
  
  class Mtd_MaBasic(maBscCfg.MaUtility):
      MOD_maya_cmds = cmds
      MOD_re = re
      MOD_copy = copy
  
  
  class Mtd_MyaObj(Mtd_MaBasic):
      DEF_mya_porttype_integer_list = [
          'long', 'short', 'byte'
      ]
  
      DEF_mya_porttype_float_list = [
          'float', 'double', 'char'
      ]
  
      # **************************************************************************************************************** #
      @classmethod
      def _dcc_getNodAttrpathString(cls, *args):
          if len(args) > 1:
              return cls.DEF_mya_node_port_pathsep.join(list(args))
          return args[0]
  
      # **************************************************************************************************************** #
      @classmethod
      def _dcc_getNodExist(cls, nodepathString):
          if nodepathString is not None:
              return cls.MOD_maya_cmds.objExists(nodepathString)
          return False
  
      # **************************************************************************************************************** #
      # noinspection PyUnusedLocal
      @classmethod
      def _dcc_getNodNodetypeStr(cls, typepathString):
          return grhCfg.GrhUtility.DEF_grh__keyword__default
  
      @classmethod
      def _dcc_getNodCategoryStr(cls, nodepathString):
          return cls.MOD_maya_cmds.nodeType(nodepathString)
  
      # **************************************************************************************************************** #
      @classmethod
      def _obj_loader_cls__get_port_format_(cls, portpathString):
          _ = portpathString.split(cls.DEF_mya_node_port_pathsep)[-1]
          if _.endswith(u']'):
              return _.split(u'[')[0]
          return _
  
      @classmethod
      def _dcc_getNodPortnames(cls, typepathString):
          return cls.MOD_maya_cmds.attributeInfo(
              allAttributes=True,
              type=typepathString
          ) or []
  
      @classmethod
      def _dcc_getNodPortIsExist(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              exists=1
          )
  
      @classmethod
      def _dcc_getNodPortIsReadable(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              readable=1
          )
  
      @classmethod
      def _dcc_getNodPortIsWritable(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              writable=1
          )
  
      @classmethod
      def _dcc_getNodPortIsConnectable(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              connectable=1
          )
  
      @classmethod
      def _dcc_getNodPortIsMessage(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              message=1
          )
  
      @classmethod
      def _dcc_getNodPortIsColor(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              usedAsColor=1
          )
  
      @classmethod
      def _dcc_getNodPortIsFilename(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              usedAsFilename=1
          )
  
      @classmethod
      def _obj_loader_cls__get_port_is_multiple_(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              multi=1
          )
  
      @classmethod
      def _dcc_getNodPortIsEnumerate(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              enum=1
          )
  
      @classmethod
      def _dcc_getNodPorttype(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              attributeType=1
          )
  
      @classmethod
      def _dcc_getNodPortHasChildren(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              numberOfChildren=1
          ) is not None
  
      @classmethod
      def _dcc_getNodPortChildren(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              listChildren=1
          ) or []
  
      @classmethod
      def _dcc_getNodPortHasParent(cls, typepathString, portpathString):
          return cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              listParent=1
          ) is not None
  
      @classmethod
      def _dcc_getNodPortParent(cls, typepathString, portpathString):
          _ = cls.MOD_maya_cmds.attributeQuery(
              cls._obj_loader_cls__get_port_format_(portpathString),
              type=typepathString,
              listParent=1
          )
          if _:
              return _[0]
  
      # **************************************************************************************************************** #
      @classmethod
      def _dcc_getAttrpathNodepath(cls, attrpathString):
          return bscMethods.MaAttrpath.nodepathString(attrpathString)
  
      @classmethod
      def _dcc_getAttrpathPortpath(cls, attrpathString):
          return bscMethods.MaAttrpath.portpathString(attrpathString)
  
      @classmethod
      def _dcc_getNodPortIsAppExist(cls, *args):
          return cls.MOD_maya_cmds.objExists(
              cls._dcc_getNodAttrpathString(*args)
          )
  
      @classmethod
      def _dcc_getNodPortIndexes(cls, *args):
          return cls.MOD_maya_cmds.getAttr(
              cls._dcc_getNodAttrpathString(*args),
              multiIndices=1,
              silent=1
          ) or []
  
      @classmethod
      def _dcc_toAttributeString(cls, nodepathString, portpathString):
          return cls.DEF_mya_node_port_pathsep.join(
              [nodepathString, portpathString]
          )
  
      @classmethod
      def _dcc_getNodPortSourceExist(cls, *args):
          if cls._dcc_getNodPortIsAppExist(*args):
              return cls.MOD_maya_cmds.connectionInfo(
                  cls._dcc_getNodAttrpathString(*args),
                  isExactDestination=1
              )
          return False
  
      @classmethod
      def _dcc_getNodPortIsSource(cls, *args):
          if cls._dcc_getNodPortIsAppExist(*args):
              return cls.MOD_maya_cmds.connectionInfo(
                  cls._dcc_getNodAttrpathString(*args),
                  isExactSource=1
              )
          return False
  
      @classmethod
      def _dcc_getNodPortSourceStr(cls, *args):
          if cls._dcc_getNodPortIsAppExist(*args):
              return cls.MOD_maya_cmds.connectionInfo(
                  cls._dcc_getNodAttrpathString(*args),
                  sourceFromDestination=1
              )
  
      @classmethod
      def _dcc_getNodPortHasTargets(cls, *args):
          if cls._dcc_getNodPortIsAppExist(*args):
              return cls.MOD_maya_cmds.connectionInfo(
                  cls._dcc_getNodAttrpathString(*args),
                  isExactSource=1
              )
          return False
  
      @classmethod
      def _dcc_getNodPortIsTarget(cls, *args):
          if cls._dcc_getNodPortIsAppExist(*args):
              return cls.MOD_maya_cmds.connectionInfo(
                  cls._dcc_getNodAttrpathString(*args),
                  isExactDestination=1
              )
          return False
  
      @classmethod
      def _dcc_getNodPortTargets(cls, *args):
          if cls._dcc_getNodPortIsAppExist(*args):
              return cls.MOD_maya_cmds.connectionInfo(
                  cls._dcc_getNodAttrpathString(*args),
                  destinationFromSource=1
              ) or []
          return []
  
      @classmethod
      def _dcc_getNodPortDatatype(cls, nodepathString, portpathString):
          return cls.MOD_maya_cmds.getAttr(
              cls._dcc_toAttributeString(nodepathString, portpathString),
              type=1,
              silent=1
          )
  
      @classmethod
      def _dcc_getNodPortraw(cls, nodepathString, portpathString, asString):
          return cls.MOD_maya_cmds.getAttr(
              cls._dcc_toAttributeString(nodepathString, portpathString),
              asString=asString,
              silent=1
          )
  
      # **************************************************************************************************************** #
      @classmethod
      def _dcc_getNodFullpathNodepathStr(cls, nodepathString):
          if not nodepathString.startswith(cls.DEF_mya_node_pathsep):
              return cls.MOD_maya_cmds.ls(nodepathString, long=1)[0]
          else:
              return nodepathString
  
      @classmethod
      def _dcc_getNodTransformNodepathStr(cls, nodepathString, fullpath=True):
          if cls._dcc_getNodExist(nodepathString):
              if cls._dcc_getNodCategoryStr(nodepathString) == cls.DEF_mya_type_transform:
                  if fullpath:
                      return cls._dcc_getNodFullpathNodepathStr(nodepathString)
                  else:
                      return bscMethods.MaNodeString.nodenameWithNamespace(nodepathString)
              else:
                  stringLis = cls.MOD_maya_cmds.listRelatives(nodepathString, parent=1, fullPath=fullpath)
                  if stringLis:
                      return stringLis[0]
  
      @classmethod
      def _dcc_getNodShapeNodepathStr(cls, nodepathString, fullpath=True):
          string = None
          if cls._dcc_getNodCategoryStr(nodepathString) == cls.DEF_mya_type_transform:
              stringLis = cls.MOD_maya_cmds.listRelatives(nodepathString, children=1, shapes=1, noIntermediate=1, fullPath=fullpath)
              if stringLis:
                  string = stringLis[0]
          else:
              if fullpath:
                  string = cls._dcc_getNodFullpathNodepathStr(nodepathString)
              else:
                  string = bscMethods.MaNodeString.nodenameWithNamespace(nodepathString)
          return string
  
      @classmethod
      def _dcc_getNodParentExist(cls, nodepathString, fullpath=True):
          return cls.MOD_maya_cmds.listRelatives(nodepathString, parent=1, fullPath=fullpath) is not None
  
      @classmethod
      def _dcc_getNodParentNodepathStr(cls, nodepathString, fullpath=True):
          _ = cls.MOD_maya_cmds.listRelatives(nodepathString, parent=1, fullPath=fullpath)
          if _:
              return _[0]
  
      @classmethod
      def _dcc_getNodChildrenExist(cls, nodepathString, fullpath=True):
          return cls.MOD_maya_cmds.listRelatives(nodepathString, children=1, type=cls.DEF_mya_type_transform, fullPath=fullpath) is not None
  
      @classmethod
      def _dcc_getNodChildNodepathStrList(cls, nodepathString, fullpath=True):
          return cls.MOD_maya_cmds.listRelatives(nodepathString, children=1, type=cls.DEF_mya_type_transform, fullPath=fullpath) or []
  
      # **************************************************************************************************************** #
      @classmethod
      def _grh_getNodePortkey_(cls, portpathString):
          _ = portpathString.split(cls.DEF_mya_node_port_pathsep)
          string = ''
          for seq, i in enumerate(_):
              if i.endswith(u']'):
                  i = i.split(u'[')[0]
              if seq > 0:
                  string += (cls.DEF_mya_node_port_pathsep + i)
              else:
                  string += i
          return string
  
      @classmethod
      def _grh_getNodePortPathdata_(cls, pathString):
          def addFnc_(item):
              if item:
                  if not item in lis:
                      lis.append(item)
  
          def getBranchFnc_(pathString_):
              if not pathString_ in lis:
                  stringLis = pathString_.split(pathsep)
                  #
                  dataCount = len(stringLis)
                  for seq, data in enumerate(stringLis):
                      if data:
                          if seq < dataCount:
                              subPath = pathsep.join(stringLis[:seq])
                              addFnc_(subPath)
                  #
                  addFnc_(pathString_)
  
          lis = []
          pathsep = cls.DEF_mya_node_port_pathsep
          getBranchFnc_(pathString)
          return lis
  
      @classmethod
      def _grh_getNodePortChildren(cls, typepathString, portpathString):
          lis = []
  
          _children = cls._dcc_getNodPortChildren(typepathString, portpathString)
          if _children:
              for _i in _children:
                  _fullpathPortnameString = cls.DEF_mya_node_port_pathsep.join([portpathString, _i])
                  lis.append(_fullpathPortnameString)
          if cls._dcc_getNodPortIsColor(typepathString, portpathString):
              if portpathString == u'outColor':
                  _alphaPortnameString = u'outAlpha'
              else:
                  _alphaPortnameString = portpathString + u'A'
              if cls._dcc_getNodPortIsExist(typepathString, _alphaPortnameString):
                  lis.append(_alphaPortnameString)
  
          return lis
  
      @classmethod
      def _grh_getNodePortSearchPortkeyStrings(cls, nodepathString, portpathString):
          def recursionFnc_(categoryString_, nodeString_, portString_):
              if cls._dcc_getNodPortHasChildren(categoryString_, portString_):
                  _children = cls._grh_getNodePortChildren(categoryString_, portString_)
                  if _children:
                      for _i in _children:
                          recursionFnc_(categoryString_, nodeString_, _i)
              else:
                  lis.append(portString_)
  
          lis = []
          typepathString = cls.MOD_maya_cmds.nodeType(nodepathString)
  
          recursionFnc_(typepathString, nodepathString, portpathString)
          return lis
  
      @classmethod
      def _grh_getNodePortParent(cls, typepathString, portpathString):
          _ = cls._dcc_getNodPortParent(typepathString, portpathString)
          if _:
              return _
  
          if portpathString == u'outAlpha':
              return u'outColor'
          elif portpathString.endswith(u'A'):
              s = portpathString[:-1]
              if cls._dcc_getNodPortIsExist(typepathString, s):
                  return s
              return _
  
      # **************************************************************************************************************** #
      @classmethod
      def _grh_getNodePortpathStringList(cls, nodepathString):
          def recursionFnc_(categoryString_, portnameString_):
              _children = cls._dcc_getNodPortChildren(categoryString_, portnameString_)
              if _children:
                  for _i in _children:
                      _portnameString = u'{}.{}'.format(portnameString_, _i)
                      lis.append(_portnameString)
                      recursionFnc_(categoryString_, _portnameString)
  
          lis = []
          typepathString = cls.MOD_maya_cmds.nodeType(nodepathString)
  
          portStringList = bscMethods.List.cleanupTo(
              cls.MOD_maya_cmds.listAttr(nodepathString)
          )
          if portStringList:
              for k in portStringList:
                  if cls._dcc_getNodPortHasParent(typepathString, k) is False:
                      lis.append(k)
                      recursionFnc_(typepathString, k)
          return lis
  
      @classmethod
      def _grh_getNodePortpathStringList_(cls, typepathString):
          def recursionFnc_(categoryString_, portnameString_):
              _children = cls._dcc_getNodPortChildren(categoryString_, portnameString_)
              if _children:
                  for _i in _children:
                      _portnameString = u'{}.{}'.format(portnameString_, _i)
                      lis.append(_portnameString)
                      recursionFnc_(categoryString_, _portnameString)
  
          lis = []
  
          portStringList = bscMethods.List.cleanupTo(
              cls.MOD_maya_cmds.attributeInfo(
                  allAttributes=True,
                  type=typepathString
              ) or []
          )
          if portStringList:
              for k in portStringList:
                  if cls._dcc_getNodPortHasParent(typepathString, k) is False:
                      lis.append(k)
                      recursionFnc_(typepathString, k)
          return lis
  
      @classmethod
      def _grh_getNodePortAssign(cls, typepathString, portpathString):
          _assignStr = None
  
          readable = cls._dcc_getNodPortIsReadable(typepathString, portpathString)
          writeable = cls._dcc_getNodPortIsWritable(typepathString, portpathString)
  
          if (readable, writeable) == (True, True):
              return grhCfg.GrhPortAssignQuery.gnport
          if (readable, writeable) == (True, False):
              return grhCfg.GrhPortAssignQuery.otport
          elif (readable, writeable) == (False, True):
              return grhCfg.GrhPortAssignQuery.inport
  
      @classmethod
      def _grh_getNodePorttypeString(cls, typepathString, portkeyString, isArray):
          _portTypeString = cls._dcc_getNodPorttype(typepathString, portkeyString)
          if cls._dcc_getNodPortIsColor(typepathString, portkeyString):
              if portkeyString == u'outColor':
                  _alphaPortnameString = u'outAlpha'
              else:
                  _alphaPortnameString = portkeyString + u'A'
              if cls._dcc_getNodPortIsExist(typepathString, _alphaPortnameString):
                  _ = u'color4'
              else:
                  _ = u'color3'
  
              if isArray is True:
                  return _ + u'array'
              return _
          elif cls._dcc_getNodPortIsFilename(typepathString, portkeyString):
              return u'filename'
          elif cls._dcc_getNodPortIsEnumerate(typepathString, portkeyString):
              _ = u'string'
              if isArray is True:
                  return _ + u'array'
              return _
          elif _portTypeString in cls.DEF_mya_porttype_integer_list:
              _ = u'integer'
              if isArray is True:
                  return _ + u'array'
              return _
          elif _portTypeString in cls.DEF_mya_porttype_float_list:
              _ = u'float'
              if isArray:
                  return _ + u'array'
              return _
          elif _portTypeString == u'bool':
              return u'boolean'
          return _portTypeString
  
      @classmethod
      def _grh_getNodePortDefDict(cls, typepathString, portpathStringList):
          dic = cls.CLS_ordered_dict()
  
          for portpathString in portpathStringList:
              portDict = cls.CLS_ordered_dict()
  
              assignString = cls._grh_getNodePortAssign(typepathString, portpathString)
              if assignString is not None:
                  isArray = cls._grh_getNodePortIsArray(typepathString, portpathString)
  
                  porttypeString = cls._grh_getNodePorttypeString(typepathString, portpathString, isArray)
                  parentPortnameString = cls._grh_getNodePortParent(typepathString, portpathString)
                  childPortnameStrings = cls._grh_getNodePortChildren(typepathString, portpathString)
  
                  portDict[grhCfg.GrhUtility.DEF_grh__key_porttype] = porttypeString
                  portDict[grhCfg.GrhUtility.DEF_grh__key_port_datatype] = porttypeString
                  portDict[grhCfg.GrhUtility.DEF_grh__key_portpath] = portpathString
                  portDict[grhCfg.GrhUtility.DEF_grh__key_assign] = assignString
                  portDict[grhCfg.GrhUtility.DEF_grh__key_parent] = parentPortnameString
                  portDict[grhCfg.GrhUtility.DEF_grh__key_children] = childPortnameStrings
  
                  dic[portpathString] = portDict
  
          return dic
  
      @classmethod
      def _grh_getNodePortRawList(cls, typepathString, portpathStringList):
          lis = []
  
          for portpathString in portpathStringList:
              portDict = {}
  
              assignString = cls._grh_getNodePortAssign(typepathString, portpathString)
              isArray = cls._grh_getNodePortIsArray(typepathString, portpathString)
  
              porttypeString = cls._grh_getNodePorttypeString(typepathString, portpathString, isArray)
              parentPortnameString = cls._grh_getNodePortParent(typepathString, portpathString)
              childPortnameStrings = cls._grh_getNodePortChildren(typepathString, portpathString)
  
              portDict[grhCfg.GrhUtility.DEF_grh__key_porttype] = porttypeString
              portDict[grhCfg.GrhUtility.DEF_grh__key_port_datatype] = porttypeString
              portDict[grhCfg.GrhUtility.DEF_grh__key_portpath] = portpathString
              portDict[grhCfg.GrhUtility.DEF_grh__key_portraw] = None
              portDict[grhCfg.GrhUtility.DEF_grh__key_assign] = assignString
              portDict[grhCfg.GrhUtility.DEF_grh__key_parent] = parentPortnameString
              portDict[grhCfg.GrhUtility.DEF_grh__key_children] = childPortnameStrings
  
              lis.append(portDict)
  
          return lis
  
      @classmethod
      def _grh_getNodNodeRaw(cls, typepathString):
          dic = {
              grhCfg.GrhUtility.DEF_grh__key_node_typepath: typepathString,
              grhCfg.GrhUtility.DEF_grh__key_node_datatype: None,
              grhCfg.GrhUtility.DEF_grh__key_port: cls._grh_getNodePortRawList(
                  typepathString, cls._grh_getNodePortpathStringList_(typepathString)
              )
          }
  
          return dic
  
      @classmethod
      def _grh_getNodePortRaw(cls, typepathString, portpathString):
          assignString = cls._grh_getNodePortAssign(typepathString, portpathString)
          isArray = cls._grh_getNodePortIsArray(typepathString, portpathString)
  
          porttypeString = cls._grh_getNodePorttypeString(typepathString, portpathString, isArray)
          parentPortnameString = cls._grh_getNodePortParent(typepathString, portpathString)
          childPortnameStrings = cls._grh_getNodePortChildren(typepathString, portpathString)
  
          return {
              grhCfg.GrhUtility.DEF_grh__key_porttype: porttypeString,
              grhCfg.GrhUtility.DEF_grh__key_port_datatype: porttypeString,
              grhCfg.GrhUtility.DEF_grh__key_portpath: portpathString, grhCfg.GrhUtility.DEF_grh__key_portraw: None,
              grhCfg.GrhUtility.DEF_grh__key_assign: assignString,
              grhCfg.GrhUtility.DEF_grh__key_parent: parentPortnameString,
              grhCfg.GrhUtility.DEF_grh__key_children: childPortnameStrings
          }
  
      @classmethod
      def _grh_getNodePortIsArray(cls, typepathString, portpathString):
          portPathdata = cls._grh_getNodePortPathdata_(portpathString)
          for seq, portpathString in enumerate(portPathdata):
              _isArray = cls._obj_loader_cls__get_port_is_multiple_(typepathString, portpathString)
              if _isArray:
                  return True
          return False
  
      @classmethod
      def _grh_getNodePortkeyStringDict(cls, typepathString, portStringList):
          def recursionFnc_(categoryString_, portString_):
              _children = cls._dcc_getNodPortChildren(categoryString_, portString_)
              if _children:
                  for _i in _children:
                      _fullpathPortnameString = u'{}.{}'.format(portString_, _i)
                      dic[_i] = _fullpathPortnameString
                      recursionFnc_(categoryString_, _fullpathPortnameString)
  
          dic = cls.CLS_ordered_dict()
  
          if portStringList:
              for i in portStringList:
                  if cls._dcc_getNodPortHasParent(typepathString, i) is False:
                      dic[i] = i
                      recursionFnc_(typepathString, i)
          return dic
      # **************************************************************************************************************** #
      @classmethod
      def _grh_getNodePortdata_(cls, nodepathString, portkeyString, asString):
          exclude_datatype_list = [
              'mesh',
              'attributeAlias',
          ]
          typepathString = cls.MOD_maya_cmds.nodeType(nodepathString)
  
          if cls._dcc_getNodPortIsAppExist(nodepathString, portkeyString) is True:
              if cls._dcc_getNodPortIsMessage(typepathString, portkeyString):
                  if cls._dcc_getNodPortSourceExist(nodepathString, portkeyString):
                      return bscMethods.MaAttrpath.nodepathString(
                          cls._dcc_getNodPortSourceStr(nodepathString, portkeyString)
                      )
                  return ''
              elif cls._dcc_getNodPortIsEnumerate(typepathString, portkeyString):
                  return cls.MOD_maya_cmds.getAttr(
                              cls._dcc_toAttributeString(nodepathString, portkeyString),
                              asString=asString,
                              silent=1
                          )
              else:
                  datatype = cls._dcc_getNodPorttype(typepathString, portkeyString)
                  if not datatype in exclude_datatype_list:
                      return cls.MOD_maya_cmds.getAttr(
                                  cls._dcc_toAttributeString(nodepathString, portkeyString), silent=1
                              )
  
      @classmethod
      def _grh_getNodPortraw(cls, nodepathString, portkeyString, asString=True):
          def getArrayPortdataFnc_(nodepathString_, portStrings_):
              return [
                  cls._grh_getNodePortdata_(
                      nodepathString_,
                      _l,
                      asString=False
                  )
                  for _l in portStrings_
              ]
  
          def getArrayFnc_(nodepathString_, formatStrings_):
              _lis = []
              for _format in formatStrings_:
                  _formatString, _indexArray = _format
                  _portStringList = []
                  for _index in _indexArray:
                      s = _formatString.format(*_index)
                      _portStringList.append(s)
                  _lis.append(_portStringList)
  
              _lis_ = []
              for _j in zip(*_lis):
                  for _k in _j:
                      _lis_.append(
                          _k
                      )
              return getArrayPortdataFnc_(nodepathString_, _lis_)
  
          def getMultiBranchFnc_(nodepathString_, portkeyString_):
              _lis = []
              _isArrayEnable = False
              _portkeyStringList = cls._grh_getNodePortSearchPortkeyStrings(nodepathString_, portkeyString_)
              for _i in _portkeyStringList:
                  _format = cls._grh_getNodePortFormat(nodepathString_, _i)
                  if _format is not None:
                      _isArrayEnable = True
                      _lis.append(_format)
                  else:
                      _lis.append(_i)
  
              if _isArrayEnable is True:
                  return getArrayFnc_(nodepathString_, _lis)
              else:
                  return getArrayPortdataFnc_(nodepathString_, _lis)
  
          typepathString = cls.MOD_maya_cmds.nodeType(nodepathString)
  
          if cls._dcc_getNodPortHasChildren(typepathString, portkeyString) is True:
              return getMultiBranchFnc_(nodepathString, portkeyString)
          else:
              format_ = cls._grh_getNodePortFormat(nodepathString, portkeyString)
              if format_ is not None:
                  formatString, indexArray = format_
                  return getArrayFnc_(nodepathString, [(formatString, indexArray)])
              else:
                  return cls._grh_getNodePortdata_(
                      nodepathString,
                      portkeyString,
                      asString=asString
                  )
  
      @classmethod
      def _grh_getNodePortIndexArray(cls, nodepathString, portkeyString):
          def recursionFnc_(categoryString_, nodepathString_, portString_):
              if cls._dcc_getNodPortIsAppExist(nodepathString_, portString_):
                  key = cls._grh_getNodePortkey_(portString_)
                  _indexes = cls._dcc_getNodPortIndexes(nodepathString_, portString_)
                  _children = cls._dcc_getNodPortChildren(categoryString_, portString_)
  
                  _hasIndex = _indexes != []
                  _hasChild = _children != []
  
                  _check = (_hasIndex, _hasChild)
                  if _indexes:
                      if key in dic:
                          __indexes = dic[key]
                          if __indexes != _indexes:
                              for _i in _indexes:
                                  if not _i in __indexes:
                                      __indexes.append(_i)
                          dic[key] = __indexes
                      else:
                          dic[key] = _indexes
  
                  if _check == (True, True):
                      for index_ in _indexes:
                          for childPortname in _children:
                              _fullpathPortnameString = u'{}[{}].{}'.format(portString_, index_, childPortname)
                              recursionFnc_(categoryString_, nodepathString_, _fullpathPortnameString)
                  elif _check == (True, False):
                      for index_ in _indexes:
                          _fullpathPortnameString = u'{}[{}]'.format(portString_, index_)
                          recursionFnc_(categoryString_, nodepathString_, _fullpathPortnameString)
                  elif _check == (False, True):
                      for childPortname in _children:
                          _fullpathPortnameString = u'{}.{}'.format(portString_, childPortname)
                          recursionFnc_(categoryString_, nodepathString_, _fullpathPortnameString)
  
          dic = {}
          typepathString = cls.MOD_maya_cmds.nodeType(nodepathString)
  
          portPathdata = cls._grh_getNodePortPathdata_(portkeyString)
  
          for i in portPathdata:
              recursionFnc_(typepathString, nodepathString, i)
          return dic
  
      @classmethod
      def _grh_getNodePortFormat(cls, nodepathString, portkeyString):
          indexArrayDict = cls._grh_getNodePortIndexArray(nodepathString, portkeyString)
          portPathdata = cls._grh_getNodePortPathdata_(portkeyString)
          _portString = ''
          _lis = []
          for seq, i in enumerate(portPathdata):
              _portname = i.split(cls.DEF_mya_node_port_pathsep)[-1]
              if i in indexArrayDict:
                  indexes = indexArrayDict[i]
                  _indexString = u'[{{{}}}]'.format(len(_lis))
                  if seq > 0:
                      _portString += (cls.DEF_mya_node_port_pathsep + _portname + _indexString)
                  else:
                      _portString += (_portname + _indexString)
                  _lis.append(indexes)
              else:
                  if seq > 0:
                      _portString += (cls.DEF_mya_node_port_pathsep + _portname)
                  else:
                      _portString += _portname
          if _lis:
              return _portString, bscMethods.NestedArray.mapTo(_lis)
  
  
  class Mtd_MaUtility(Mtd_MaBasic):
      @classmethod
      def _dcc_getNodFullpathNodepathStr(cls, nodepathString):
          if not nodepathString.startswith(cls.DEF_mya_node_pathsep):
              return cls.MOD_maya_cmds.ls(nodepathString, long=1)[0]
          else:
              return nodepathString
  
      @classmethod
      def _toAppExistStringList(cls, nodepathString, fullPath=True):
          lis = []
          if isinstance(nodepathString, (str, unicode)):
              if cls._isAppExist(nodepathString):
                  if fullPath is True:
                      lis = [cls._dcc_getNodFullpathNodepathStr(nodepathString)]
                  else:
                      lis = [bscMethods.MaNodeString.nodenameWithNamespace(nodepathString)]
          elif isinstance(nodepathString, (tuple, list)):
              for i in nodepathString:
                  if cls._isAppExist(i):
                      if fullPath is True:
                          lis.append(cls._dcc_getNodFullpathNodepathStr(i))
                      else:
                          lis.append(bscMethods.MaNodeString.nodenameWithNamespace(i))
          return lis
  
      @staticmethod
      def _setListCleanup(lis):
          lis_ = list(set(lis))
          lis_.sort(key=lis.index)
          return lis_
  
      @classmethod
      def _isAppExist(cls, nodepathString):
          if nodepathString is not None:
              return cls.MOD_maya_cmds.objExists(nodepathString)
          return False
  
  
  class Mtd_MaAttribute(Mtd_MaBasic):
      DEF_mya_porttype_dict = {
          'bool': 'boolean',
          'long': 'integer',
          'short': 'integer',
          'byte': 'integer',
          'float': 'float',
          'double': 'float',
          'char': 'string',
      }
  
      @classmethod
      def _getAttributeQueryNameString(cls, attrpathString):
          _ = attrpathString.split(cls.DEF_mya_node_port_pathsep)[-1]
          if _.endswith(u']'):
              return _.split(u'[')[0]
          return _
  
      @classmethod
      def _toAttributePortsepSplit(cls, attrpathString):
          _ = attrpathString.split(cls.DEF_mya_node_port_pathsep)
          return _[0], cls.DEF_mya_node_port_pathsep.join(_[1:])
  
      @classmethod
      def _getAttributeType(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              attributeType=1
          )
  
      @classmethod
      def _getAttributeData(cls, attrpathString):
          if cls._getAttributeIsAppExist(attrpathString) is True:
              if cls._getAttributeIsMessage(attrpathString):
                  if cls._getAttributeHasSource(attrpathString):
                      return bscMethods.MaAttrpath.nodepathString(cls._getAttributeSource(attrpathString))
              else:
                  return cls.MOD_maya_cmds.getAttr(attrpathString, silent=1)
  
      @classmethod
      def _getAttributePorttype(cls, attrpathString):
          if cls._getAttributeIsEnum(attrpathString):
              return 'string'
          elif cls._getAttributeIsColor(attrpathString):
              return 'color'
          elif cls._getAttributeIsFilename(attrpathString):
              return 'filename'
          _ = cls._getAttributeType(attrpathString)
          if _ in cls.DEF_mya_porttype_dict:
              return cls.DEF_mya_porttype_dict[_]
          return _
  
      @classmethod
      def _getAttributePortdata(cls, attrpathString, asString):
          exclude_datatype_list = [
              'mesh',
              'attributeAlias',
              'TdataCompound',
          ]
          exclude_porttype_list = [
              'polyFaces'
          ]
          if cls._getAttributeIsAppExist(attrpathString) is True:
              if cls._getAttributeIsMessage(attrpathString):
                  if cls._getAttributeHasSource(attrpathString):
                      return bscMethods.MaAttrpath.nodepathString(cls._getAttributeSource(attrpathString))
                  return ''
              else:
                  porttype = cls._getAttributePorttype(attrpathString)
                  if porttype not in exclude_porttype_list:
                      datatype = cls._getAttributeDatatype(attrpathString)
                      attrpathString = cls._getAttributeString_(attrpathString)
                      if datatype == 'enum':
                          return cls.MOD_maya_cmds.getAttr(attrpathString, asString=asString, silent=1)
                      elif datatype not in exclude_datatype_list:
                          _ = cls.MOD_maya_cmds.getAttr(attrpathString, silent=1)
                          if datatype in cls.DEF_mya_datatype_compchannel_list:
                              return list(_[0])
                          return _
  
      @classmethod
      def _getAttributeIsAppExist(cls, attrpathString):
          attrpathString = cls._getAttributeString_(attrpathString)
          return cls.MOD_maya_cmds.objExists(attrpathString)
  
      @classmethod
      def _getAttributeIsNodeExist(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              exists=1
          )
  
      @classmethod
      def _getAttributeIsCompound(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              usesMultiBuilder=1
          )
  
      @classmethod
      def _getAttributeIsMultichannel(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              multi=1
          )
  
      @classmethod
      def _getAttributeIndexes(cls, attrpathString):
          """
          :param attrpathString: etc. aiRampFloat1.ramp
          :return:
          """
          attrpathString = cls._getAttributeString_(attrpathString)
          return cls.MOD_maya_cmds.getAttr(attrpathString, multiIndices=1, silent=1) or []
  
      @classmethod
      def _getAttributeIsMessage(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              message=1
          )
  
      @classmethod
      def _getAttributeIsColor(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              usedAsColor=1
          )
  
      @classmethod
      def _getAttributeIsFilename(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              usedAsFilename=1
          )
  
      @classmethod
      def _getAttributeIsEnum(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              enum=1
          )
  
      @classmethod
      def _getAttributeNicename(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              niceName=1
          )
  
      @classmethod
      def _getAttributeHasParent(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              listParent=1
          ) is not None
  
      @classmethod
      def _getAttributeParentPortname(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          _ = cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              listParent=1
          )
          if _:
              return _[0]
  
      @classmethod
      def _getAttributeHasChild(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              numberOfChildren=1
          ) > 0
  
      @classmethod
      def _getAttributeChildPortnameList(cls, attrpathString):
          nodepathString, portpathString = cls._getAttributeQueryString_(attrpathString)
          return cls.MOD_maya_cmds.attributeQuery(
              cls._getAttributeQueryNameString(portpathString),
              node=nodepathString,
              listChildren=1
          ) or []
  
      @classmethod
      def _getAttributeQueryString_(cls, attrpathString):
          if isinstance(attrpathString, (tuple, list)):
              nodepathString, portpathString = attrpathString
          else:
              nodepathString, portpathString = cls._toAttributePortsepSplit(attrpathString)
          return nodepathString, portpathString
  
      @classmethod
      def _getAttributeString_(cls, attrpathString):
          if isinstance(attrpathString, (tuple, list)):
              attrpathString = cls.DEF_mya_node_port_pathsep.join(list(attrpathString))
          return attrpathString
  
      @classmethod
      def _getAttributeHasChannels(cls, attrpathString):
          return cls._getAttributePorttype(attrpathString) in cls.DEF_mya_datatype_compchannel_list
  
      @classmethod
      def _getAttributeChannelnameList(cls, attrpathString):
          if cls._getAttributeHasChannels(attrpathString):
              return cls._getAttributeChildPortnameList(attrpathString)
          return []
  
      @classmethod
      def _getAttributeDefaultData(cls, attrpathString):
          pass
  
      @classmethod
      def _getAttributeDatatype(cls, attrpathString):
          attrpathString = cls._getAttributeString_(attrpathString)
          return cls.MOD_maya_cmds.getAttr(attrpathString, type=1, silent=1)
  
      @classmethod
      def _getAttributeHasSource(cls, attrpathString):
          attrpathString = cls._getAttributeString_(attrpathString)
          return cls.MOD_maya_cmds.connectionInfo(attrpathString, isExactDestination=1)
  
      @classmethod
      def _getAttributeIsSource(cls, attrpathString):
          attrpathString = cls._getAttributeString_(attrpathString)
          return cls.MOD_maya_cmds.connectionInfo(attrpathString, isExactSource=1)
  
      @classmethod
      def _getAttributeSource(cls, attrpathString):
          attrpathString = cls._getAttributeString_(attrpathString)
          return cls.MOD_maya_cmds.connectionInfo(attrpathString, sourceFromDestination=1)
  
      @classmethod
      def _getAttributeHasTargets(cls, attrpathString):
          return cls.MOD_maya_cmds.connectionInfo(attrpathString, isExactSource=1)
  
      @classmethod
      def _getAttributeIsTarget(cls, attrpathString):
          return cls.MOD_maya_cmds.connectionInfo(attrpathString, isExactDestination=1)
  
      @classmethod
      def _getAttributeTargetList(cls, attrpathString):
          attrpathString = cls._getAttributeString_(attrpathString)
          return cls.MOD_maya_cmds.connectionInfo(attrpathString, destinationFromSource=1) or []
  
      @classmethod
      def _getAttributeNodeString(cls, attrpathString):
          return bscMethods.MaAttrpath.nodepathString(attrpathString)
  
      @classmethod
      def _getAttributeFullpathPortname(cls, attrpathString):
          return bscMethods.MaAttrpath.portpathString(attrpathString)
  
      @classmethod
      def _getAttributePortname(cls, attrpathString):
          return bscMethods.MaAttrpath.name(attrpathString)
  
  
  class Mtd_MaFile(Mtd_MaBasic):
      DEF_mya_type_maya_ascii = 'mayaAscii'
      DEF_mya_type_maya_binary = 'mayaBinary'
      AlembicType = 'Alembic'
      #
      FileTypeDic = {
          '.ma': DEF_mya_type_maya_ascii,
          '.mb': DEF_mya_type_maya_binary,
          '.abc': AlembicType
      }
      #
      MaFileExportAllOption = 'exportAll'
      MaFileExportSelectedOption = 'exportSelected'
      #
      MaFileConstructionHistoryOption = 'constructionHistory'
      MaFileShaderOption = 'shader'
      #
      MaFileExportSelectedOptions = [
          MaFileConstructionHistoryOption,
          MaFileShaderOption
      ]
      VAR_file_export_kwarg_dic = dict(
          type='mayaAscii',
          options='v=0',
          force=True,
          defaultExtensions=True,
          exportAll=True,
          preserveReferences=False,
      )
      VAR_file_import_kwarg_dic = dict(
          options='v=0;',
          type='mayaAscii',
          i=True,
          renameAll=True,
          mergeNamespacesOnClash=True,
          namespace=':',
          preserveReferences=True
      )
  
      @classmethod
      def _getMaFileType(cls, fileString):
          ext = bscMethods.OsFile.ext(fileString)
          return cls.FileTypeDic.get(ext, cls.DEF_mya_type_maya_ascii)
  
      @classmethod
      def _maFileExportCommand(cls, fileString, optionKwargs=None):
          if optionKwargs is None:
              optionKwargs = cls.VAR_file_export_kwarg_dic.copy()
          #
          optionKwargs['type'] = cls._getMaFileType(fileString)
          #
          cls.MOD_maya_cmds.file(fileString, **optionKwargs)
  
      @classmethod
      def _maFileImportCommand(cls, fileString, optionKwargs=None):
          if optionKwargs is None:
              optionKwargs = cls.VAR_file_import_kwarg_dic.copy()
          #
          optionKwargs['type'] = cls._getMaFileType(fileString)
          #
          cls.MOD_maya_cmds.file(
              fileString,
              **optionKwargs
          )
  
      @classmethod
      def _setMaFileImport(cls, fileString, namespace=':'):
          optionKwargs = cls.VAR_file_import_kwarg_dic.copy()
          #
          optionKwargs['type'] = cls._getMaFileType(fileString)
          optionKwargs['namespace'] = namespace
          #
          cls.MOD_maya_cmds.file(
              fileString,
              **optionKwargs
          )
      
      @classmethod
      def _setMaFileImportWithGroup(cls, fileString, groupString, namespace=':'):
          cls.MOD_maya_cmds.file(
              fileString,
              i=1,
              options='v=0;',
              type=cls._getMaFileType(fileString),
              ra=1,
              mergeNamespacesOnClash=1,
              namespace=namespace,
              preserveReferences=1,
              groupReference=True,
              groupString=groupString
          )
          
      @classmethod
      def _setMaAlembicImport(cls, fileString, namespace=':'):
          cls.MOD_maya_cmds.loadPlugin('AbcImport', quiet=1)
  
          cls.MOD_maya_cmds.file(
              fileString,
              i=1,
              options='v=0;',
              type='Alembic',
              ra=1,
              mergeNamespacesOnClash=1,
              namespace=namespace,
              preserveReferences=1
          )
          #
          if namespace:
              alembicNodeString = namespace + ':' + bscMethods.OsFile.name(fileString) + '_AlembicNode'
          else:
              alembicNodeString = bscMethods.OsFile.name(fileString) + '_AlembicNode'
  
          if cls.MOD_maya_cmds.objExists(alembicNodeString):
              pass
          else:
              cls.MOD_maya_cmds.createNode(cls.DEF_mya_type_alembic, name=alembicNodeString)
              cls.MOD_maya_cmds.setAttr(alembicNodeString + '.abc_File', fileString, type='string')
  
      @classmethod
      def _setMaMaterialExport(cls, fileString, shadingEngines, aiAovs):
          cls.MOD_maya_cmds.select(clear=1)
          if shadingEngines:
              cls.MOD_maya_cmds.select(shadingEngines, noExpand=1)
              if aiAovs:
                  cls.MOD_maya_cmds.select(aiAovs, add=1)
              cls.MOD_maya_cmds.file(rename=fileString)
              cls.MOD_maya_cmds.file(
                  force=1,
                  options='v=0',
                  type=cls._getMaFileType(fileString),
                  preserveReferences=0,
                  exportSelected=1
              )
              cls.MOD_maya_cmds.select(clear=1)
          
      @classmethod
      def _setMaFileExportSelected(cls, fileString, nodepathString, withHistory=False):
          temporaryFile = bscMethods.OsFile.temporaryName(fileString)
          cls.MOD_maya_cmds.select(nodepathString)
          cls.MOD_maya_cmds.file(
              temporaryFile,
              force=1,
              options='v=0',
              type=cls._getMaFileType(fileString),
              preserveReferences=0,
              exportSelected=1,
              constructionHistory=withHistory
          )
          cls.MOD_maya_cmds.select(clear=1)
          bscMethods.OsFile.copyTo(temporaryFile, fileString)
          
      @classmethod
      def _setMaFileExportSelectedWithSet(cls, fileString, nodepathString, setString, withHistory=False):
          cls.MOD_maya_cmds.select(clear=1)
          cls.MOD_maya_cmds.select(nodepathString)
  
          if isinstance(setString, str):
              if cls.MOD_maya_cmds.objExists(setString):
                  cls.MOD_maya_cmds.select(setString, add=1, noExpand=1)
          elif isinstance(setString, list):
              for i in setString:
                  if cls.MOD_maya_cmds.objExists(i):
                      cls.MOD_maya_cmds.select(i, add=1, noExpand=1)
          #
          temporaryFile = bscMethods.OsFile.temporaryName(fileString)
          cls.MOD_maya_cmds.file(
              temporaryFile,
              force=1,
              options='v=0',
              type=cls._getMaFileType(fileString),
              preserveReferences=0,
              exportSelected=1,
              constructionHistory=withHistory
          )
          cls.MOD_maya_cmds.select(clear=1)
          bscMethods.OsFile.copyTo(temporaryFile, fileString)
  
      @classmethod
      def _setMaFileReference(cls, fileString, namespace=':'):
          cls.MOD_maya_cmds.file(
              fileString,
              ignoreVersion=1,
              reference=1,
              mergeNamespacesOnClash=0,
              namespace=namespace,
              options='v=0;p=17;f=0',
              type=cls._getMaFileType(fileString)
          )
      
      @classmethod
      def _setMaCacheReference(cls, fileString, namespace=':'):
          cls.MOD_maya_cmds.file(
              fileString,
              reference=1,
              mergeNamespacesOnClash=1,
              namespace=namespace
          )
  
      @classmethod
      def _setMaFileOpen(cls, fileString):
          cls.MOD_maya_cmds.file(
              fileString,
              open=1,
              options='v=0',
              force=1,
              type=cls._getMaFileType(fileString)
          )
          
      @classmethod
      def _setMaFileSaveToServer(cls, fileString):
          temporaryFile = bscMethods.OsFile.temporaryName(fileString)
          cls.MOD_maya_cmds.file(rename=temporaryFile)
          cls.MOD_maya_cmds.file(save=1, type=cls._getMaFileType(fileString))
          bscMethods.OsFile.copyTo(temporaryFile, fileString)
          
      @classmethod
      def _setMaFileSaveToLocal(cls, fileString, timetag=None):
          if timetag is None:
              timetag = bscMethods.OsTimetag.active()
          #
          bscMethods.OsFile.createDirectory(fileString)
          fileString = bscMethods.OsFile.toJoinTimetag(fileString, timetag)
          # Main
          cls.MOD_maya_cmds.file(rename=fileString)
          cls.MOD_maya_cmds.file(
              save=1,
              options='v=0;',
              force=1,
              type=cls._getMaFileType(fileString)
          )
      
      @classmethod
      def _setMaFileUpdate(cls, fileString):
          origString = cls.MOD_maya_cmds.file(query=1, sceneName=1)
          cls._setMaFileSaveToServer(fileString)
          cls.MOD_maya_cmds.file(rename=origString)
      
      @classmethod
      def _setMaFileOpenAsTemporary(cls, fileString):
          if bscMethods.OsFile.isExist(fileString):
              temporaryFile = bscMethods.OsFile.temporaryName(fileString)
              bscMethods.OsFile.createDirectory(temporaryFile)
  
              bscMethods.OsFile.copyTo(fileString, temporaryFile)
              cls._setMaFileOpen(temporaryFile)
          
      @classmethod
      def _setMaFileOpenAsBackup(cls, fileString, backupString, timetag=None):
          if bscMethods.OsFile.isExist(fileString):
              if timetag is None:
                  timetag = bscMethods.OsTimetag.active()
              bscMethods.OsFile.createDirectory(backupString)
              localFileJoinUpdateTag = bscMethods.OsFile.toJoinTimetag(backupString, timetag)
              
              bscMethods.OsFile.copyTo(fileString, localFileJoinUpdateTag)
              cls._setMaFileOpen(localFileJoinUpdateTag)
      
      @classmethod
      def _setMaFileNew(cls):
          cls.MOD_maya_cmds.file(new=1, force=1)
  
  
  class Mtd_MaObject(Mtd_MaUtility):
  
      @classmethod
      def _getNodeIsGroup(cls, nodepathString):
          boolean = False
          # category is "transform" and has no "shape(s)"
          if cls.MOD_maya_cmds.nodeType(nodepathString) == cls.DEF_mya_type_transform:
              _ = cls.MOD_maya_cmds.listRelatives(nodepathString, children=1, shapes=1, noIntermediate=0, fullPath=1)
              if _ is None:
                  boolean = True
          return boolean
  
      @classmethod
      def _getNodeIsTransform(cls, nodepathString):
          boolean = False
          # category is "transform" and has "shape(s)"
          if cls.MOD_maya_cmds.nodeType(nodepathString) == cls.DEF_mya_type_transform:
              _ = cls.MOD_maya_cmds.listRelatives(nodepathString, children=1, shapes=1, noIntermediate=0, fullPath=1)
              if _ is not None:
                  boolean = True
          return boolean
  
      @classmethod
      def _getNodeIsShape(cls, nodepathString):
          boolean = False
          # parent is "transform" and has no "shape(s)"
          if cls.MOD_maya_cmds.nodeType(nodepathString) != cls.DEF_mya_type_transform:
              transformPath = cls._dcc_getNodTransformNodepathStr(nodepathString)
              _ = cls._getNodeShapeNodeStringList(nodepathString)
              if transformPath and not _:
                  boolean = True
          return boolean
  
      @classmethod
      def _isNodeDag(cls, nodepathString):
          return cls.DEF_mya_node_pathsep in cls._dcc_getNodFullpathNodepathStr(nodepathString)
  
      @classmethod
      def _getNodeUniqueIdString(cls, nodepathString):
          if cls._isAppExist(nodepathString):
              stringLis = cls.MOD_maya_cmds.ls(nodepathString, uuid=1)
              if stringLis:
                  return stringLis[0]
  
      @classmethod
      def _getNodeCategoryString(cls, nodepathString):
          return cls.MOD_maya_cmds.nodeType(nodepathString)
  
      @classmethod
      def _getNodeShapeCategoryString(cls, nodepathString):
          string = cls._getNodeCategoryString(nodepathString)
          if string == cls.DEF_mya_type_transform:
              shapePathString = cls._dcc_getNodShapeNodepathStr(nodepathString)
              if shapePathString:
                  string = cls._getNodeCategoryString(shapePathString)
          return string
  
      @classmethod
      def _dcc_getNodTransformNodepathStr(cls, nodepathString, fullpath=True):
          if cls._isAppExist(nodepathString):
              if cls._getNodeCategoryString(nodepathString) == cls.DEF_mya_type_transform:
                  if fullpath:
                      return cls._dcc_getNodFullpathNodepathStr(nodepathString)
                  else:
                      return bscMethods.MaNodeString.nodenameWithNamespace(nodepathString)
              else:
                  stringLis = cls.MOD_maya_cmds.listRelatives(nodepathString, parent=1, fullPath=fullpath)
                  if stringLis:
                      return stringLis[0]
  
      @classmethod
      def _dcc_getNodShapeNodepathStr(cls, nodepathString, fullpath=True):
          string = None
          if cls._getNodeCategoryString(nodepathString) == cls.DEF_mya_type_transform:
              stringLis = cls.MOD_maya_cmds.listRelatives(nodepathString, children=1, shapes=1, noIntermediate=1, fullPath=fullpath)
              if stringLis:
                  string = stringLis[0]
          else:
              if fullpath:
                  string = cls._dcc_getNodFullpathNodepathStr(nodepathString)
              else:
                  string = bscMethods.MaNodeString.nodenameWithNamespace(nodepathString)
          return string
  
      @classmethod
      def _getNodeShapeNodeStringList(cls, nodepathString, fullpath=True):
          return cls.MOD_maya_cmds.listRelatives(nodepathString, children=1, shapes=1, noIntermediate=0, fullPath=fullpath) or []
  
      @classmethod
      def _getNodeTargetNodeStringList(cls, nodepathString, includeCategoryString=None):
          if includeCategoryString is not None:
              return cls.MOD_maya_cmds.listConnections(nodepathString, destination=1, source=0, type=includeCategoryString) or []
          return cls.MOD_maya_cmds.listConnections(nodepathString, destination=1, source=0) or []
  
      @classmethod
      def _getNodeSourceNodeStringList(cls, nodepathString, includeCategoryString=None):
          if includeCategoryString is not None:
              return cls.MOD_maya_cmds.listConnections(nodepathString, destination=0, source=1, type=includeCategoryString) or []
          return cls.MOD_maya_cmds.listConnections(nodepathString, destination=0, source=1) or []
  
      @classmethod
      def _getNodeShadingEngineNodeStringList(cls, nodepathString, excludeNodeString=None):
          def branchFnc_(subObjectString):
              shapePathString = cls._dcc_getNodShapeNodepathStr(subObjectString)
              if not shapePathString:
                  shapePathString = subObjectString
              #
              _ = cls._getNodeTargetNodeStringList(shapePathString, cls.DEF_mya_type_shading_engine)
              if _:
                  if excludeNodeString is not None:
                      [lis.append(j) for j in _ if not j in lis and not j in excludeNodeString]
                  else:
                      [lis.append(j) for j in _ if not j in lis]
          #
          lis = []
          #
          stringLis = cls._toAppExistStringList(nodepathString)
  
          if excludeNodeString is not None:
              excludeNodeString = bscMethods.String.toList(excludeNodeString)
  
          [branchFnc_(i) for i in stringLis]
          return lis
  
      @classmethod
      def _getShadingEngineObjectSetDatumList(cls, nodepathString):
          """
          :param nodepathString: str
          :return: list
          """
          lis = []
          #
          objSetLis = cls.MOD_maya_cmds.sets(nodepathString, query=1)
          if objSetLis:
              shaderObjectPathLis = [i for i in cls.MOD_maya_cmds.ls(objSetLis, leaf=1, noIntermediate=1, long=1)]
              for shaderObjectPath in shaderObjectPathLis:
                  # Object Group
                  showType = cls.MOD_maya_cmds.ls(shaderObjectPath, showType=1)[1]
                  if showType == 'float3':
                      shaderObjectPath_ = shaderObjectPath.split('.')[0]
                      shaderObjectUuid = cls._getNodeUniqueIdString(shaderObjectPath_)
                      objSetData = shaderObjectPath, shaderObjectUuid
                      if not objSetData in lis:
                          lis.append(objSetData)
                  else:
                      shaderObjectUuid = cls._getNodeUniqueIdString(shaderObjectPath)
                      objSetData = shaderObjectPath, shaderObjectUuid
                      if not objSetData in lis:
                          lis.append(objSetData)
          return lis
  
      @classmethod
      def _getNodeAllTargetNodeStringList(cls, nodepathString, includeCategoryString=None, excludeCategoryString=None, useShapeCategory=False, extend=False):
          def recursionFnc_(nodeString_):
              if extend is True:
                  searchNodes = [cls._dcc_getNodTransformNodepathStr(nodeString_), cls._dcc_getNodShapeNodepathStr(nodeString_)]
                  set(searchNodes)
              else:
                  searchNodes = [nodeString_]
  
              for subNode in searchNodes:
                  nodeStrings = cls.MOD_maya_cmds.listConnections(subNode, destination=1, source=0, shapes=1)
                  if nodeStrings:
                      for i in nodeStrings:
                          if useShapeCategory is True:
                              nodeTypeString = cls._getNodeShapeCategoryString(i)
                          else:
                              nodeTypeString = cls._getNodeCategoryString(i)
  
                          if includeCategoryString is not None:
                              if nodeTypeString in includeCategoryString:
                                  if not i in lis:
                                      lis.append(i)
                          elif excludeCategoryString is not None:
                              if nodeTypeString not in excludeCategoryString:
                                  if not i in lis:
                                      lis.append(i)
                          else:
                              if not i in lis:
                                  lis.append(i)
                          #
                          if not i in lis:
                              searchLis.append(i)
                              recursionFnc_(i)
  
          #
          searchLis = []
          #
          lis = []
          #
          if includeCategoryString is not None:
              includeCategoryString = bscMethods.String.toList(includeCategoryString)
          elif excludeCategoryString is not None:
              excludeCategoryString = bscMethods.String.toList(excludeCategoryString)
          #
          recursionFnc_(nodepathString)
          #
          return lis
  
      @classmethod
      def _getNodeAllSourceNodeStringList(cls, nodepathString, includeCategoryString=None, excludeCategoryString=None, useShapeCategory=False, extend=False):
          def addFnc_(nodeString_):
              if not nodeString_ in lis:
                  lis.append(nodeString_)
  
          def recursionFnc_(nodeString_):
              if extend is True:
                  searchNodes = [cls._dcc_getNodTransformNodepathStr(nodeString_), cls._dcc_getNodShapeNodepathStr(nodeString_)]
                  set(searchNodes)
              else:
                  searchNodes = [nodeString_]
  
              for subNode in searchNodes:
                  nodeStrings = cls.MOD_maya_cmds.listConnections(subNode, destination=0, source=1, shapes=1)
                  if nodeStrings:
                      for i in nodeStrings:
                          if useShapeCategory is True:
                              nodeTypeString = cls._getNodeShapeCategoryString(i)
                          else:
                              nodeTypeString = cls._getNodeCategoryString(i)
  
                          if includeCategoryString is not None:
                              if nodeTypeString in includeCategoryString:
                                  addFnc_(i)
                          elif excludeCategoryString is not None:
                              if nodeTypeString not in excludeCategoryString:
                                  addFnc_(i)
                          else:
                              addFnc_(i)
                          #
                          if not i in searchLis:
                              searchLis.append(i)
                              recursionFnc_(i)
          #
          searchLis = []
          #
          lis = []
          #
          if includeCategoryString is not None:
              includeCategoryString = bscMethods.String.toList(includeCategoryString)
          elif excludeCategoryString is not None:
              excludeCategoryString = bscMethods.String.toList(excludeCategoryString)
          #
          recursionFnc_(nodepathString)
          #
          return lis
  
  
  class Mtd_MaNodeGraph(Mtd_MaUtility):
      @classmethod
      def _getNodeGraphNodeStringList(cls, nodepathString, includeCategoryString=None, excludeCategoryString=None, useShapeCategory=False, extend=False):
          return Mtd_MaObject._getNodeAllSourceNodeStringList(
              nodepathString,
              includeCategoryString,
              excludeCategoryString,
              useShapeCategory,
              extend
          )
  
      @classmethod
      def _getNodeGraphConnectionDatumList(cls):
          pass
  
  
  class Mtd_MaDag(Mtd_MaUtility):
      @classmethod
      def _getDagParentString(cls, dagString, fullpath=True):
          _ = cls.MOD_maya_cmds.listRelatives(dagString, parent=1, fullPath=fullpath)
          if _:
              return _[0]
  
      @classmethod
      def _getDagChildStringList(cls, dagString, fullpath=True):
          return cls.MOD_maya_cmds.listRelatives(dagString, children=1, type=cls.DEF_mya_type_transform, fullPath=fullpath) or []
  
  
  class Mtd_MaShadingEngine(Mtd_MaUtility):
      pass
  
  
  class Mtd_MaNodeGroup(Mtd_MaUtility):
      @classmethod
      def _getGroupChildNodeStringList(cls, groupString, includeCategoryString=None, excludeCategoryString=None, useShapeCategory=False, withShape=True):
          def addFnc_(nodeString_):
              if not nodeString_ in lis:
                  if withShape is True:
                      lis.append(nodeString_)
                  else:
                      if Mtd_MaObject._getNodeIsShape(nodeString_) is False:
                          lis.append(nodeString_)
  
          def recursionFnc_(nodeString_):
              nodeStrings = cls.MOD_maya_cmds.listRelatives(nodeString_, children=1, fullPath=1)
              if nodeStrings:
                  for i in nodeStrings:
                      if useShapeCategory is True:
                          nodeTypeString = Mtd_MaObject._getNodeShapeCategoryString(i)
                      else:
                          nodeTypeString = Mtd_MaObject._getNodeCategoryString(i)
  
                      if includeCategoryString is not None:
                          if nodeTypeString in includeCategoryString:
                              addFnc_(i)
                      elif excludeCategoryString is not None:
                          if nodeTypeString not in excludeCategoryString:
                              addFnc_(i)
                      else:
                          addFnc_(i)
                      #
                      if not i in searchLis:
                          searchLis.append(i)
                          recursionFnc_(i)
          #
          searchLis = []
          #
          lis = []
          #
          if includeCategoryString is not None:
              includeCategoryString = bscMethods.String.toList(includeCategoryString)
          elif excludeCategoryString is not None:
              excludeCategoryString = bscMethods.String.toList(excludeCategoryString)
          #
          recursionFnc_(groupString)
          #
          return lis
  
  
  class Mtd_MaPlug(Mtd_MaBasic):
      pass
  