【MAYA】あるインスタンスの兄弟ノードを選択する

さらに、続きです。インスタンスを選択して実行すると兄弟インスタンスを選択し直すコードも作ってみました。
ここでいう兄弟インスタンスとは、インスタンスの仲間のうち、親インスタンスを除くものの事です。
スクリプトエディタにペーストする用です。シェルフに登録すると楽に使えると思います。
MAYA2018 + MacOS Sierraで動作確認しています。

#使い方

1.ノードを選択状態にします。対象としてはインスタンスメッシュそのもの、またはその親トランスフォームとなります。
2.Scriptを実行します。
3.兄弟インスタンスノードがあれば選択状態になります。親ノードは選択対象にはいりません。選択すべきものがなければエラーメッセージが表示されます。

<img width="354" alt=" 2018-01-04 3.17.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/6270f74d-39ca-5fbd-286b-d2f4a123f44d.png">
最初にインスタンスの親トランスフォームが選択されていれば、

<img width="377" alt=" 2018-01-04 3.17.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/19bea7cb-80f8-7353-99ca-83bc048005e1.png">
兄弟インスタンスの親トランスフォームが選択されます。（自身も選択されたまま。）

<img width="360" alt=" 2018-01-04 3.17.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/cab39e7c-2daa-6325-1790-bb4ce933fb91.png">
最初にインスタンスそのものが選択されていれば、

<img width="380" alt=" 2018-01-04 3.17.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/405bd74f-9c90-5fa0-e02d-98b877d35450.png">
兄弟インスタンスもそのものがそれぞれ選択されます。（自身も選択されたまま。）

<img width="358" alt=" 2018-01-04 3.18.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/42d04849-f344-a839-00cb-4bb769e469fa.png">
親インスタンスが選択されていた場合、

<img width="373" alt=" 2018-01-04 3.18.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/fa0fba60-cc9a-f540-566b-f3307a9a093f.png">
兄弟インスタンスが選択され直されます。（親の選択は解除される。）

<img width="300" alt=" 2018-01-04 3.31.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/34c7234a-ee06-0a41-92d5-55d5352577d9.png">
親インスタンス１つと子インスタンス１つしかない場合、親インスタンスを選択して処理を実行すると子インスタンスに選択が移ります。子インスタンスを選択して処理を実行した場合、選択が維持され何も起きません。

<img width="352" alt=" 2018-01-04 3.19.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/c523179c-ac92-1b8e-9f0a-3887b435ef9e.png">
インスタンスが見つからない場合はエラーとなります。

#対応していないパターン
親インスタンスは探索後の選択対象から外れます。
親も合わせて選択したい -> もう一つの scriptで親を見つけてから手動で追加選択して下さい。

自身は探索後の選択対象に含まれます。
自身は兄弟と合わせて選択したくない -> 手動で追加選択解除して下さい。

UIを作ればいろんなパターンに対応できますが、そこまでやりだすと大変なので…。（なのでクイック実行用コードという表現をしている。）

#クイック実行用コード

```python
import pymel.core as pm


def get_instance_siblings(node, exclude_first_instance=True):
    """
    インスタンスの兄弟を得る

    :param node: 兄弟を探すインスタンスノード参照
    :type node: pymel.nodetypes.DagNode
    :param exclude_first_instance: 親インスタンスを除くか
    :type exclude_first_instance: bool
    :return: 見つかった兄弟ノードとエラー情報ストリング
    :rtype: tuple of (list of DagNode) and str
    """
    org_node = node
    target_is_children = False
    is_instanced = node.isInstanced()
    if not is_instanced:
        # 選択がインスタンスでない場合は子供を探す
        target_is_children = True
        children = pm.listRelatives(node)
        node = None
        for child_node in children:
            if child_node.isInstanced():
                node = child_node
                break
        if node is None:
            return None, '対象インスタンスが見つかりません。'
    instances = node.getInstances()
    if exclude_first_instance:
        instances = [x for x in instances if x.instanceNumber() != 0]
    if target_is_children:
        instances_ = []
        for ins_node in instances:
            parents = pm.listRelatives(ins_node, parent=True)
            if len(parents) == 1:
                instances_.append(parents[0])
        instances = instances_
    if len(instances) == 0:
        return [], '兄弟インスタンスが存在しません。'
    return instances, None


def select_instance_siblings():
    selected = pm.selected()
    if len(selected) == 0:
        pm.confirmDialog(title='Info', message='ノードを選択して下さい。', button=['Ok'])
        return
    node = selected[0]
    siblings, error_info = get_instance_siblings(node)
    if error_info is not None:
        pm.confirmDialog(title='Info', message=error_info, button=['Ok'])
    if siblings is not None:
        for sibling in siblings:
            print (sibling)
        pm.select(siblings)


select_instance_siblings()
del select_instance_siblings
del get_instance_siblings

```