コード例 #1
0
def set_connection_offsets(connection_data):
    '''applies offset positions to the input dictionary
    input >
    [{'source':string, 'target':string, 'setPosition':bool, 'setRotation':bool}...]
    output > 
    [{'source':string, 'target':string, 'setPosition':bool, 'setRotation':bool, 'offsetPosition':(3), 'offsetForward':(3), 'offsetUp':(3)}...]'''

    for i, connection in enumerate(connection_data):
        source_pos = POS.get(connection['source'], asEuclid=True)
        target_pos = POS.get(connection['target'], asEuclid=True)

        v = target_pos - source_pos
        connection['positionOffset'] = [v.x, v.y, v.z]

        v = TRANS.transformInverseDirection(
            connection['source'],
            TRANS.transformDirection(connection['target'],
                                     euclid.Vector3(0, 0, 1)))
        connection['offsetForward'] = [v.x, v.y, v.z]

        v = TRANS.transformInverseDirection(
            connection['source'],
            TRANS.transformDirection(connection['target'],
                                     euclid.Vector3(0, 1, 0)))
        connection['offsetUp'] = [v.x, v.y, v.z]
コード例 #2
0
def get_bb_size(arg=None, shapes=False, mode=None, asEuclid=False):
    """
    Get the bb size of a given arg
    
    :parameters:
        arg(str/list): Object(s) to check
        shapes(bool): Only check dag node shapes
        mode(varied): 
            True/'max': Only return max value
            'min': Only min
            maxFill - [max,max.max]

    :returns
        boundingBox size(list)
    """
    _str_func = 'get_bb_size'
    #_arg = VALID.stringListArg(arg,False,_str_func)
    arg = VALID.mNodeString(arg)
    if shapes:
        log.debug("|{0}| >> shapes mode ".format(_str_func))
        arg = VALID.listArg(arg)
        l_use = []
        for o in arg:
            log.debug("|{0}| >> o: '{1}' ".format(_str_func, o))
            l_shapes = mc.listRelatives(o, s=True, fullPath=True) or []
            if l_shapes: l_use.extend(l_shapes)
            else:
                l_use.append(o)
        arg = l_use

    log.debug("|{0}| >> arg: '{1}' ".format(_str_func, arg))
    _box = mc.exactWorldBoundingBox(arg)

    if mode == 'raw':
        if asEuclid:
            log.debug("|{0}| >> asEuclid...".format(_str_func))
            return EUCLID.Vector3(_box[0], _box[1], _box[2])
        return _box
    _res = [(_box[3] - _box[0]), (_box[4] - _box[1]), (_box[5] - _box[2])]

    if mode is None:
        if asEuclid:
            log.debug("|{0}| >> asEuclid...".format(_str_func))
            return EUCLID.Vector3(_res[0], _res[1], _res[2])
        return _res
    elif mode in [True, 'max']:
        return max(_res)
    elif mode in ['min']:
        return min(_res)
    elif mode == 'maxFill':
        _max = max(_res)
        return [_max, _max, _max]
    else:
        log.error("|{0}| >> Unknown mode. Returning default. {1} ".format(
            _str_func, mode))
    return _res
コード例 #3
0
def get_planeIntersect(planeSource=None,
                       target=None,
                       planeAxis='z+',
                       objAxis='z+',
                       mark=False):
    _str_func = 'get_planeIntersect'

    if target:
        mTarget = cgmMeta.asMeta(target)
    else:
        mTarget = cgmMeta.asMeta(mc.ls(sl=1))
        if not mTarget:
            return log.error(cgmGEN.logString_msg(_str_func, 'No Target'))
        mTarget = mTarget[0]

    mObj = cgmMeta.asMeta(planeSource)

    planePoint = VALID.euclidVector3Arg(mObj.p_position)
    planeNormal = VALID.euclidVector3Arg(mObj.getAxisVector(planeAxis))

    rayPoint = VALID.euclidVector3Arg(mTarget.p_position)
    rayDirection = VALID.euclidVector3Arg(mTarget.getAxisVector(objAxis))

    plane = EUCLID.Plane(
        EUCLID.Point3(planePoint.x, planePoint.y, planePoint.z),
        EUCLID.Point3(planeNormal.x, planeNormal.y, planeNormal.z))
    pos = plane.intersect(
        EUCLID.Line3(
            EUCLID.Point3(rayPoint.x, rayPoint.y, rayPoint.z),
            EUCLID.Vector3(rayDirection.x, rayDirection.y, rayDirection.z)))

    if mark:
        LOC.create(position=pos, name='pewpew_planeIntersect')

    return pos
