Я пишу узел деформера, который принимает в качестве входных данных worldMatrix и видимость цилиндров. Цилиндры организованы в группы, и эта структура отражается на моем деформаторе. У меня есть 2D-массив, организованный по группам с цилиндрами для детей, и каждый массив является составным атрибутом, поэтому я могу контролировать видимость целых групп и отдельных отверстий.
Это настройка атрибута:
aVisibility = nAttr.create("Visibility", "vis", MFnNumericData::kBoolean);
CHECK_MSTATUS(addAttribute(aVisibility));
aTransform = mAttr.create("Transform", "trans", MFnMatrixAttribute::kDouble);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aTransform));
aCylinders = cAttr.create("Cylinders", "cylinders");
cAttr.addChild(aTransform);
cAttr.addChild(aVisibility);
cAttr.setArray(true);
CHECK_MSTATUS(addAttribute(aCylinders));
aGroupVisibility = nAttr.create("GroupVisibility", "grpVis", MFnNumericData::kBoolean, true);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aGroupVisibility));
aGroups = cAttr.create("Groups", "grps");
cAttr.addChild(aGroupVisibility);
cAttr.addChild(aGroupHoles);
cAttr.setArray(true);
CHECK_MSTATUS(addAttribute(aGroups));
Я написал скрипты Python, чтобы добавить к этому цилиндр, который определит, к какой группе он должен принадлежать, добавит новую запись и соединит видимость и worldMatrix.
У меня есть пара проблем с этой настройкой. Во-первых, удаление цилиндра действует так, как я ожидал, так как я определил DisnectBehaviour для удаления экземпляра в массиве. Однако удаление группы оставляет отключенный атрибут на верхнем уровне иерархии, который я должен очистить вручную.
Во-вторых, хотя удаление работает достаточно хорошо, было бы очень удобно, если бы также можно было использовать дублирование. Поэтому, если кто-то дублирует цилиндр, создается запись массива и связываются необходимые атрибуты. Это возможно? До сих пор люди, использующие деформатор, естественно пытались это сделать, и мне пришлось заставить их использовать скрипт.
Кажется, у вас есть некоторые недостающие части для удаления массива в соответствии с документацией. Взято из документации по API:
Если поведение kDelete установлено для атрибута массива, который является составным, он будет обрабатывать только тот случай, когда соединение с родительским атрибутом не связано с его дочерними элементами. Таким образом, разрыв соединения с элементом родителя (например, node.parent [3]) приведет к удалению этого элемента, но разрыв соединения с дочерним элементом (например, node.parent [3] .child) оставит элемент без изменений. , даже если это было последнее такое соединение.
Чтобы родительский элемент массива был удален при разрыве последнего подключения к дочернему элементу, необходимо также установить поведение kDelete для подключаемых дочерних элементов.
На строке, где вы создаете свой матричный атрибут, следующая строка должна быть такой:
aTransform = mAttr.create("Transform", "trans", MFnMatrixAttribute::kDouble);
mAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
Не это:
aTransform = mAttr.create("Transform", "trans", MFnMatrixAttribute::kDouble);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
Обратите внимание, что nAttr.setDiconnectBehavior должен быть mAttr, в противном случае вы применяете его к первому атрибуту видимости.
Таким образом, согласно документации, вам нужно установить поведение отключения как для дочернего, так и для атрибута массива, чтобы при отключении последнего дочернего атрибута родительский элемент массива удалялся. Вот что я думаю должно выглядеть так:
aVisibility = nAttr.create("Visibility", "vis", MFnNumericData::kBoolean);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aVisibility));
aTransform = mAttr.create("Transform", "trans", MFnMatrixAttribute::kDouble);
mAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aTransform));
aCylinders = cAttr.create("Cylinders", "cylinders");
cAttr.addChild(aTransform);
cAttr.addChild(aVisibility);
cAttr.setArray(true);
cAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aCylinders));
aGroupVisibility = nAttr.create("GroupVisibility", "grpVis", MFnNumericData::kBoolean, true);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aGroupVisibility));
aGroups = cAttr.create("Groups", "grps");
cAttr.addChild(aGroupVisibility);
cAttr.addChild(aGroupHoles);
cAttr.setArray(true);
cAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aGroups));
Я вижу отсутствующий атрибут «aGroupHoles» в этом фрагменте кода, поэтому вы должны убедиться, что вы также настроили отключенное поведение там же.
Ваша вторая проблема с дублированием. Я бы сказал, что лучше всего иметь скрипт, который ваши пользователи вызывают, который обрабатывает это правильно.
Других решений пока нет …