# -*- coding: utf-8 -*-
import maya.cmds as cmds
import webbrowser
def lc_open_help_url(*_):
webbrowser.open("https://www.google.com/") # ← 必要に応じて変更
def lc_get_parent():
return cmds.scrollField("lc_parentScroll", q=True, text=True).strip()
def lc_get_children():
raw = cmds.scrollField("lc_childScroll", q=True, text=True)
return [line.strip() for line in raw.splitlines() if line.strip()]
def lc_update_display_parent(*_):
sel = cmds.ls(sl=True)
if not sel or len(sel) != 1:
cmds.warning(u"親は1つだけ選択してください。")
return
cmds.scrollField("lc_parentScroll", e=True, text=sel[0])
def lc_update_display_children(*_):
sel = cmds.ls(sl=True)
if not sel:
cmds.warning(u"子オブジェクトを1つ以上選択してください。")
return
cmds.scrollField("lc_childScroll", e=True, text=u"\n".join(sel))
def lc_reset_selection(*_):
cmds.scrollField("lc_parentScroll", e=True, text=u"")
cmds.scrollField("lc_childScroll", e=True, text=u"")
def lc_is_locked_or_hidden(obj, attrs):
for attr in attrs:
full_attr = u"{0}.{1}".format(obj, attr)
if not cmds.objExists(full_attr):
continue
if cmds.getAttr(full_attr, lock=True):
return True
if not cmds.getAttr(full_attr, keyable=True) and not cmds.getAttr(full_attr, channelBox=True):
return True
return False
def lc_lock_attrs(obj, attrs):
for attr in attrs:
if cmds.objExists(u"{0}.{1}".format(obj, attr)):
cmds.setAttr(u"{0}.{1}".format(obj, attr), lock=True, keyable=False, channelBox=False)
def lc_match_transform(target, source):
pos = cmds.xform(source, q=True, ws=True, t=True)
rot = cmds.xform(source, q=True, ws=True, ro=True)
cmds.xform(target, ws=True, t=pos)
cmds.xform(target, ws=True, ro=rot)
def lc_create_unique_name(base_name):
if not cmds.objExists(base_name):
return base_name
i = 1
while cmds.objExists(u"{0}{1}".format(base_name, i)):
i += 1
return u"{0}{1}".format(base_name, i)
def lc_create_control_pair(common_parent, child_obj):
skip_t = lc_is_locked_or_hidden(child_obj, ["translateX", "translateY", "translateZ"])
skip_r = lc_is_locked_or_hidden(child_obj, ["rotateX", "rotateY", "rotateZ"])
locator_trans = None
if not skip_t:
loc_d = u"TH_{0}_translrig".format(child_obj)
if cmds.objExists(loc_d):
cmds.delete(loc_d)
locator_trans = cmds.spaceLocator(name=loc_d)[0]
cmds.delete(cmds.pointConstraint(child_obj, locator_trans))
cmds.parent(locator_trans, common_parent)
pc = cmds.pointConstraint(child_obj, locator_trans, mo=False)[0]
start = cmds.playbackOptions(q=True, min=True)
end = cmds.playbackOptions(q=True, max=True)
cmds.bakeResults(locator_trans, t=(start, end), at=["translate"], simulation=True, preserveOutsideKeys=True)
cmds.delete(pc)
lc_lock_attrs(locator_trans, ["rotateX", "rotateY", "rotateZ", "scaleX", "scaleY", "scaleZ"])
if not skip_r:
loc_e = u"TH_{0}_orientrig".format(child_obj)
if cmds.objExists(loc_e):
cmds.delete(loc_e)
locator_rot = cmds.spaceLocator(name=loc_e)[0]
lc_match_transform(locator_rot, child_obj)
cmds.parent(locator_rot, locator_trans if locator_trans else common_parent)
lc_lock_attrs(locator_rot, ["translateX", "translateY", "translateZ", "scaleX", "scaleY", "scaleZ"])
oc = cmds.orientConstraint(child_obj, locator_rot, mo=False)[0]
start = cmds.playbackOptions(q=True, min=True)
end = cmds.playbackOptions(q=True, max=True)
cmds.bakeResults(locator_rot, t=(start, end), at=["rotate"], simulation=True, preserveOutsideKeys=True)
cmds.delete(oc)
cmds.orientConstraint(locator_rot, child_obj, mo=True)
if locator_trans:
cmds.pointConstraint(locator_trans, child_obj, mo=True)
print(u"[OK] {0} → ローカル制御構造 作成完了".format(child_obj))
def lc_execute_all(*_):
parent = lc_get_parent()
children = lc_get_children()
if not parent or not children:
cmds.warning(u"親と子オブジェクトを選択してください。")
return
raw_parent_name = u"TH_{0}_pivot_parent".format(parent)
unique_parent_name = lc_create_unique_name(raw_parent_name)
common_parent = cmds.spaceLocator(name=unique_parent_name)[0]
cmds.delete(cmds.pointConstraint(parent, common_parent))
cmds.parentConstraint(parent, common_parent, mo=False)
# 親ロケーターをロック
lc_lock_attrs(common_parent, [
"translateX", "translateY", "translateZ",
"rotateX", "rotateY", "rotateZ",
"scaleX", "scaleY", "scaleZ"
])
for child in children:
lc_create_control_pair(common_parent, child)
cmds.inViewMessage(amg=u"ローカル制御リグ構築完了", pos="midCenter", fade=True)
lc_reset_selection()
def lc_build_ui():
win = "lc_localControlRigUI"
if cmds.window(win, exists=True):
cmds.deleteUI(win)
cmds.window(win, title=u"ローカル制御リグ構築", sizeable=False, menuBar=True)
cmds.menu(label=u"ヘルプ", helpMenu=True)
cmds.menuItem(label=u"ドキュメントを開く", command=lc_open_help_url)
cmds.columnLayout(adjustableColumn=True, rowSpacing=10, columnAttach=("both", 2), columnOffset=("both", 2))
cmds.separator(h=1)
cmds.scrollField("lc_parentScroll", editable=False, wordWrap=False, height=30)
cmds.button(label=u"親を登録", command=lc_update_display_parent)
cmds.separator(h=8)
cmds.scrollField("lc_childScroll", editable=False, wordWrap=False, height=60)
cmds.button(label=u"子を登録", command=lc_update_display_children)
cmds.separator(h=10)
cmds.button(label=u"実行(ローカル制御構築)", command=lc_execute_all, bgc=(0.2, 0.5, 0.3))
cmds.rowLayout(numberOfColumns=1, columnAlign1="left")
cmds.button(label=u"選択をリセット", width=100, command=lc_reset_selection, bgc=(0.3, 0.3, 0.3))
cmds.setParent('..')
cmds.showWindow(win)
# 起動
lc_build_ui()