コード例 #4
0
def get_uv_normal(mesh, uvValue, asEuclid=False):
    """
    Get a normal at a uv
    
    :parameters:
        mesh(string) | Surface uv resides on
        uValue(float) | uValue  
        vValue(float) | vValue 
        asEuclid(bool) - whether to return as Vector or not

    :returns
        pos(double3)

    """
    _str_func = 'get_uv_position'

    _follicle = NODE.add_follicle(mesh)
    ATTR.set(_follicle[0], 'parameterU', uvValue[0])
    ATTR.set(_follicle[0], 'parameterV', uvValue[1])

    _normal = ATTR.get(_follicle[0], 'outNormal')
    mc.delete(_follicle)
    if asEuclid:
        log.debug("|{0}| >> asEuclid...".format(_str_func))
        return EUCLID.Vector3(_normal[0], _normal[1], _normal[2])
    return _normal
コード例 #5
0
ファイル: transform_utils.py プロジェクト: liudger/cgmTools
def transformInversePoint(node=None, v=None):
    """
    Get local position of vector transformed from world space of Transform
    
    :parameters:
        node(str): Object to check
        v(d3): vector

    :returns
        new value(Vector3)
    """
    _str_func = 'transformInversePoint'
    _node = VALID.mNodeString(node)

    v = euclidVector3Arg(v)

    log.debug("|{0}| >> node: [{1}] | {2}".format(_str_func, _node, v))

    current_matrix = worldMatrix_get(_node, True)
    s = scaleLocal_get(_node, True)

    transform_matrix = EUCLID.Matrix4()
    transform_matrix.m = v.x
    transform_matrix.n = v.y
    transform_matrix.o = v.z

    scale_matrix = EUCLID.Matrix4()
    scale_matrix.a = s.x
    scale_matrix.f = s.y
    scale_matrix.k = s.z
    scale_matrix.p = 1

    result_matrix = transform_matrix * current_matrix.inverse() * scale_matrix
    return EUCLID.Vector3(result_matrix.m, result_matrix.n, result_matrix.o)
コード例 #6
0
def get_uv_position(mesh, uvValue, asEuclid=False):
    """
    Get a uv position in world space. UV should be normalized.
    
    :parameters:
        mesh(string) | Surface uv resides on
        uValue(float) | uValue  
        vValue(float) | vValue 
        asEuclid(bool) - whether to return as Vector or not

    :returns
        pos(double3)

    """
    _str_func = 'get_uv_position'

    _follicle = NODE.add_follicle(mesh)
    ATTR.set(_follicle[0], 'parameterU', uvValue[0])
    ATTR.set(_follicle[0], 'parameterV', uvValue[1])

    _pos = get(_follicle[1])
    mc.delete(_follicle)

    if asEuclid:
        log.debug("|{0}| >> asEuclid...".format(_str_func))
        return EUCLID.Vector3(_pos[0], _pos[1], _pos[2])
    return _pos
コード例 #7
0
ファイル: transform_utils.py プロジェクト: liudger/cgmTools
def euclidVector3Arg(arg):
    _str_func = 'euclidVector3Arg'
    if not issubclass(type(arg), EUCLID.Vector3):
        if VALID.isListArg(arg) and len(arg) == 3:
            return EUCLID.Vector3(float(arg[0]), float(arg[1]), float(arg[2]))
        else:
            raise ValueError, "|{0}| >> arg: {1}".format(_str_func, arg)
    return arg
