距离过远检查项


# -*- coding: utf-8 -*-
import re, time
import pymel.core as pm

import holyPipePM.HLPipePM.HLPipePMBase as HLPipePM
from upUtil import AbstractChecker, Get, ProjectConfig


get = Get.Get()
PROJECT = get.Get_ActiveProject()  # 项目名称
CAMERA_PATTERN = r'(s|seq|SC)\d{2,3}_(shot|cam)\d{3}[a-z,A-Z_]?\d{0,2}'  # 相机匹配规则
ZERO = pm.datatypes.Vector(0.0, 0.0, 0.0)  # 原点
START_FRAME = 101  # 起始帧
MAX_LENGTH = 6000  # 1比1角色比例的距离边界值
CACHE_GRP = ['::geometryGrp', '::Geo_render', '::high']  # 缓存组
CTRL = ['::Constrain', '::Master_ctrl']  # 控制器名称
CHR_PATH = 'I:/dsf/Asset/CH'

def get_camera(camera_pattern=CAMERA_PATTERN):
    all_cam = pm.ls(type='camera')
    all_skip_cam = ['persp', 'top', 'front', 'side', 'back', 'left', 'bottom']
    cur_cam = []
    for i in all_cam:
        if not i.isReferenced():
            for skip_cam in all_skip_cam:
                if i.startswith(skip_cam):
                    break
            else:
                cur_cam.append(i)

    if not cur_cam:
        return all_cam[0]
    else:
        for cam in cur_cam:
            if re.match(camera_pattern, cam.name()):
                return cam
        return cur_cam[0]


def get_asscet(ctrl=CTRL):
    obj = []
    all_asb = pm.ls(type='assemblyReference')
    env = ''
    if all_asb:
        i = 10
        for asb in all_asb:
            space_num = len(re.findall(':', asb.namespace()))
            if space_num < i:
                i = space_num
                env = asb
    if env:
        obj.append(env)

    obj.extend([i for i in pm.ls(ctrl) if  '_eye_' not in i and 'face_' not in i])
    return obj


def get_shot(cam, camera_pattern=CAMERA_PATTERN):
    cam = cam.name()
    seq = '001'
    shot = '001'
    if re.search(camera_pattern.split('_', 1)[0], cam):
        seq = re.search(r'\d{3}', re.search(camera_pattern.split('_', 1)[0], cam).group()).group()
    if re.search(camera_pattern.split('_', 1)[1], cam):
        shot = ''.join(re.findall(r'\d', re.search(camera_pattern.split('_', 1)[1], cam).group()))
    return 'seq{}_shot{}'.format(seq, shot)


def get_frame(shot, project=PROJECT, start_frame=101):
    script_name = "HolyPipeUploadVersion"
    api_key = ProjectConfig.ProjectConfig().getValue('ProductionManage/HolyPipeUploadVersionKey', default=[])
    sg = HLPipePM.HLPipePM(script_name, api_key)
    fliter = [['project.Project.code', 'is', project],
              ['code', 'is', shot]]
    field = ['sg_cut_in', 'sg_key_frame']
    Shot = sg.find_one('Shot', fliter, field)
    frame = start_frame
    if Shot:
        if Shot['sg_key_frame'] and Shot['sg_key_frame'] > Shot['sg_cut_in']:
            frame = Shot['sg_key_frame']
        else:
            frame = Shot['sg_cut_in'] or start_frame
    return frame


def move_obj(obj, pos):
    print u'obj: {}, pos: {}'.format(obj, pos)
    obj.t.unlock()
    attr_dict = {'tx': pos[0], 'ty': pos[1], 'tz': pos[2]}
    for attr in attr_dict:
        print attr
        attr_node = pm.PyNode('{}.{}'.format(obj.name(), attr))
        attr_node.unlock()
        key_list = pm.keyframe(attr_node, q=1, vc=1)
        if key_list:
            key_list = [i + attr_dict[attr] for i in key_list]
            time_list = pm.keyframe(attr_node, q=1, tc=1)
            for key_iter in zip(time_list, key_list):
                pm.keyframe(attr_node, t=key_iter[0], vc=key_iter[1])
                print key_iter[0], key_iter[1]
        else:
            if not attr_node.listConnections(s=1, d=0):
                attr_node.set(attr_node.get() + attr_dict[attr])
                print attr_node.get() + attr_dict[attr]
                print 'no key'


