123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- # coding:utf-8
- #!/usr/bin/python
- #
- # Copyright (c) Contributors to the Open 3D Engine Project.
- # For complete copyright and license terms please see the LICENSE at the root of this distribution.
- #
- # SPDX-License-Identifier: Apache-2.0 OR MIT
- #
- #
- # -------------------------------------------------------------------------
- """
- azpy.dcc.maya.helpers.utils 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
- _DCCSI_GDEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
- _DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
- _PACKAGENAME = __name__
- if _PACKAGENAME == '__main__':
- _PACKAGENAME = 'azpy.dcc.maya.helpers.utils'
- _LOGGER = initialize_logger(_PACKAGENAME, default_log_level=int(20))
- _LOGGER.debug('Invoking:: {0}.'.format({_PACKAGENAME}))
- # -------------------------------------------------------------------------
- # -------------------------------------------------------------------------
- # Initiate the Wing IDE debug connection.
- if _DCCSI_GDEBUG:
- #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 range(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
- #----------------------------------------------------------------------
- # ----------------------------------------------------------------------
- def get_object_attributes(self, obj):
- attribute_list = {}
- for attr in cmds.listAttr(obj):
- target_string = f'{obj}.{attr}'
- try:
- attr_value = cmds.getAttr(target_string)
- if attr_value:
- attribute_list[attr] = attr_value
- else:
- attribute_list[attr] = ''
- except RuntimeError:
- pass
- except ValueError:
- pass
- for key, value in attribute_list.items():
- print(f'AttributeName: {key} : Value: {value}')
- # ----------------------------------------------------------------------
- # -------------------------------------------------------------------------
- #==========================================================================
- # Class Test
- #==========================================================================
- if __name__ == '__main__':
- # get a selection object
- sel = Selection()
-
- # to do: this needs some tests?
|