コード例 #8
0
    def storeTransformData(self, obj=None):
        if obj is None:
            obj = self.obj

        ct = mc.currentTime(q=True)

        self._prevDataDict = {}

        mc.refresh(su=True)
        for i in range(int(ct), int(mc.playbackOptions(q=True, max=True)) + 1):
            mc.currentTime(i)
            self._prevDataDict[i] = {
                'p': obj.p_position,
                'f': obj.getTransformDirection(EUCLID.Vector3(0, 0, 1)),
                'u': obj.getTransformDirection(EUCLID.Vector3(0, 1, 0))
            }
        mc.refresh(su=False)

        mc.currentTime(ct)
コード例 #9
0
def euclidVector3(arg):
    """
    Simple check to see if an arg is EULER.Vector3 arg
    """
    try:
        [arg.x, arg.y, arg.z]
        return arg
    except:
        try:
            return EUCLID.Vector3(arg)
        except Exception, err:
            raise Exception, err
コード例 #10
0
def bake(connection_data, start, end):
    bake_range = range( int(math.floor(start)), int(math.floor(end+1)))
    if end < start:
        bake_range = range(int(math.floor(end)),int(math.floor(start+1)))
        bake_range.reverse()

    for i in bake_range:
        mc.currentTime(i)
        for conn in connection_data:
            source_pos = POS.get(conn['source'])
            
            if conn['setPosition']:
                positionOffset = euclid.Vector3(0,0,0)
                if 'positionOffset' in conn:
                    pos = conn['positionOffset']
                    positionOffset = euclid.Vector3(pos[0], pos[1], pos[2])
                wanted_position = source_pos + positionOffset
                POS.set(conn['target'], [wanted_position.x, wanted_position.y, wanted_position.z])
                mc.setKeyframe('%s.translate' % conn['target'])
            
            target_pos = POS.get(conn['target'])
            if conn['setRotation']:
                offsetForward = euclid.Vector3(0,0,1)
                if 'offsetForward' in conn:
                    fwd = conn['offsetForward']
                    offsetForward = euclid.Vector3(fwd[0], fwd[1], fwd[2])
                offsetUp = euclid.Vector3(0,1,0)
                if 'offsetUp' in conn:
                    up = conn['offsetUp']
                    offsetUp = euclid.Vector3(up[0], up[1], up[2])
                fwd = TRANS.transformDirection(conn['source'], offsetForward)
                up = TRANS.transformDirection(conn['source'], offsetUp)
                SNAP.aim_atPoint(conn['target'], target_pos + fwd, vectorUp=up, mode='matrix')
                mc.setKeyframe('%s.rotate' % conn['target'])
コード例 #11
0
    def projectOntoPlane(self, vector):
        _str_func = 'LiveRecord.projectOntoPlane'

        camPos = VALID.euclidVector3Arg(self.cam.p_position)

        planeNormal = self.planeNormal
        if self.plane in ['custom', 'object']:
            planeNormal = VALID.euclidVector3Arg(
                self._currentPlaneObject.getTransformDirection(
                    self.planeNormal))

        log.info('Current plane object : {0}'.format(self._currentPlaneObject))
        self.planePoint = VALID.euclidVector3Arg(
            self._currentPlaneObject.p_position)

        rayPoint = VALID.euclidVector3Arg(self.cam.p_position)
        rayDirection = VALID.euclidVector3Arg(vector)

        plane = EUCLID.Plane(
            EUCLID.Point3(self.planePoint.x, self.planePoint.y,
                          self.planePoint.z),
            EUCLID.Point3(planeNormal.x, planeNormal.y, planeNormal.z))
        pos = plane.intersect(
            EUCLID.Line3(
                EUCLID.Point3(rayPoint.x, rayPoint.y, rayPoint.z),
                EUCLID.Vector3(rayDirection.x, rayDirection.y,
                               rayDirection.z)))

        if self._debugPlane:
            self._debugPlane.p_position = self.planePoint
            SNAP.aim_atPoint(obj=self._debugPlane.mNode,
                             mode='matrix',
                             position=self.planePoint + planeNormal,
                             aimAxis='y+',
                             upAxis='z+',
                             vectorUp=planeNormal.cross(
                                 EUCLID.Vector3(0, 1, .01)))

        return pos