def move_camera(cam, pos):
    cam = pm.listRelatives(cam, p=1)[0]
    cam.rename('_'.join(cam.name()))
    new_cam = pm.duplicate(cam, n=cam.name()[::2], po=1)[0]
    pm.parent(new_cam, world=1)
    for attr in ['t', 'tx', 'ty', 'tz', 'r', 'rx', 'ry', 'rz']:
        pm.setAttr('{}.{}'.format(new_cam, attr), l=0)
    pm.parentConstraint(cam, new_cam)
    startTime = pm.playbackOptions(q=1, min=1)
    endTime = pm.playbackOptions(q=1, max=1)
    pm.bakeResults(new_cam, t=(startTime, endTime))
    pm.delete(new_cam.getChildren())
    cam.getShapes()[0].rename('{}Shape1'.format(new_cam))
    pm.parent(cam.getShapes(), new_cam, s=1, r=1)

    add_attr(new_cam, pos)
    move_obj(new_cam, pos)


def add_attr(obj, pos, zero=ZERO):
    if not pm.attributeQuery('move_pos', node=obj, ex=1):
        obj.addAttr('move_pos', dt='string', h=0)
        pos = pos + zero
        offset = {}
    else:
        obj.move_pos.unlock()
        offset = eval(obj.move_pos.get())
        pos = pos + zero + pm.datatypes.Vector(offset[sorted(offset.keys())[-1]])
    offset[time.strftime("%Y.%m.%d_%H:%M:%S", time.localtime())] = list(pos)
    obj.move_pos.set(str(offset), type='string')
    obj.move_pos.lock()


def add_field(cam, project, shot_name):
    script_name = "HolyPipeShotMoveOffset"
    api_key = ProjectConfig.ProjectConfig().getValue('ProductionManage/ShotgunShotMoveOffsetKey', default=[])
    sg_update = HLPipePM.HLPipePM(script_name, api_key)
    fliter = [['project.Project.code', 'is', project], ['code', 'is', shot_name]]
    shot = sg_update.find_one('Shot', fliter, ['sg_shotmoveoffset'])

    offset = eval(cam.getParent().move_pos.get() or '{}')

    print offset
    data = {'sg_shotmoveoffset': str(offset)}
    print 'Shot', shot['id'], data
    sg_update.update('Shot', shot['id'], data)
    

