Dieser Artikel ist der Artikel zum 10. Tag des ** Houdini Adventskalenders 2019 **.
** Houdini 18.0 ** wurde Ende letzten Monats veröffentlicht!
Viele Leute benutzen es bereits, aber der in [** New Feature Movie **] eingeführte Knoten (https://www.sidefx.com/products/houdini/whats-new-in-18/) Außerdem scheinen kleinere Aktualisierungen vorgenommen worden zu sein.
In diesem Artikel werde ich Ihnen zeigen, wie Sie Knoten erhalten und erstellen, die in Houdini 18.0 hinzugefügt und aktualisiert wurden.
Betrachten Sie die Definition von Ergänzungen und Aktualisierungen, um dies herauszufinden. Die folgenden zwei sind definiert.
Basierend auf dieser Bedingung möchte ich alle hinzugefügten und aktualisierten Knoten in Python wie einen Netzwerkeditor erstellen. Die zu vergleichenden Versionen sind übrigens ** 17.5.391 ** und ** 18.0.287 **.
Sehen Sie sich zunächst das Ergebnis der Ausführung des Skripts an.
Wenn Sie das Skript ausführen, wird ein Fenster angezeigt, in dem Sie auswählen können, welche Version verglichen werden soll. Wenn Sie es auswählen, wird der Knotenvergleichsprozess ausgeführt. Wenn die Verarbeitung abgeschlossen ist, werden ** NewNodes ** für den Knoten mit dem hinzugefügten Knoten selbst erstellt, und ** Subnetz ** wird für den Knoten mit dem hinzugefügten Parameter ** NewParmNodes ** erstellt, und die Kategorien wie ** Sop ** werden erstellt. Für jeden gibt es einen Knoten.
** Sop-Knoten in 18.0 hinzugefügt **
Übrigens enthält der hinzugefügte Parameter einen Ausdruck namens ** Konstante () **. Wenn Sie also ** Parameter mit Nicht-Standardwerten ** aus dem Parameterfilter auswählen, kann nur der hinzugefügte Parameter angezeigt werden. Ich werde.
Das Skript kann aus dem unten stehenden ** GitHub ** -Repository heruntergeladen und verwendet werden.
Zuerst habe ich darüber nachgedacht, alle hinzugefügten und aktualisierten Knoten aufzulisten, aber es gab zu viele. Deshalb habe ich die Anzahl der hinzugefügten und aktualisierten Knoten nach Kategorien zusammengefasst.
Category | Node Count |
---|---|
Shop | 1 |
Chop | 2 |
Top | 12 |
Object | 3 |
Driver | 6 |
Cop2 | 1 |
Sop | 62 |
Lop | 51 |
Dop | 12 |
TopNet | 2 |
Insgesamt wurden ** 152 ** Knoten hinzugefügt und aktualisiert.
Nicht nur die neu hinzugefügte ** LOP **, sondern auch ** SOP ** allein hat ** 62 ** Knoten hinzugefügt und aktualisiert.
Schauen wir uns nun die Anzahl der Knoten mit hinzugefügten Parametern an.
Category | Node Count | Parameter Count |
---|---|---|
Top | 44 | 175 |
Object | 1 | 3 |
Driver | 1 | 3 |
Chop | 1 | 4 |
Sop | 43 | 226 |
Lop | 24 | 241 |
Vop | 10 | 41 |
Dop | 63 | 361 |
Hier wurden Parameter zu insgesamt ** 187 ** Knoten hinzugefügt, und ** 1054 ** Parameter wurden in Bezug auf die Anzahl der Parameter hinzugefügt.
In diesem Sinne war ** Lop ** ab ** Houdini 17.5 **. Und es scheint, dass nicht nur ** LOP ** und ** Sop **, sondern auch ** Top ** und ** Dop ** erheblich aktualisiert wurden.
Ich habe keine Lust mehr zu jagen.
Für diejenigen, die die Liste der Knotennamen und Parameternamen sehen möchten, haben wir die folgende CSV-Datei hochgeladen.
Die Abbildung wurde in Excel geöffnet. Jeder Knoten ist nach Kategorie, Knotenname und Knotenbezeichnung unterteilt.
Die Abbildung wurde in Excel geöffnet. Jeder Parameter ist in Kategorie, Knotenname, Knotenbezeichnung, Parametername und Parameterbezeichnung unterteilt.
Das Folgende ist eine Erklärung von Python. Es ist schwierig, alles zu schreiben, deshalb werde ich nur die wichtigsten Punkte erläutern.
Zuerst möchte ich die Version angeben, die ich vergleichen möchte, damit ich alle Versionen von Houdini erhalte, die ich installiert habe.
import os
hfs = os.getenv('HFS')
#C:/PROGRA~1/SIDEEF~1/HOUDIN~1.287
root = os.path.dirname(hfs)
versions = os.listdir(root)
#['Houdini 16.5.268', 'Houdini 17.0.376', 'Houdini 17.5.258', 'Houdini 17.5.360','Houdini 17.5.391', 'Houdini 18.0.287']
HOUDIN ~ 1.287
zurückgegeben, sodass ich es mit der folgenden Methode weggelassen habe.import hou
current_version = hou.applicationVersionString()
versions.remove('Houdini ' + current_version)
sel_version = hou.ui.selectFromList(
versions, exclusive=True, title='Select Compare Version',
column_header='Versions', width=240, height=240
)
if not sel_version:
return
version = versions[sel_version[0]]
version_path = '{}/{}'.format(root, version)
#C:/PROGRA~1/SIDEEF~1/Houdini 17.5.391
Sie müssen alle Knotentypen zum Vergleich abrufen.
Um alle Knotentypen abzurufen, verwenden Sie ** hou.nodeTypeCategories () **, um jede Kategorie einzugeben. Ein Wörterbuch mit dem Objekt ** hou.NodeTypeCategory ** im Namen und Wert wird zurückgegeben. Und das ** hou.NodeTypeCategory ** Objekt [** nodeTypes ](https: // www) Bei Ausführung der Funktion .sidefx.com / ja / docs / houdini / hom / hou / NodeTypeCategory.html # nodeTypes) ist der Schlüssel der Name des Knotentyps und der Wert [ hou.NodeType **](https: // www.sidefx.com/de/docs/houdini/hom/hou/NodeType.html) Ein Wörterbuch mit Objekten wird zurückgegeben.
Führen Sie beispielsweise den folgenden Code aus, um alle Knotentypnamen von SOP abzurufen.
import hou
categories = hou.nodeTypeCategories()
sop_category = categories['Sop']
sop_data = sop_category.nodeTypes()
sop_nodes = sop_data.keys()
Um alle Parameter abzurufen ** hou.NodeType ** Objekt ** parmTemplates () ** Durch Ausführen der Funktion werden im Grunde alle Parameter ** hou.parmTemplate ** Sie können das Objekt abrufen. Da die in ** Multiparm Block ** enthaltenen Parameter jedoch nicht enthalten sind, können Elemente wie ** Gruppenförderung **, deren Parameter in ** Multiparm Block ** enthalten sind, nicht abgerufen werden.
Um die in ** Multiparm Block ** enthaltenen Parameter abzurufen, können Sie sie mithilfe der unten gezeigten rekursiven Funktion abrufen.
def get_all_parm_templates(all_parms, node_type):
parms = node_type.parmTemplates()
for parm in parms:
if parm.type() == hou.parmTemplateType.Folder:
get_all_parm_templates(all_parms, parm)
elif parm.type() != hou.parmTemplateType.FolderSet:
all_parms.append(parm)
return all_parms
Rufen Sie auf der Grundlage der obigen Informationen alle Knotentypen und Parameter ab.
# -*- coding: utf-8 -*-
import hou
def get_all_parm_templates(all_parms, node_type):
parms = node_type.parmTemplates()
for parm in parms:
if parm.type() == hou.parmTemplateType.Folder:
get_all_parm_templates(all_parms, parm)
elif parm.type() != hou.parmTemplateType.FolderSet:
all_parms.append(parm)
return all_parms
def main():
node_data = {}
categories = hou.nodeTypeCategories()
for category_name, category in categories.items():
category_data = []
nodes = category.nodeTypes()
for node_name, node_type in nodes.items():
node_info = {}
node_info['node_name'] = node_name
node_info['node_label'] = node_type.description()
all_parms = get_all_parm_templates([], node_type)
node_info['parms'] = [parm.name() for parm in all_parms]
category_data.append(node_info)
node_data[category_name] = category_data
return node_data
Wenn Sie den obigen Code ausführen, wird ein Wörterbuch mit Knotennamen, Knotenbezeichnungen und Parameternamen für jede Kategorie zurückgegeben (siehe unten) (nur der PolySplitSop-Teil wird angezeigt).
"Sop": [
{
"node_label": "PolySplit",
"parms": [
"splitloc",
"pathtype",
"override",
"newt",
"updatenorms",
"close",
"tolerance"
],
"node_name": "polysplit"
},
Selbst wenn Sie dies ausführen, können Sie nur die Knoteninformationen der aktuell ausgeführten Version abrufen, nicht jedoch die Knoteninformationen der angegebenen Version.
Verwenden Sie ** Hython **, um die Knoteninformationen für die angegebene Version abzurufen. ** Hython ** ist eine ** Python-Shell ** in ** $ HFS / bin **, die für jede Version vorhanden ist. Da das ** hou ** -Modul beim Start automatisch geladen wird, können Sie die Houdini-eigene Verarbeitung ausführen, ohne ** Houdini zu starten. ** ** **
Um das Skript auf der angegebenen Version von ** Hython ** auszuführen, speichern Sie den Code in einer **. Py ** -Datei und verwenden Sie den ** Unterprozess **, um ihn im Argument ** Hython ** anzugeben. Ich werde.
import subprocess
from subprocess import PIPE
hython = 'Weg nach Hython'
script = 'Pfad des auszuführenden Skripts'
p = subprocess.Popen([hython, script], shell=True, stdout=PIPE, stderr=PIPE)
#Ruft den Rückgabewert aus dem Skript ab
stdout, stderr = p.communicate()
#Der zurückgegebene Wert ist eine Zeichenfolge. Konvertieren Sie ihn daher mit eval in ein Wörterbuch
node_data = eval(stdout)
Als ich dies tat, wurde jedoch nichts an ** stdout ** zurückgegeben, und die folgende Zeichenfolge wurde an ** stderr ** zurückgegeben.
'EnvControl: HOUDINI_USER_PREF_DIR missing __HVER__, ignored.\r\nTraceback (most rec
ent call last):\n File "<string>", line 8, in <module>\n File "C:/PROGRA~1/SIDEEF~
1/HOUDIN~1.287/houdini/python2.7libs\\hou.py", line 19, in <module>\n import _hou
\nImportError: DLL load failed: \x8ew\x92\xe8\x82\xb3\x82\xea\x82\xbd\x83v\x83\x8d\x
83V\x81[\x83W\x83\x83\x82\xaa\x8c\xa9\x82\xc2\x82\xa9\x82\xe8\x82\xdc\x82\xb9\x82\xf
1\x81B\nTraceback (most recent call last):\r\n File "D:\\create_update_node\\get_node_data.py", lin
e 2, in <module>\r\n import hou\r\n File "C:/PROGRA~1/SIDEEF~1/HOUDIN~1.287/houd
ini/python2.7libs\\hou.py", line 19, in <module>\r\n import _hou\r\nImportError:
DLL load failed: \x8ew\x92\xe8\x82\xb3\x82\xea\x82\xbd\x83v\x83\x8d\x83V\x81[\x83W\x
83\x83\x82\xaa\x8c\xa9\x82\xc2\x82\xa9\x82\xe8\x82\xdc\x82\xb9\x82\xf1\x81B\r\n'
Wenn man sich den Fehler ansieht, scheint der Import des ** hou ** -Moduls fehlgeschlagen zu sein.
Der Grund, warum ich den Fehler erhalte, ist, dass ** Hython ** beim Importieren des ** hou ** -Moduls zu ** $ HFS ** und ** $ HFS / houdini / python2.7libs ** wechselt. Mit anderen Worten, wenn Sie ** Hython ** von ** 18.0 ** ausführen, werden nur ** HFS ** und ** PYTHONPATH ** für ** 18.0 ** erkannt, sodass Sie einen Importfehler erhalten.
Um dies zu beheben, müssen Sie vor dem Ausführen von ** Hython ** den folgenden Code ausführen, um die Einstellungen für diese Version zu ändern (stellen Sie aus Sicherheitsgründen die ursprünglichen Einstellungen nach dem Ausführen von Hython wieder her). ..
import sys
#Überschreiben Sie mit dem Pfad der Vergleichsversion, die HFS erhalten hat
os.putenv('HFS') = version_path
#Da die DLL auch beim Import des hou-Moduls geladen wird, wird auch die Umgebungsvariable PATH neu geschrieben.
path = '{}/bin;{}'.format(version_path, os.getenv('PATH'))
os.putenv('PATH', path)
Der gesamte Code sieht so aus (er ist lang, also gefaltet). Die Skriptausführung ruft die Hauptfunktion auf.
python
# -*- coding: utf-8 -*-
import hou
import os
import subprocess
from subprocess import PIPE
from .get_node_data import get_all_parm_templates
def get_compare_version(hfs):
version_root = os.path.dirname(hfs)
versions = os.listdir(version_root)
current_version = 'Houdini ' + hou.applicationVersionString()
if current_version in versions:
versions.remove(current_version)
#UI-Optionswörterbuch
kwargs = {
'exclusive': True,
'title': 'Select Compare Version',
'column_header': 'Versions',
'width': 240,
'height': 240
}
#Listenansicht zur Auswahl der Version anzeigen
sel_version = hou.ui.selectFromList(versions, **kwargs)
if not sel_version:
return
version = versions[sel_version[0]]
return version
def get_env_from_version(version, hfs, pref_dir):
old_hfs = '{}/{}'.format(os.path.dirname(hfs), version)
old_pref_dir = '{}/{}'.format(
os.path.dirname(pref_dir),
'.'.join(version.replace('Houdini ', 'houdini').split('.')[:2])
)
return old_hfs, old_pref_dir
def set_base_env(path, hfs, pref_dir):
#Legen Sie Umgebungsvariablen und den Python-Pfad fest
os.putenv('PATH', path)
os.putenv('HFS', hfs)
os.putenv('HOUDINI_USER_PREF_DIR', pref_dir)
def get_old_node_data(old_hfs, old_pref_dir):
script_root = os.path.dirname(__file__)
script = os.path.normpath(script_root + "/get_node_data.py")
hython = os.path.normpath(old_hfs + '/bin/hython.exe')
#Übergeben Sie die erforderlichen Umgebungsvariablen und den Python-Pfad, bevor Sie sie an hython übergeben
path = '{}/bin;{}'.format(old_hfs, os.getenv('PATH'))
set_base_env(path, old_hfs, old_pref_dir)
#Führen Sie das Skript mit hython aus
p = subprocess.Popen([hython, script], shell=True, stdout=PIPE, stderr=PIPE)
#Ruft den Rückgabewert aus dem Skript ab
stdout, stderr = p.communicate()
if stderr:
hou.ui.displayMessage('Script Error', severity=hou.severityType.Error)
return
#Der zurückgegebene Wert ist eine Zeichenfolge. Konvertieren Sie ihn daher mit eval in ein Wörterbuch
old_node_data = eval(stdout)
return old_node_data
def get_node_info(node_name, node_label):
node_info = {}
node_info['Node Name'] = node_name
node_info['Node Label'] = node_label
return node_info
def compare(old_node_data):
new_node_data = {}
new_parm_node_data = {}
categories = hou.nodeTypeCategories()
for category, type_category in categories.items():
new_nodes = []
new_parm_nodes = []
nodes = type_category.nodeTypes()
old_nodes = old_node_data.get(category)
#Was tun, wenn die Kategorie selbst nicht vorhanden ist?
if not old_nodes:
for node_name, node_type in sorted(nodes.items()):
node_label = node_type.description()
node_info = get_node_info(node_name, node_label)
new_nodes.append(node_info)
if new_nodes:
new_node_data[category] = new_nodes
continue
#Wenn eine Kategorie vorhanden ist
old_node_names = [node_info['node_name'] for node_info in old_nodes]
for node_name, node_type in sorted(nodes.items()):
node_label = node_type.description()
node_info = get_node_info(node_name, node_label)
if node_name in old_node_names:
all_parms = get_all_parm_templates([], node_type)
index = old_node_names.index(node_name)
parm_sets = set(old_nodes[index]['parms'])
new_parms = [parm.name() for parm in all_parms if not parm.name() in parm_sets]
if new_parms:
node_info['parms'] = new_parms
new_parm_nodes.append(node_info)
else:
new_nodes.append(node_info)
if new_nodes:
new_node_data[category] = new_nodes
if new_parm_nodes:
new_parm_node_data[category] = new_parm_nodes
return new_node_data, new_parm_node_data
def create_nodes(node_data, root_node):
for category, nodes in node_data.items():
#Erstellen Sie einen übergeordneten Knoten gemäß der Kategorie zum Erstellen eines Knotens
if category == 'Object':
parent_node = root_node.createNode('subnet', category)
elif category == 'Driver':
parent_node = root_node.createNode('ropnet', category)
elif category == 'Sop':
parent_node = root_node.createNode('geo', category)
elif category == 'Vop':
parent_node = root_node.createNode('matnet', category)
elif not 'Net' in category:
try:
parent_node = root_node.createNode(
category.lower() + 'net', category, run_init_scripts=False)
except:
continue
else:
parent_node = root_node.createNode(category.lower(), category)
#Knoten erstellen
for node_info in nodes:
#Holen Sie sich den Namen des Knotens und erstellen Sie ihn
node_name = node_info['Node Name']
try:
new_node = parent_node.createNode(node_name)
except:
continue
#Parameter abrufen
parms = node_info.get('parms')
if not parms:
continue
#Setzen Sie den Ausdruck im Parameter
for parm_name in parms:
try:
if parm_name[-1] == '#':
parm_name = parm_name[:-1] + '1'
parm_tuple = new_node.parmTuple(parm_name)
if not parm_tuple:
continue
for parm in parm_tuple:
parm.setExpression('constant()')
except:
pass
#Knotenorganisation
parent_node.layoutChildren()
root_node.layoutChildren()
def create_new_nodes(new_node_data):
root_node = hou.node('/obj').createNode('subnet', 'NewNodes')
create_nodes(new_node_data, root_node)
def create_new_parm_nodes(new_parm_node_data):
root_node = hou.node('/obj').createNode('subnet', 'NewParmNodes')
create_nodes(new_parm_node_data, root_node)
def main():
hfs = os.getenv('HFS')
#Holen Sie sich die Version zum Vergleichen
version = get_compare_version(hfs)
if not version:
return
pref_dir = os.getenv('HOUDINI_USER_PREF_DIR')
path = os.getenv('PATH')
#Ruft Umgebungsvariablen für die zu vergleichende Version ab
old_hfs, old_pref_dir = get_env_from_version(
version, hfs, pref_dir)
#Abrufen von Knoteninformationen für die zu vergleichende Version
old_node_data = get_old_node_data(old_hfs, old_pref_dir)
if not old_node_data:
return
#Stellen Sie die für hython festgelegten Umgebungsvariablen wieder her
set_base_env(path, hfs, pref_dir)
#Abrufen von Knoteninformationen im Vergleich zu Knoten in der aktuellen Version
new_node_data, new_parm_node_data = compare(old_node_data)
#Erstellen Sie einen Knoten, der nur in der aktuellen Version vorhanden ist
create_new_nodes(new_node_data)
#Erstellen Sie einen Knoten mit Parametern, die in der aktuellen Version hinzugefügt wurden
create_new_parm_nodes(new_parm_node_data)
#Knoten organisieren
hou.node('/obj').layoutChildren()
So überprüfen Sie die Knoten, die in der neuen Version hinzugefügt und aktualisiert wurden. Mit diesem Skript können Sie den aktualisierten Knoten überprüfen, sobald eine neue Version herauskommt!
Wenn Sie Fehler oder unklare Punkte in dem Artikel haben, würde ich es begrüßen, wenn Sie sie aufschreiben könnten. Bis zum Ende Danke fürs Lesen.