コード例 #12
0
ファイル: transform_utils.py プロジェクト: liudger/cgmTools
def scaleLocal_get(node=None, asEuclid=False):
    """
    Query the local scale of a given obj
    
    :parameters:
        node(str): node to query
        asEuclid(bool): whether to return a EUCLID.Vector3

    :returns
        rotation(vector/asEuclid.Vector3)
    """
    _str_func = 'scaleLocal_get'

    node = VALID.mNodeString(node)

    _res = ATTR.get(node, 'scale')
    log.debug("|{0}| >> [{2}] = {1}".format(_str_func, _res, node))

    if asEuclid:
        return EUCLID.Vector3(_res[0], _res[1], _res[2])
    return _res
コード例 #13
0
ファイル: transform_utils.py プロジェクト: liudger/cgmTools
def orientObject_get(node=None, asEuclid=False):
    """
    Query the local rotation/euler of a given obj
    
    :parameters:
        node(str): node to query
        asEuclid(bool): whether to return a EUCLID.Vector3

    :returns
        rotation(vector/asEuclid.Vector3)
    """
    _str_func = 'orient_get'

    node = VALID.mNodeString(node)

    _res = mc.xform(node, q=True, os=True, ro=True)
    log.debug("|{0}| >> [{2}] = {1}".format(_str_func, _res, node))

    if asEuclid:
        return EUCLID.Vector3(_res[0], _res[1], _res[2])
    return _res
コード例 #14
0
ファイル: transform_utils.py プロジェクト: liudger/cgmTools
def scalePivot_get(node=None, asEuclid=False):
    """
    Query the world space rotatePivot of a given node
    
    :parameters:
        node(str): node to query
        asEuclid(bool): whether to return a EUCLID.Vector3

    :returns
        rotation(vector/asEuclid.Vector3)
    """
    _str_func = 'scalePivot_get'

    node = VALID.mNodeString(node)

    _res = mc.xform(node, q=True, ws=True, sp=True)
    log.debug("|{0}| >> [{2}] = {1}".format(_str_func, _res, node))

    if asEuclid:
        return EUCLID.Vector3(_res[0], _res[1], _res[2])
    return _res
コード例 #15
0
def get_planeIntersect(self,
                       target=None,
                       planeAxis='z+',
                       objAxis='z+',
                       mark=True):
    _short = self.mNode
    _str_func = '[{0}] get_planeIntersect'.format(_short)

    if target:
        mTarget = cgmMeta.asMeta(target)
    else:
        mTarget = cgmMeta.asMeta(mc.ls(sl=1))
        if not mTarget:
            return log.error(cgmGEN.logString_msg(_str_func, 'No Target'))
        mTarget = mTarget[0]

    if not self.atUtils('is_rigged'):
        mObj = self
    else:
        mObj = self.moduleTarget.eyeLook

    planePoint = VALID.euclidVector3Arg(mObj.p_position)
    planeNormal = VALID.euclidVector3Arg(mObj.getAxisVector(planeAxis))

    rayPoint = VALID.euclidVector3Arg(mTarget.p_position)
    rayDirection = VALID.euclidVector3Arg(mTarget.getAxisVector(objAxis))

    plane = EUCLID.Plane(
        EUCLID.Point3(planePoint.x, planePoint.y, planePoint.z),
        EUCLID.Point3(planeNormal.x, planeNormal.y, planeNormal.z))
    pos = plane.intersect(
        EUCLID.Line3(
            EUCLID.Point3(rayPoint.x, rayPoint.y, rayPoint.z),
            EUCLID.Vector3(rayDirection.x, rayDirection.y, rayDirection.z)))

    if mark:
        LOC.create(position=pos, name='pewpew')

    return pos
