Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create correct Hdas from Subnetworks, keeping Parms, Outputs and Inputs. #160

176 changes: 81 additions & 95 deletions client/ayon_houdini/plugins/create/create_hda.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,8 @@
import hou

import ayon_api
from ayon_core.pipeline import (
CreatorError,
get_current_project_name
)
from ayon_core.lib import (
get_ayon_username,
BoolDef
)
from ayon_core.pipeline import CreatorError, get_current_project_name
from ayon_core.lib import get_ayon_username, BoolDef

from ayon_houdini.api import plugin

Expand All @@ -31,15 +25,16 @@ def get_tool_submenus(hda_def):
"""

import xml.etree.ElementTree as ET
if hda_def.hasSection('Tools.shelf'):

if hda_def.hasSection("Tools.shelf"):
sections = hda_def.sections()
ts_section = sections['Tools.shelf'].contents()
ts_section = sections["Tools.shelf"].contents()
try:
root = ET.fromstring(ts_section)
except ET.ParseError:
return None
tool = root[0]
submenus = tool.findall('toolSubmenu')
submenus = tool.findall("toolSubmenu")
if submenus:
tool_submenus = []
for submenu in submenus:
Expand All @@ -57,8 +52,7 @@ def get_tool_submenus(hda_def):
return None


def set_tool_submenu(hda_def,
new_submenu='Digital Assets'):
def set_tool_submenu(hda_def, new_submenu="Digital Assets"):
"""Sets the tab menu entry for a node.

Arguments:
Expand All @@ -68,34 +62,36 @@ def set_tool_submenu(hda_def,
"""

context_dict = {
'Shop': 'SHOP',
'Cop2': 'COP2',
'Object': 'OBJ',
'Chop': 'CHOP',
'Sop': 'SOP',
'Vop': 'VOP',
'VopNet': 'VOPNET',
'Driver': 'ROP',
'TOP': 'TOP',
'Top': 'TOP',
'Lop': 'LOP',
'Dop': 'DOP'}
"Shop": "SHOP",
"Cop2": "COP2",
"Object": "OBJ",
"Chop": "CHOP",
"Sop": "SOP",
"Vop": "VOP",
"VopNet": "VOPNET",
"Driver": "ROP",
"TOP": "TOP",
"Top": "TOP",
"Lop": "LOP",
"Dop": "DOP",
}

utils_dict = {
'Shop': 'shoptoolutils',
'Cop2': 'cop2toolutils',
'Object': 'objecttoolutils',
'Chop': 'choptoolutils',
'Sop': 'soptoolutils',
'Vop': 'voptoolutils',
'VopNet': 'vopnettoolutils',
'Driver': 'drivertoolutils',
'TOP': 'toptoolutils',
'Top': 'toptoolutils',
'Lop': 'loptoolutils',
'Dop': 'doptoolutils'}

if hda_def.hasSection('Tools.shelf'):
"Shop": "shoptoolutils",
"Cop2": "cop2toolutils",
"Object": "objecttoolutils",
"Chop": "choptoolutils",
"Sop": "soptoolutils",
"Vop": "voptoolutils",
"VopNet": "vopnettoolutils",
"Driver": "drivertoolutils",
"TOP": "toptoolutils",
"Top": "toptoolutils",
"Lop": "loptoolutils",
"Dop": "doptoolutils",
}

if hda_def.hasSection("Tools.shelf"):
old_submenu = get_tool_submenus(hda_def)[0]
else:
# Add default tools shelf section
Expand All @@ -118,26 +114,29 @@ def set_tool_submenu(hda_def,
</tool>
</shelfDocument>
"""

nodetype_category_name = hda_def.nodeType().category().name()
context = context_dict[nodetype_category_name]
util = utils_dict[nodetype_category_name]
content = content.replace(
"<contextNetType>SOP</contextNetType>",
f"<contextNetType>{context}</contextNetType>")
content = content.replace('soptoolutils', util)
hda_def.addSection('Tools.shelf', content)
old_submenu = 'Digital Assets'
f"<contextNetType>{context}</contextNetType>",
)
content = content.replace("soptoolutils", util)
hda_def.addSection("Tools.shelf", content)
old_submenu = "Digital Assets"

# Replace submenu
tools = hda_def.sections()["Tools.shelf"]
content = tools.contents()
content = content.replace(
f"<toolSubmenu>{old_submenu}</toolSubmenu>",
f"<toolSubmenu>{new_submenu}</toolSubmenu>"
f"<toolSubmenu>{new_submenu}</toolSubmenu>",
)

