# -*- 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()