コード例 #16
0
def get(obj=None,
        pivot='rp',
        space='ws',
        targets=None,
        mode='xform',
        asEuclid=False):
    """
    General call for querying position data in maya.
    Note -- pivot and space are ingored in boundingBox mode which returns the center pivot in worldSpace
    
    :parameters:
        obj(str): Object to check
            Transform, components supported
        pivot(str): Which pivot to use. (rotate,scale,boundingBox)
            rotatePivot
            scalePivot
            boundingBox -- Returns the calculated center pivot position based on bounding box
        space(str): World,Object,Local
        mode(str):
            xform -- Utilizes tranditional checking with xForm or pointPosition for components
        asEuclid(bool) - whether to return as Vector or not
    :returns
        success(bool)
    """
    try:
        _str_func = 'get_pos'
        _obj = VALID.mNodeString(obj)
        _pivot = VALID.kw_fromDict(pivot,
                                   SHARED._d_pivotArgs,
                                   noneValid=False,
                                   calledFrom=_str_func)
        _targets = VALID.stringListArg(targets,
                                       noneValid=True,
                                       calledFrom=_str_func)
        _space = VALID.kw_fromDict(space,
                                   SHARED._d_spaceArgs,
                                   noneValid=False,
                                   calledFrom=_str_func)
        _mode = VALID.kw_fromDict(mode,
                                  _d_pos_modes,
                                  noneValid=False,
                                  calledFrom=_str_func)
        _res = False

        if _pivot == 'boundingBox':
            log.debug("|{0}|...boundingBox pivot...".format(_str_func))
            _res = get_bb_center(_obj)
            if MATH.is_vector_equivalent(
                    _res, [0, 0, 0]) and not mc.listRelatives(_obj, s=True):
                _pivot = 'rp'
                log.warning(
                    "|{0}|...boundingBox pivot is zero, using rp....".format(
                        _str_func))

        if '[' in _obj:
            log.debug("|{0}| >> component mode...".format(_str_func))
            if ":" in _obj.split('[')[-1]:
                raise ValueError, "|{0}| >>Please specify one obj. Component list found: {1}".format(
                    _str_func, _obj)
            #_cType = VALID.get_mayaType(_obj)
            _l_comp = VALID.get_component(_obj)
            _root = _l_comp[1]
            _cType = _l_comp[3]
            if not VALID.is_shape(_root):
                _shapes = mc.listRelatives(_root, s=True, fullPath=True) or []
                if len(_shapes) > 1:
                    log.warning(
                        "|{0}| >>More than one shape found. To be more accurate, specify: {1} | shapes: {2}"
                        .format(_str_func, _obj, _shapes))
                _root = _shapes[0]

            _OBJ = '.'.join([_root, _l_comp[0]])

            log.debug(
                "|{0}| >> obj: {1}({6}) | type: {2} | pivot: {3} | space: {4} | mode: {5}"
                .format(_str_func, _OBJ, _cType, _pivot, _space, _mode, _obj))

            kws_pp = {'world': False, 'local': False}
            if _space == 'world': kws_pp['world'] = True
            else: kws_pp['local'] = True

            if _cType == 'polyVertex':
                _res = mc.pointPosition(_OBJ, **kws_pp)
            elif _cType == 'polyEdge':
                mc.select(cl=True)
                mc.select(_OBJ)
                mel.eval("PolySelectConvert 3")
                edgeVerts = mc.ls(sl=True, fl=True)
                posList = []
                for vert in edgeVerts:
                    posList.append(mc.pointPosition(vert, **kws_pp))
                _res = MATH.get_average_pos(posList)
            elif _cType == 'polyFace':
                mc.select(cl=True)
                mc.select(_OBJ)
                mel.eval("PolySelectConvert 3")
                edgeVerts = mc.ls(sl=True, fl=True)
                posList = []
                for vert in edgeVerts:
                    posList.append(mc.pointPosition(vert, **kws_pp))
                _res = MATH.get_average_pos(posList)
            elif _cType in [
                    'surfaceCV', 'curveCV', 'editPoint', 'surfacePoint',
                    'curvePoint', 'cv', 'bezierCurve'
            ]:
                _res = mc.pointPosition(_OBJ, **kws_pp)
                #_res =  mc.pointPosition(_OBJ)
            else:
                raise RuntimeError, "|{0}| >> Shouldn't have gotten here. Need another check for component type. '{1}'".format(
                    _str_func, _cType)

        else:
            log.debug(
                "|{0}| >> obj: {1} | pivot: {2} | space: {3} | mode: {4} | asEuclid: {5}"
                .format(_str_func, _obj, _pivot, _space, _mode, asEuclid))
            if _space == 'local' or _pivot == 'local':
                _res = ATTR.get(_obj, 'translate')
            #elif _pivot == 'local':
            #if _space == 'world':
            #    _res = mc.xform(_obj, q=True, rp = True, ws=True )
            #else:
            #    _res = ATTR.get(_obj,'translate')
            else:
                kws = {
                    'q': True,
                    'rp': False,
                    'sp': False,
                    'os': False,
                    'ws': False
                }
                if _pivot == 'rp': kws['rp'] = True
                else: kws['sp'] = True

                if _space == 'object': kws['os'] = True
                else: kws['ws'] = True

                log.debug("|{0}| >> xform kws: {1}".format(_str_func, kws))

                _res = mc.xform(_obj, **kws)

        if _res is not None:
            if asEuclid:
                log.debug("|{0}| >> asEuclid...".format(_str_func))
                return EUCLID.Vector3(_res[0], _res[1], _res[2])
            return _res
        raise RuntimeError, "|{0}| >> Shouldn't have gotten here: obj: {1}".format(
            _str_func, _obj)
    except Exception, err:
        cgmGen.cgmExceptCB(Exception, err)