hda_def.addSection('Tools.shelf', content)
hda_def.addSection("Tools.shelf", content)


# endregion


Expand All @@ -162,18 +161,12 @@ def _check_existing(self, folder_path, product_name):
project_name, folder_ids={folder_entity["id"]}, fields={"name"}
)
existing_product_names_low = {
product_entity["name"].lower()
for product_entity in product_entities
product_entity["name"].lower() for product_entity in product_entities
}
return product_name.lower() in existing_product_names_low

def create_instance_node(
self,
folder_path,
node_name,
parent,
node_type="geometry",
pre_create_data=None
self, folder_path, node_name, parent, node_type="geometry", pre_create_data=None
):
if pre_create_data is None:
pre_create_data = {}
Expand All @@ -187,8 +180,8 @@ def create_instance_node(
else:
parent_node = self.selected_nodes[0].parent()
subnet = parent_node.collapseIntoSubnet(
self.selected_nodes,
subnet_name="{}_subnet".format(node_name))
self.selected_nodes, subnet_name="{}_subnet".format(node_name)
)
subnet.moveToGoodPosition()
to_hda = subnet
else:
Expand All @@ -201,34 +194,34 @@ def create_instance_node(
parent_node = pane.pwd()

to_hda = parent_node.createNode(
"subnet", node_name="{}_subnet".format(node_name))
"subnet", node_name="{}_subnet".format(node_name)
)
if not to_hda.type().definition():
# if node type has not its definition, it is not user
# created hda. We test if hda can be created from the node.
if not to_hda.canCreateDigitalAsset():
raise CreatorError(
"cannot create hda from node {}".format(to_hda))
raise CreatorError("cannot create hda from node {}".format(to_hda))

# Pick a unique type name for HDA product per folder path per project.
type_name = (
"{project_name}{folder_path}_{node_name}".format(
project_name=get_current_project_name(),
folder_path=folder_path.replace("/","_"),
node_name=node_name
)
type_name = "{project_name}{folder_path}_{node_name}".format(
project_name=get_current_project_name(),
folder_path=folder_path.replace("/", "_"),
node_name=node_name,
)

hda_node = to_hda.createDigitalAsset(
name=type_name,
description=node_name,
hda_file_name="$HIP/{}.hda".format(node_name),
ignore_external_references=True
ignore_external_references=True,
)
hda_node.layoutChildren()
elif self._check_existing(folder_path, node_name):
raise CreatorError(
("product {} is already published with different HDA"
"definition.").format(node_name))
(
"product {} is already published with different HDA" "definition."
).format(node_name)
Lypsolon marked this conversation as resolved.
Show resolved Hide resolved
)
else:
hda_node = to_hda

Expand Down Expand Up @@ -263,52 +256,45 @@ def get_network_categories(self):
hou.objNodeTypeCategory(),
hou.sopNodeTypeCategory(),
hou.topNodeTypeCategory(),
hou.vopNodeTypeCategory()
hou.vopNodeTypeCategory(),
]

def get_pre_create_attr_defs(self):
attrs = super(CreateHDA, self).get_pre_create_attr_defs()
return attrs + [
BoolDef("set_user",
tooltip="Set current user as the author of the HDA",
default=False,
label="Set Current User"),
BoolDef("use_project",
tooltip="Use project name as tab submenu path.\n"
"The location in TAB Menu will be\n"
"'AYON/project_name/your_HDA_name'",
default=True,
label="Use Project as menu entry"),
BoolDef(
"set_user",
tooltip="Set current user as the author of the HDA",
default=False,
label="Set Current User",
),
BoolDef(
"use_project",
tooltip="Use project name as tab submenu path.\n"
"The location in TAB Menu will be\n"
"'AYON/project_name/your_HDA_name'",
default=True,
label="Use Project as menu entry",
),
]

def get_dynamic_data(
self,
project_name,
folder_entity,
task_entity,
variant,
host_name,
instance
self, project_name, folder_entity, task_entity, variant, host_name, instance
):
"""
Pass product name from product name templates as dynamic data.
"""
dynamic_data = super(CreateHDA, self).get_dynamic_data(
project_name,
folder_entity,
task_entity,
variant,
host_name,
instance
project_name, folder_entity, task_entity, variant, host_name, instance
)

dynamic_data.update(
{
"asset": folder_entity["name"],
"folder": {
"label": folder_entity["label"],
"name": folder_entity["name"]
}
"label": folder_entity["label"],
"name": folder_entity["name"],
},
}
)

Expand Down