Il est facile d'oublier le flux de travail d'implémentation de nœuds personnalisés dans Maya, je vais donc l'écrire comme rappel.
Cette fois, je présenterai un nœud avec une entrée / sortie simple, un nœud qui peut gérer des tableaux et un nœud qui peut gérer des attributs composés, et enfin l'utiliser pour créer un nœud qui génère les positions centrales de plusieurs points.
Pour les nœuds personnalisés (nœuds de dépendance, nœuds avec entrée / sortie), reportez-vous aux pages officielles suivantes. Bases du plugin Dependency Graph Plugin de graphique de dépendance
Au moins dans le script
Une fonction vide qui vous indique d'utiliser Maya Python API 2.0
Si vous définissez une fonction appelée maya_useNewAPI ()
, vous pouvez clairement indiquer que l'API 2.0 sera utilisée du côté Maya.
Points d'entrée / sortie du plugin
Vous devez appeler ʻinitializePlugin (mobject) et ʻuninitializePlugin (mobject)
lors du chargement et de la fermeture du plugin.
Ici, nous définissons ** nom de nœud **, ** ID de nœud **, ** les 4/5 fonctions suivantes **, ** type de nœud **, ** classification de nœud ** (voir ci-dessous).
Créez une fonction qui renvoie une instance du nœud
Fonction qui initialise les attributs du nœud
Classe de corps de nœud
Sera nécessaire.
L'exemple de nœud que j'ai réellement écrit est le suivant. C'est un nœud qui multiplie la valeur Float placée dans l'attribut d'entrée par la fonction sin et la sort à partir de l'attribut de sortie. Je vais expliquer un par un.
# -*- coding: utf-8 -*-
import maya.api.OpenMaya as om
import maya.api.OpenMayaUI as omui
import math, sys
# Maya API 2.Fonctions requises pour utiliser 0
def maya_useNewAPI():
pass
#Classe réelle
class sampleNode(om.MPxNode):
id = om.MTypeId(0x7f001) #Identifiant unique https://download.autodesk.com/us/maya/2011help/API/class_m_type_id.html
input = om.MObject()
output = om.MObject()
#Méthode pour renvoyer une instance
@staticmethod
def creator():
return sampleNode()
#Méthode appelée par Maya lors de l'initialisation
#Définir les attributs
@staticmethod
def initialize():
#Les attributs sont définis à l'aide de la méthode create d'une sous-classe de la classe MFnAttribute.
nAttr = om.MFnNumericAttribute()
sampleNode.input = nAttr.create(
'input', 'i', om.MFnNumericData.kFloat, 0.0)
nAttr.storable = True
nAttr.writable = True
nAttr = om.MFnNumericAttribute()
sampleNode.output = nAttr.create('output', 'o', om.MFnNumericData.kFloat, 0.0)
nAttr.storable = True
nAttr.writable = True
#Après avoir défini, exécutez addAttribute de MPxNode
sampleNode.addAttribute(sampleNode.input)
sampleNode.addAttribute(sampleNode.output)
#Définissez également la sortie à recalculer lorsque l'entrée est modifiée.
sampleNode.attributeAffects( sampleNode.input, sampleNode.output)
#Le constructeur appelle le constructeur parent
def __init__(self):
om.MPxNode.__init__(self)
#Une méthode appelée par Maya lorsque la valeur d'un attribut est calculée
def compute(self, plug, dataBlock):
if(plug == sampleNode.output):
dataHandle = dataBlock.inputValue(sampleNode.input)
inputFloat = dataHandle.asFloat()
result = math.sin(inputFloat) * 10.0
outputHandle = dataBlock.outputValue(sampleNode.output)
outputHandle.setFloat(result)
dataBlock.setClean(plug)
# http://help.autodesk.com/view/MAYAUL/2016/ENU/
# api1.0 signifie MStatus sauf si vous nous dites explicitement de ne pas traiter la fiche.kUnknownParameter n'est pas renvoyé
# api2.À 0, il n'y a pas de MStatus en premier lieu, vous pouvez donc l'ignorer.
#Une fonction appelée par Maya qui enregistre un nouveau nœud
def initializePlugin(obj):
mplugin = om.MFnPlugin(obj)
try:
mplugin.registerNode('sampleNode', sampleNode.id, sampleNode.creator,
sampleNode.initialize, om.MPxNode.kDependNode)
except:
sys.stderr.write('Faled to register node: %s' % 'sampleNode')
raise
#Fonctions appelées par Maya lors de la sortie du plug-in
def uninitializePlugin(mobject):
mplugin = om.MFnPlugin(mobject)
try:
mplugin.deregisterNode(sampleNode.id)
except:
sys.stderr.write('Faled to uninitialize node: %s' % 'sampleNode')
raise
Premier de la définition de classe
class sampleNode(om.MPxNode):
id = om.MTypeId(0x7f001) #Identifiant unique https://download.autodesk.com/us/maya/2011help/API/class_m_type_id.html
input = om.MObject()
output = om.MObject()
Décidez de l'ID du plug-in. Pour plus de détails, consultez site Autodesk, mais vous pouvez généralement utiliser n'importe quelle valeur comprise entre 0x00000 et 0x7ffff. Je vais.
Et j'ai préparé les attributs d'entrée et de sortie en tant que champ de classe ʻintput ʻoutput
.
#Méthode pour renvoyer une instance
@staticmethod
def creator():
return sampleNode()
Une fonction qui crée une instance d'un nœud. Vous pouvez l'écrire en dehors de la classe, mais cette fois je l'ai écrit en tant que méthode statique de la classe.
#Méthode appelée par Maya lors de l'initialisation
#Définir les attributs
@staticmethod
def initialize():
#Les attributs sont définis à l'aide de la méthode create d'une sous-classe de la classe MFnAttribute.
nAttr = om.MFnNumericAttribute()
sampleNode.input = nAttr.create(
'input', 'i', om.MFnNumericData.kFloat, 0.0)
nAttr.storable = True
nAttr.writable = True
nAttr = om.MFnNumericAttribute()
sampleNode.output = nAttr.create('output', 'o', om.MFnNumericData.kFloat, 0.0)
nAttr.storable = True
nAttr.writable = True
#Après avoir défini, exécutez addAttribute de MPxNode
sampleNode.addAttribute(sampleNode.input)
sampleNode.addAttribute(sampleNode.output)
#Définissez également la sortie à recalculer lorsque l'entrée est modifiée.
sampleNode.attributeAffects( sampleNode.input, sampleNode.output)
C'est la partie correspondant à "4. Fonctions qui initialisent les attributs de nœud" dans la liste précédente. Vous pouvez l'écrire en dehors de la classe, mais c'est encombré, donc je l'ai écrit comme une méthode statique.
Les attributs sont définis en utilisant les sous-classes appropriées de la classe MFnAttribute
. Cette fois, c'est une valeur Float, donc j'utilise MFnNumericAttribute
. Les valeurs flottantes tridimensionnelles (coordonnées, etc.) et les valeurs booléennes sont également ce MFnNumericAttribute
. Vous pouvez trouver l'angle, la distance et le temps à partir de MFnUnitAttribute
, la matrice de MFnMatrixAttribute
, et les autres à partir de la référence ci-dessous.
MFnAttribute Class Reference
OpenMaya.MFnAttribute Class Reference
Spécifiez le nom, l'abréviation, le type et la valeur initiale de l'attribut avec nAttr.create
.
Si nAttr.storable
écrit la valeur de l'attribut dans le fichier de sauvegarde. Il existe d'autres propriétés telles que «inscriptible» et «lisible», alors définissez-les correctement.
sampleNode.addAttribute (sampleNode.input)
Ajoute l'attribut créé au nœud.
sampleNode.attributeAffects (sampleNode.input, sampleNode.output)
Lorsque la valeur de l'attribut d'entrée change, l'attribut de sortie sera mis à jour.
#Une méthode appelée par Maya lorsque la valeur d'un attribut est calculée
def compute(self, plug, dataBlock):
if(plug == sampleNode.output):
dataHandle = dataBlock.inputValue(sampleNode.input)
inputFloat = dataHandle.asFloat()
result = math.sin(inputFloat) * 10.0
outputHandle = dataBlock.outputValue(sampleNode.output)
outputHandle.setFloat(result)
dataBlock.setClean(plug)
La méthode de calcul est la méthode appelée lorsque le calcul est effectué. Ce nœud calcule Sin. La valeur est transmise sous forme de plug. Pour plus d'informations sur les plugs, accédez à l'aide d'Autodesk (https://help.autodesk.com/view/MAYAUL/2016/JPN/?guid=__files_Dependency_graph_plugins_Attributes_and_plugs_htm). C'est long car il faut un handle du DataBlock pour obtenir l'entrée et l'affecter à la sortie, mais il s'agit en fait de calculer simplement la fonction Sin.
#Une fonction appelée par Maya qui enregistre un nouveau nœud
def initializePlugin(obj):
mplugin = om.MFnPlugin(obj)
try:
mplugin.registerNode('sampleNode', sampleNode.id, sampleNode.creator,
sampleNode.initialize, om.MPxNode.kDependNode)
except:
sys.stderr.write('Faled to register node: %s' % 'sampleNode')
raise
Un point d'entrée en dehors de la classe. Spécifiez le nom et l'ID du nœud, la méthode d'instance définie dans la classe et le type de nœud.
Chargez le script que vous avez créé à partir du gestionnaire de plugins de Maya.
Créez un nœud avec cmds.createNode ('sampleNode')
ou cmds.shadingNode ('sampleNode', asUtility = True)
dans la ligne de commande ou l'éditeur de script de Maya. Si vous l'avez créé avec ce dernier, votre propre nœud sera affiché dans l'onglet "Utilitaires" de la fenêtre hypershade.
Il existe deux méthodes, l'une consiste à connecter les données du tableau au plug en tant qu'attribut, et l'autre à utiliser le ** plug array ** dans lequel le plug lui-même est un tableau.
Modifiez la définition d'attribut dans la méthode ʻinitializeplus tôt comme suit.
nAttr.array = True est ok, mais vous pouvez utiliser
-nextAvailable avec la commande
connectAttr en définissant
nAttr.indexMatters = False` sur False. Au contraire, s'il vaut True, il semble que l'index à insérer doive être spécifié.
@staticmethod
def initialize():
nAttr = om.MFnNumericAttribute()
sampleArrayNode.input = nAttr.create(
'input', 'i', om.MFnNumericData.kFloat, 0.0)
nAttr.storable = True
nAttr.writable = True
nAttr.readable = True
nAttr.array = True #ajouter à
nAttr.indexMatters = False #ajouter à
Ensuite, la méthode compute
qui gère le calcul réel. Cette fois, le processus consiste à sortir la valeur totale du tableau d'entrée.
def compute(self, plug, dataBlock):
arrayDataHandle = dataBlock.inputArrayValue(
sampleArrayNode.input
)
sum = 0
while not arrayDataHandle.isDone():
handle = arrayDataHandle.inputValue()
v = handle.asFloat()
sum += v
arrayDataHandle.next()
outhandle = dataBlock.outputValue( sampleArrayNode.output )
outhandle.setFloat(sum)
dataBlock.setClean(plug)
Lorsque vous utilisez un plug-in de tableau, récupérez le MArrayDataHandle
une fois avec ʻinputArrayValue au lieu de ʻinputValue
.
Puisqu'il s'agit d'un itérateur, avancez l'itérateur avec next ()
ou jumpToLogicalElement ()
et obtenez la valeur de l'élément du tableau avec ʻarrayDataHandle.inputValue () `. Après cela, il est converti en valeur numérique et calculé de la même manière qu'une fiche normale.
↑ La constante 1 + 2 + 3 + 4 = 10 a été calculée correctement.
Un attribut composite est une collection de plusieurs attributs. Attributs dynamiques complexes Dans cet exemple, les «coordonnées et poids» sont utilisés comme attributs composés, et ils sont utilisés comme connecteurs de tableau.
Cela ressemble à l'image ci-dessous sur l'éditeur de nœuds. La mise en œuvre de la partie classe est la suivante. Les points d'entrée, etc. sont les mêmes que le code précédent (omis).
class sampleArrayNode(om.MPxNode):
#Identifiant unique https://download.autodesk.com/us/maya/2011help/API/class_m_type_id.html
id = om.MTypeId(0x7f011)
input = om.MObject()
output = om.MObject()
#Attributs enfants
position = om.MObject()
weight = om.MObject()
#Méthode pour renvoyer une instance
@staticmethod
def creator():
return sampleArrayNode()
#Méthode appelée par Maya lors de l'initialisation
#Définir les attributs
@staticmethod
def initialize():
#Attributs enfants
#Coordonner
nAttr = om.MFnNumericAttribute()
sampleArrayNode.position = nAttr.create(
'position', 'pos', om.MFnNumericData.k3Float, 0
)
nAttr.readable = True
#poids
nAttr = om.MFnNumericAttribute()
sampleArrayNode.weight = nAttr.create(
'weight', 'w', om.MFnNumericData.kFloat, 1
)
nAttr.readable = True
nAttr.setMax(1) # Min,Max peut également être spécifié
nAttr.setMin(0)
#Attributs composites
nAttr = om.MFnCompoundAttribute()
sampleArrayNode.input = nAttr.create(
'input', 'i')
nAttr.readable = True
nAttr.array = True
nAttr.indexMatters = False
nAttr.addChild(sampleArrayNode.position)
nAttr.addChild(sampleArrayNode.weight)
#La sortie est les coordonnées (3D Float) cette fois
nAttr = om.MFnNumericAttribute()
sampleArrayNode.output = nAttr.create(
'output', 'o', om.MFnNumericData.k3Float)
nAttr.storable = True
nAttr.writable = True
nAttr.readable = True
#Après avoir défini, exécutez addAttribute de MPxNode
sampleArrayNode.addAttribute(sampleArrayNode.input)
sampleArrayNode.addAttribute(sampleArrayNode.output)
#Définissez également la sortie à recalculer lorsque l'entrée est modifiée.
sampleArrayNode.attributeAffects(
sampleArrayNode.input, sampleArrayNode.output)
#Le constructeur appelle le constructeur parent
def __init__(self):
om.MPxNode.__init__(self)
#Une méthode appelée par Maya lorsque la valeur d'un attribut est calculée
def compute(self, plug, dataBlock):
arrayDataHandle = dataBlock.inputArrayValue(
sampleArrayNode.input
)
sumX = 0
sumY = 0
sumZ = 0
num = len(arrayDataHandle)
while not arrayDataHandle.isDone():
#Poignée de données d'attribut composite
dataHandle = arrayDataHandle.inputValue()
# .Vous pouvez obtenir des attributs enfants avec child
childHandle = dataHandle.child(
sampleArrayNode.position
)
pos = childHandle.asFloat3()
childHandle = dataHandle.child(
sampleArrayNode.weight
)
w = childHandle.asFloat()
sumX += pos[0] * w
sumY += pos[1] * w
sumZ += pos[2] * w
arrayDataHandle.next()
outhandle = dataBlock.outputValue(sampleArrayNode.output)
if(num != 0):
outhandle.set3Float(sumX / num, sumY / num, sumZ / num)
else:
outhandle.set3Float(0, 0, 0)
dataBlock.setClean(plug)
# http://help.autodesk.com/view/MAYAUL/2016/ENU/
# api1.0 signifie MStatus sauf si vous nous dites explicitement de ne pas traiter la fiche.kUnknownParameter n'est pas renvoyé
# api2.À 0, il n'y a pas de MStatus en premier lieu, vous pouvez donc l'ignorer.
#Une fonction appelée par Maya qui enregistre un nouveau nœud
Ce qui a changé, c'est que les variables «position» et «poids» sont préparées comme les champs de la classe. Comme ceux-ci sont utilisés comme attributs enfants d'attributs composés, ils sont définis dans la méthode ʻinitialize de la même manière que les attributs normaux. L'attribut composite qui les rassemble est ʻinput
.
#Attributs composites
nAttr = om.MFnCompoundAttribute()
sampleArrayNode.input = nAttr.create(
'input', 'i')
nAttr.readable = True
nAttr.array = True
nAttr.indexMatters = False
nAttr.addChild(sampleArrayNode.position) #← C'est le point
nAttr.addChild(sampleArrayNode.weight)
La différence avec les attributs normaux est que la classe de l'attribut est «MFnCompoundAttribute» et que l'attribut enfant défini ci-dessus dans «.addChild» est ajouté.
Pour utiliser des attributs composés dans la méthode de calcul
#Poignée de données d'attribut composite
dataHandle = arrayDataHandle.inputValue()
# .Vous pouvez obtenir des attributs enfants avec child
childHandle = dataHandle.child(
sampleArrayNode.position
)
pos = childHandle.asFloat3()
childHandle = dataHandle.child(
sampleArrayNode.weight
)
w = childHandle.asFloat()
Utilisez la méthode .child
du handle de données d'attribut composite pour obtenir et accéder au handle de données d'attribut enfant.
Lorsque vous utilisez réellement le nœud créé, il ressemble à ceci. Connectez les positions de plusieurs objets à un nœud. Essayez de connecter la sortie au localisateur. Le localisateur s'est déplacé vers le centre de la sphère, du cône et du cube. Cette fois, j'ai ajouté une valeur de poids en plus des coordonnées en tant qu'attribut composé, alors utilisons-la. Si vous abaissez le poids de la sphère ... L'influence de la sphère a disparu et le localisateur s'est déplacé vers le centre du cône et du cube.
Recommended Posts