コード例 #17
0
def get_axisBox_size(arg=None, children=False, mode=None, asEuclid=False):
    """
    Get the bb size of a given arg
    
    :parameters:
        arg(str/list): Object(s) to check
        shapes(bool): Only check dag node shapes
        mode(varied): 
            True/'max': Only return max value
            'min': Only min

    :returns
        boundingBox size(list)
    """
    _str_func = 'get_axisBox_size'
    #_arg = VALID.stringListArg(arg,False,_str_func)
    try:
        log.debug("|{0}| >> shapes mode ".format(_str_func))
        arg = VALID.listArg(arg)

        _dag = VALID.getTransform(arg[0])
        if not _dag:
            raise ValueError, "Must have a dag node. Obj: {0}".format(_dag)
        if VALID.is_shape(_dag):
            l_shapes = [_dag]
        else:
            l_shapes = mc.listRelatives(_dag, s=True, fullPath=True) or []

        _dup = mc.duplicate(l_shapes, po=False, rc=True)[0]
        if not children:
            for o in mc.listRelatives(
                    _dup, children=True, type='transform',
                    fullPath=True) or []:
                mc.delete(o)
        try:
            _dup = mc.parent(_dup, world=True)[0]
        except:
            pass

        #Reset our stuff before we make our bb...
        ATTR.reset(_dup, ['t', 'r', 'shear'])
        _size = get_bb_size(_dup, True)

        mc.delete(_dup)

        _res = _size

        if mode is None:
            if asEuclid:
                log.debug("|{0}| >> asEuclid...".format(_str_func))
                return EUCLID.Vector3(_res[0], _res[1], _res[2])
            return _res
        elif mode in [True, 'max']:
            return max(_res)
        elif mode in ['min']:
            return min(_res)
        else:
            log.error("|{0}| >> Unknown mode. Returning default. {1} ".format(
                _str_func, mode))
        return _res
    except Exception, err:
        cgmGen.cgmExceptCB(Exception, err, msg=vars())