def check_dis(cam, cache_grp=None, max_length=6000, frame=None):
    print cam, cache_grp, max_length, frame
    print "cam, cache_grp, max_length, frame"
    cam = pm.PyNode(cam).getParent()
    focal = cam.focalLength.get()
    chr = []

    if frame:
        pm.currentTime(frame)
    if cache_grp:
        cache_grps = pm.ls(cache_grp)
    else:
        print "cache_grps start"
        cache_grps = pm.ls(['::geometryGrp', '::high'])
        print "cache_grps end"

    for grp in cache_grps:
        if not grp.referenceFile() or CHR_PATH not in grp.referenceFile().path:
            continue
        mesh = [i for i in grp.listRelatives(ad=1, type='mesh', ni=1) if i.isVisible()]
        print '\n'
        if mesh:
            minX = min(i.boundingBoxMinX.get() for i in mesh)
            minY = min(i.boundingBoxMinY.get() for i in mesh)
            minZ = min(i.boundingBoxMinZ.get() for i in mesh)
            maxX = max(i.boundingBoxMaxX.get() for i in mesh)
            maxY = max(i.boundingBoxMaxY.get() for i in mesh)
            maxZ = max(i.boundingBoxMaxZ.get() for i in mesh)
            mid_x = (maxX + minX) * 0.5
            mid_y = (maxY + minY) * 0.5
            mid_z = (maxZ + minZ) * 0.5

            bd_leng = pm.datatypes.Vector(maxX - minX, maxY - minY, maxZ - minZ).length()
            pos = pm.spaceLocator(n='boundingBoxLoc')
            pos.t.set(mid_x, mid_y, mid_z)
            pm.orientConstraint(cam, pos)
            distance = pm.spaceLocator(n='distanceLoc')
            pm.parent(distance, cam)
            distance.t.set(0, 0, 0)
            pm.orientConstraint(cam, distance)
            pm.pointConstraint(pos, distance, skip=['x', 'y'])
            dis_num = distance.tz.get() * -1
            pm.delete(pos, distance)
            print grp
            print abs(bd_leng / dis_num * focal), 8
            print pm.datatypes.Vector(mid_x, mid_y, mid_z).length(), 0.006 * bd_leng * max_length
            print 'bd_leng:', bd_leng, 'max_length:', max_length

            if abs(bd_leng / dis_num * focal) > 8 and pm.datatypes.Vector(mid_x, mid_y, mid_z).length() > 0.006 * bd_leng * max_length:
                chr.append(grp.name())

    return chr


def try_fix():
    cam = get_camera()
    shot = get_shot(cam)
    frame = get_frame(shot)
    pm.currentTime(frame)

    pos = cam.getParent().getTranslation(space='world') * -1

    move_camera(cam, pos)
    obj_list = get_asscet(CTRL)
    for obj in obj_list:
        move_obj(obj, pos)

    top_transforms = [i for i in pm.ls(assemblies=1) if i.name() not in ['front', 'top', 'persp', 'side']]
    for transform in top_transforms:
        if transform.nodeType() == 'assemblyReference' or transform.isReferenced() or transform.nodeType() == 'camera':
            continue
        i = 0
        for i in transform.listRelatives(ad=1):
            if i.nodeType() == 'assemblyReference' or i.isReferenced() or i.nodeType() == 'camera':
                i = 1
                break
        if i == 1:
            continue
        for i in ['t', 'tx', 'ty', 'tz']:
            if pm.listConnections('{}.{}'.format(transform.name(), i), s=1, d=0):
                i = 1
                break
        if i == 1:
            continue
        else:
            pm.move(transform, pos, r=1, ws=1)
            print transform


    add_field(cam, PROJECT, shot)
    # 增加一个新组,用于动画师手动归位
    # 旧的移动到正确位置
    # 新的保留本次位移
    if pm.objExists('|TOO_FAR_GRP'):
        grp = pm.PyNode('|TOO_FAR_GRP')
        old_pos = pm.datatypes.Vector(eval(grp.move_pose.get()))
        grp.move_pose.set(str(pos))
        pm.move(pm.datatypes.Vector(pos*-1) - old_pos, r=1)

    else:
        grp = pm.group(n='TOO_FAR_GRP', em=1)
        grp.addAttr('move_pose', dataType='string')
        grp.move_pose.set(str(pos*-1))
        pm.move(pos*-1)

def check(checkList=AbstractChecker.AbstractCheckList()):
    checkItem = checkList.addCheckItem('Hiding Mesh Check', checkTitleCn=u'检查物体距离原点的距离是否过远',
                                       allowAutoFix=False, allFixEval='')
    frame = pm.getCurrentTime()
    cam = get_camera(CAMERA_PATTERN)
    chr = check_dis(cam, CACHE_GRP, MAX_LENGTH, frame)
    if chr:
        checkItem.addProblem(u'检查物体距离原点的距离过远,建议移动至原点', ProblemObjects=chr, fixProcEval=try_fix, asWarning=False)


评论
  目录