# -*- 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)
评论