コード例 #18
0
def get_bb_pos(arg=None,
               shapes=False,
               mode='center',
               mark=False,
               asEuclid=False):
    """
    Get points relative to a bounding box where z is forward
    
    :parameters:
        arg(str/list): Object(s) to check
        shapes(bool): Only check dag node shapes
        mode(varied): 
            center
            bottom
            top
            left
            right
            front
            back
        mark(bool): whether to add a locator at the position for testing
        asEuclid(bool) - whether to return as Vector or not

    :returns
        boundingBox size(list)
    """
    _str_func = 'get_bb_pos'
    #_arg = VALID.stringListArg(arg,False,_str_func)
    _sel = mc.ls(sl=True)
    bb_raw = get_bb_size(arg, shapes, mode='raw')
    _mode = mode.lower()
    if _mode == 'center':
        log.debug("|{0}| >> Center mode".format(_str_func))
        _res = [((bb_raw[0] + bb_raw[3]) / 2), ((bb_raw[4] + bb_raw[1]) / 2),
                ((bb_raw[5] + bb_raw[2]) / 2)]
    elif _mode in ['bottom', 'y-']:
        log.debug("|{0}| >> Bottom mode".format(_str_func))
        _res = [((bb_raw[0] + bb_raw[3]) / 2), bb_raw[1],
                ((bb_raw[5] + bb_raw[2]) / 2)]
    elif _mode in ['top', 'y+']:
        log.debug("|{0}| >> Top mode".format(_str_func))
        _res = [((bb_raw[0] + bb_raw[3]) / 2), bb_raw[4],
                ((bb_raw[5] + bb_raw[2]) / 2)]
    elif _mode in ['front', 'z+']:
        log.debug("|{0}| >> Front mode".format(_str_func))
        _res = [((bb_raw[0] + bb_raw[3]) / 2), ((bb_raw[4] + bb_raw[1]) / 2),
                bb_raw[5]]
    elif _mode in ['back', 'z-']:
        log.debug("|{0}| >> Back mode".format(_str_func))
        _res = [((bb_raw[0] + bb_raw[3]) / 2), ((bb_raw[4] + bb_raw[1]) / 2),
                bb_raw[2]]
    elif _mode in ['left', 'x+']:
        log.debug("|{0}| >> Left mode".format(_str_func))
        _res = [
            bb_raw[3], ((bb_raw[4] + bb_raw[1]) / 2),
            ((bb_raw[5] + bb_raw[2]) / 2)
        ]
    elif _mode in ['right', 'x-']:
        log.debug("|{0}| >> Right mode".format(_str_func))
        _res = [
            bb_raw[0], ((bb_raw[4] + bb_raw[1]) / 2),
            ((bb_raw[5] + bb_raw[2]) / 2)
        ]
    else:
        raise ValueError, "|{0}| >> Unknown mode: {1}".format(_str_func, _mode)

    if mark:
        _size = get_bb_size(arg, shapes)
        _loc = mc.spaceLocator()[0]
        ATTR.set(_loc, 'scale', [v / 4 for v in _size])
        mc.move(_res[0], _res[1], _res[2], _loc, ws=True)
        mc.rename(_loc, '{0}_loc'.format(_mode))
    if _sel:
        mc.select(_sel)
    if asEuclid:
        log.debug("|{0}| >> asEuclid...".format(_str_func))
        return EUCLID.Vector3(_res[0], _res[1], _res[2])
    return _res