Maya API Vertex Colors


#1

#2

For those curious. This was the code in questioning.
I wrote my first custom maya api command, which will transfer vertexColors from one channel to the other, or from one colorSet to the other. Multiple channels/sets can be set.

This isn’t heavily tested yet, so if you want to use it use with caution :slight_smile:

If anyone sees something that I could improve let me know! I’m always happy for some feedback

import sys
import maya.OpenMaya as om
import maya.OpenMayaMPx as omMPx

commandName = "transferColors"

kObjectNameFlag = "-n"
kObjectNameLongFlag = "-name"

kObjectRedFlag = "-r"
kObjectRedLongFlag = "-colorR"
kObjectGreenFlag = "-g"
kObjectGreenLongFlag = "-colorG"
kObjectBlueFlag = "-b"
kObjectBlueLongFlag = "-colorB"
kObjectAlphaFlag = "-a"
kObjectAlphaLongFlag = "-alpha"
kObjectColorSet1Flag = "-s1"
kObjectColorSet1LongFlag = "-set1"
kObjectColorSet2Flag = "-s2"
kObjectColorSet2LongFlag = "-set2"

kHelpFlag = "-h"
kHelpLongFlag = "-help"
helpMessage = """This command is used to transfer vertex colors per channel and from one colorSet to the other.\n"""


class pluginCommand(omMPx.MPxCommand):
	"""This command is used to transfer vertex colors per channel and from one colorSet to the other.
	If no colorSet is specified the current one will be used.
	-r, -g, -b, -a = [index colorSet (0/1), index vertexColor (0/1/2/3)]
	set1 = colorSet
	set2 = colorSet"""
	def __init__(self):
		self.meshFn = None
		self.sourceColors = None
		self.polygons = []
		self.vertices = []

		self.r = None
		self.g = None
		self.b = None
		self.a = None
		self.set1 = None
		self.set2 = None

		omMPx.MPxCommand.__init__(self)

	def argumentParser(self, argList):
		syntax = self.syntax()
		parsedArguments = om.MArgDatabase(syntax, argList)

		# Get selection
		selection = om.MSelectionList()
		parsedArguments.getObjects(selection)
		component = om.MObject()
		mDagPath = om.MDagPath()
		selection.getDagPath(0, mDagPath, component)
		self.meshFn = om.MFnMesh(mDagPath)

		# Parse all flags
		if parsedArguments.isFlagSet(kHelpFlag):
			self.setResult(helpMessage)

		if parsedArguments.isFlagSet(kObjectRedFlag):
			idx1 = parsedArguments.flagArgumentInt(kObjectRedFlag, 0)
			idx2 = parsedArguments.flagArgumentInt(kObjectRedFlag, 1)
			if idx1 > 1 or idx2 > 3:
				return False
			self.r = [idx1, idx2]

		if parsedArguments.isFlagSet(kObjectGreenFlag):
			idx1 = parsedArguments.flagArgumentInt(kObjectGreenFlag, 0)
			idx2 = parsedArguments.flagArgumentInt(kObjectGreenFlag, 1)
			if idx1 > 1 or idx2 > 3:
				return False
			self.g = [idx1, idx2]

		if parsedArguments.isFlagSet(kObjectBlueFlag):
			idx1 = parsedArguments.flagArgumentInt(kObjectBlueFlag, 0)
			idx2 = parsedArguments.flagArgumentInt(kObjectBlueFlag, 1)
			if idx1 > 1 or idx2 > 3:
				return False
			self.b = [idx1, idx2]

		if parsedArguments.isFlagSet(kObjectAlphaFlag):
			idx1 = parsedArguments.flagArgumentInt(kObjectAlphaFlag, 0)
			idx2 = parsedArguments.flagArgumentInt(kObjectAlphaFlag, 1)
			if idx1 > 1 or idx2 > 3:
				return False
			self.a = [idx1, idx2]

		if parsedArguments.isFlagSet(kObjectColorSet1Flag):
			self.set1 = parsedArguments.flagArgumentString(kObjectColorSet1Flag, 0)

		if parsedArguments.isFlagSet(kObjectColorSet2Flag):
			self.set2 = parsedArguments.flagArgumentString(kObjectColorSet2Flag, 0)

		# If no colorSet is defined use current
		if not self.set1:
			self.set1 = self.meshFn.currentColorSetName()
		if not self.set2:
			self.set2 = self.meshFn.currentColorSetName()

		if not self.set1 and not self.set2:
			sys.stderr.write("Object has no colorSets.\n")
			return False

		# Get components
		if not component.isNull():
			if component.hasFn(om.MFn.kMeshPolygonComponent):
				self.polygons = om.MIntArray()
				om.MItMeshPolygon(mDagPath, component)
				face_itr = om.MItMeshPolygon(mDagPath, component)
				while not face_itr.isDone():
					self.polygons.append(face_itr.index())
					face_itr.next()

			elif component.hasFn(om.MFn.kMeshEdgeComponent):
				om.MItMeshEdge(mDagPath, component)
				edge_itr = om.MItMeshEdge(mDagPath, component)
				while not edge_itr.isDone():
					self.vertices.append(edge_itr.index(0))
					self.vertices.append(edge_itr.index(1))
					edge_itr.next()

			elif component.hasFn(om.MFn.kMeshVertComponent):
				self.vertices = om.MIntArray()
				om.MItMeshVertex(mDagPath, component)
				vert_itr = om.MItMeshVertex(mDagPath, component)
				while not vert_itr.isDone():
					self.vertices.append(vert_itr.index())
					vert_itr.next()
		return True

	def isUndoable(self):
		return True

	def doIt(self, argList):
		if self.argumentParser(argList) and (self.r or self.g or self.b or self.a):
			# get current colors and store it for undo
			self.sourceColors = om.MColorArray()
			self.meshFn.getFaceVertexColors(self.sourceColors, self.set1)

			self.redoIt()
		else:
			sys.stderr.write("No flag specified or setup incorrectly for '%s' command.\n" % commandName)

	def redoIt(self):
		meshFn = self.meshFn

		vertexCount = om.MIntArray()
		vertexList = om.MIntArray()
		meshFn.getVertices(vertexCount, vertexList)

		# Set2 colors
		sourceColors2 = om.MColorArray()
		meshFn.getFaceVertexColors(sourceColors2, self.set2, om.MColor(0, 0, 0, 1))

		# Set1 colors
		targetColors = om.MColorArray()
		meshFn.getFaceVertexColors(targetColors, self.set1, om.MColor(0, 0, 0, 1))

		# inner function to transfer colors from set2 to set1
		def transferColors(i):
			if self.r:
				if self.r[0] == 0:
					targetColors[i].r = self.sourceColors[i][self.r[1]]
				elif self.r[0] == 1:
					targetColors[i].r = sourceColors2[i][self.r[1]]
			if self.g:
				if self.g[0] == 0:
					targetColors[i].g = self.sourceColors[i][self.g[1]]
				elif self.g[0] == 1:
					targetColors[i].g = sourceColors2[i][self.g[1]]
			if self.b:
				if self.b[0] == 0:
					targetColors[i].b = self.sourceColors[i][self.b[1]]
				elif self.b[0] == 1:
					targetColors[i].b = sourceColors2[i][self.b[1]]
			if self.a:
				if self.a[0] == 0:
					targetColors[i].a = self.sourceColors[i][self.a[1]]
				elif self.a[0] == 1:
					targetColors[i].a = sourceColors2[i][self.a[1]]

		i = 0  # faceVertex index
		colorIds = om.MIntArray()
		for polygon in range(vertexCount.length()):
			for faceVert in range(vertexCount[polygon]):
				# Check if any components are selected
				if self.polygons or self.vertices:
					# Only transfer selected components
					if polygon in self.polygons or vertexList[i] in self.vertices:
						transferColors(i)
				else:
					transferColors(i)
				# Add faceVertex to colorIds
				colorIds.append(i)
				i += 1

		# Apply colors to all faceVertices
		meshFn.setColors(targetColors, self.set1)
		meshFn.assignColors(colorIds, self.set1)
		meshFn.setCurrentColorSetName(self.set1)

	def undoIt(self):
		meshFn = self.meshFn
		vertexCount = om.MIntArray()
		vertexList = om.MIntArray()

		meshFn.getVertices(vertexCount, vertexList)

		colorIds = om.MIntArray()
		for i in range(vertexList.length()):
			colorIds.append(i)

		# Apply old colors (pre doIt)
		meshFn.setColors(self.sourceColors, self.set1)
		meshFn.assignColors(colorIds, self.set1)


def syntaxCreator():
	syntax = om.MSyntax()

	# Add objects/selection to the syntax
	syntax.useSelectionAsDefault(True)
	syntax.setObjectType(om.MSyntax.kSelectionList)

	# Add all needed flags
	syntax.addFlag(kHelpFlag, kHelpLongFlag)
	syntax.addFlag(kObjectRedFlag, kObjectRedLongFlag, om.MSyntax.kUnsigned, om.MSyntax.kUnsigned)  # 2x om.MSynstax.kUnsigned to create a float2 parameter
	syntax.addFlag(kObjectGreenFlag, kObjectGreenLongFlag, om.MSyntax.kUnsigned, om.MSyntax.kUnsigned)
	syntax.addFlag(kObjectBlueFlag, kObjectBlueLongFlag, om.MSyntax.kUnsigned, om.MSyntax.kUnsigned)
	syntax.addFlag(kObjectAlphaFlag, kObjectAlphaLongFlag, om.MSyntax.kUnsigned, om.MSyntax.kUnsigned)
	syntax.addFlag(kObjectColorSet1Flag, kObjectColorSet1LongFlag, om.MSyntax.kString)
	syntax.addFlag(kObjectColorSet2Flag, kObjectColorSet2LongFlag, om.MSyntax.kString)
	return syntax


def cmdCreator():
	return omMPx.asMPxPtr(pluginCommand())


def initializePlugin(mobject):
	mplugin = omMPx.MFnPlugin(mobject, "Jeroen Heemskerk", "1.0")
	try:
		mplugin.registerCommand(commandName, cmdCreator, syntaxCreator)
	except:
		sys.stderr.write("Failed to register command: %s.\n" % commandName)


def uninitializePlugin(mobject):
	mplugin = omMPx.MFnPlugin(mobject)
	try:
		mplugin.deregisterCommand(commandName)
	except:
		sys.stderr.write("Failed to de-register command: %s.\n" % commandName)