#!/usr/bin/python # -*- coding: utf-8 -*- """ _____ _____ ______ _____ ______ / ____| __ \| ____| /\ / ____| ____|_ | | | |__) | |__ / \ | (___ | |__ _| |_ | | | _ /| __| / /\ \ \___ \| __|_ _| | |____| | \ \| |____ / ____ \ ____) | |____|_| \_____|_| \_\______/_/ \_\_____/|______| """ # import maya.cmds as mc import maya.api.OpenMaya as om # import copy # uses python maya 2 maya_useNewAPI = True ################# def cPhardEdgeIds(mesh): edgeIter = om.MItMeshEdge(mesh) ids = [] while not edgeIter.isDone(): if not edgeIter.isSmooth: ids.append(edgeIter.index()) edgeIter.next() return ids def cPcompToIds(compdata, cptyp): compDataFn = om.MFnComponentListData(compdata) # compDataFn ids = [] for i in range(compDataFn.length()): curcomp = compDataFn.get(i) if curcomp.hasFn(cptyp): sic = om.MFnSingleIndexedComponent(curcomp) for j in range(sic.elementCount): curIdx = sic.element(j) ids.append(curIdx) return ids def cPidsToComp(ids, cptyp): sic = om.MFnSingleIndexedComponent() sic.create(cptyp) # om.MFn.kMeshEdgeComponent sic.addElements(ids) compData = om.MFnComponentListData() compObj = compData.create() compData.add(sic.object()) return (sic.object(), compObj) def cPtransformMeshPoints(mesh, mat): meshFn = om.MFnMesh(mesh) pts = meshFn.getPoints() for pt in pts: pt *= mat meshFn.setPoints(pts) """ input: mesh output: componentlist """ MayaNodeT = om.MPxNode class CpCurveBevel(MayaNodeT): kNodeName = "creasePlusCurveBevel" kNodeId = om.MTypeId(0x1154) aCvs = None aOffset = None aSeg = None aOffsetFrac = None aInputCurve = None aOutput = None def __init__(self): super(CpCurveBevel, self).__init__() @classmethod def creator(cls): return cls() @classmethod def initialize(cls): nAttr = om.MFnNumericAttribute() tAttr = om.MFnTypedAttribute() cls.aCvs = tAttr.create("cvComponentList", "cvs", om.MFnComponentListData.kComponentList) cls.aOffset = nAttr.create("offset", "off", om.MFnNumericData.kFloat) nAttr.setMin(0) nAttr.default = 0.5 nAttr.keyable = True cls.aSeg = nAttr.create("segments", "seg", om.MFnNumericData.kInt) nAttr.setMin(1) nAttr.default = 1 nAttr.keyable = True cls.aOffsetFrac = nAttr.create("offsetAsFraction", "oaf", om.MFnNumericData.kBoolean) nAttr.default = False nAttr.keyable = True cls.aInputCurve = tAttr.create("inCurve", "inc", om.MFnData.kNurbsCurve) cls.aOutput = tAttr.create("outCurve", "out", om.MFnData.kNurbsCurve) tAttr.storable = False tAttr.writable = False MayaNodeT.addAttribute(cls.aCvs) MayaNodeT.addAttribute(cls.aOffset) MayaNodeT.addAttribute(cls.aSeg) MayaNodeT.addAttribute(cls.aOffsetFrac) MayaNodeT.addAttribute(cls.aInputCurve) MayaNodeT.addAttribute(cls.aOutput) MayaNodeT.attributeAffects(cls.aCvs, cls.aOutput) MayaNodeT.attributeAffects(cls.aOffset, cls.aOutput) MayaNodeT.attributeAffects(cls.aSeg, cls.aOutput) MayaNodeT.attributeAffects(cls.aOffsetFrac, cls.aOutput) MayaNodeT.attributeAffects(cls.aInputCurve, cls.aOutput) def setOutputToCopy(self, data): inCurveHandle = data.inputValue(CpCurveBevel.aInputCurve) outHandle = data.outputValue(CpCurveBevel.aOutput) outHandle.copy(inCurveHandle) outHandle.setClean() def compute(self, plug, data): if plug != CpCurveBevel.aOutput: return None inCurveHandle = data.inputValue(CpCurveBevel.aInputCurve) inCurve = inCurveHandle.asNurbsCurveTransformed() inCvsHandle = data.inputValue(CpCurveBevel.aCvs) compData = inCvsHandle.data() ids = cPcompToIds(compData, om.MFn.kCurveCVComponent) # inOffset = data.inputValue(CpCurveBevel.aOffset).asFloat() inSeg = data.inputValue(CpCurveBevel.aSeg).asInt() inFrac = data.inputValue(CpCurveBevel.aOffsetFrac).asBool() if len(ids) == 0 or inOffset == 0: self.setOutputToCopy(data) return curveFn = om.MFnNurbsCurve(inCurve) curveDegree = curveFn.degree curveForm = curveFn.form # curveKnots = curveFn.knots() curvePts = curveFn.cvPositions() # to be modified numcv = len(curvePts) # to be modified bevelParam = 1 / float(inSeg) bevelPts = [] ids.sort() for cvIdx in ids: mpos = om.MVector(curvePts[cvIdx]) if curveForm == curveFn.kPeriodic: lpos = om.MVector(curvePts[(cvIdx + numcv - (1 + curveDegree)) % (numcv - curveDegree)]) rpos = om.MVector(curvePts[(cvIdx + 1) % (numcv - curveDegree)]) else: lpos = om.MVector(curvePts[(cvIdx + numcv - 1) % numcv]) rpos = om.MVector(curvePts[(cvIdx + 1) % numcv]) lvec = lpos - mpos rvec = rpos - mpos lanchor = None ranchor = None if inFrac: lanchor = mpos + (inOffset * lvec) ranchor = mpos + (inOffset * rvec) else: lanchor = mpos + (inOffset * lvec.normal()) ranchor = mpos + (inOffset * rvec.normal()) bevelPts.append(lanchor) t = 1 * bevelParam for i in range(inSeg - 1): # (1-t)^2A+2t(1-t)B+t^2C res = (1 - t)**2 * lanchor + (2 * t * (1 - t) * mpos) + ( t**2 * ranchor) bevelPts.append(res) t += bevelParam bevelPts.append(ranchor) # i = len(bevelPts) - (inSeg + 1) ids.sort(reverse=True) for cvIdx in ids: curvePts[cvIdx] = bevelPts[i] curvePts[cvIdx + 1:cvIdx + 1] = bevelPts[i + 1:i + inSeg + 1] i -= (inSeg + 1) numcv = len(curvePts) if curveForm == curveFn.kPeriodic: curvePts[-curveDegree:] = curvePts[:curveDegree] if curveDegree == 1: knots = [float(i) for i in range(numcv)] else: knots = [None] * (numcv - curveDegree + (2 * curveDegree) - 1) if curveForm == curveFn.kPeriodic: knots[:curveDegree] = [ float(i) for i in reversed(range(0, -curveDegree, -1)) ] knots[curveDegree:] = [ float(i) for i in range(1, len(knots) - curveDegree + 1) ] else: knots[:curveDegree] = [float(0)] * curveDegree knots[-curveDegree:] = [float(numcv - curveDegree) ] * curveDegree knots[curveDegree:-curveDegree] = [ float(i) for i in range(1, len(knots) - (2 * curveDegree) + 1) ] curveDataFn = om.MFnNurbsCurveData() curveDataFn.create() knots = om.MDoubleArray(knots) curveFn.create( curvePts, knots, curveDegree, curveForm, False, False, parent=curveDataFn.object()) out = data.outputValue(CpCurveBevel.aOutput) out.setMObject(curveDataFn.object()) out.setClean() class CpCurveToPoly(MayaNodeT): kNodeName = "creasePlusCurveToPoly" kNodeId = om.MTypeId(0x12547) aCount = None aRevNorm = None aControlPts = None aInputCurve = None aOutput = None def __init__(self): super(CpCurveToPoly, self).__init__() @classmethod def creator(cls): return cls() @classmethod def initialize(cls): nAttr = om.MFnNumericAttribute() tAttr = om.MFnTypedAttribute() cls.aRevNorm = nAttr.create("reverse", "rev", om.MFnNumericData.kBoolean) nAttr.default = False nAttr.keyable = True cls.aCount = nAttr.create("count", "cnt", om.MFnNumericData.kInt) nAttr.setMin(3) nAttr.default = 12 nAttr.keyable = True cls.aControlPts = nAttr.create("controlPts", "cv", om.MFnNumericData.kBoolean) nAttr.default = True nAttr.keyable = True cls.aInputCurve = tAttr.create("inCurve", "inc", om.MFnData.kNurbsCurve) cls.aOutput = tAttr.create("outPoly", "out", om.MFnData.kMesh) tAttr.storable = False tAttr.writable = False MayaNodeT.addAttribute(cls.aRevNorm) MayaNodeT.addAttribute(cls.aCount) MayaNodeT.addAttribute(cls.aControlPts) MayaNodeT.addAttribute(cls.aInputCurve) MayaNodeT.addAttribute(cls.aOutput) MayaNodeT.attributeAffects(cls.aRevNorm, cls.aOutput) MayaNodeT.attributeAffects(cls.aCount, cls.aOutput) MayaNodeT.attributeAffects(cls.aControlPts, cls.aOutput) MayaNodeT.attributeAffects(cls.aInputCurve, cls.aOutput) def setOutputToNull(self, data): out = data.outputValue(CpCurveToPoly.aOutput) out.setMObject(om.MObject.kNullObj) out.setClean() def compute(self, plug, data): if plug != CpCurveToPoly.aOutput: return None reverseNormal = data.inputValue(CpCurveToPoly.aRevNorm).asBool() inCurveHandle = data.inputValue(CpCurveToPoly.aInputCurve) inCurve = inCurveHandle.asNurbsCurveTransformed() inCount = data.inputValue(CpCurveToPoly.aCount).asInt() # useCvs = data.inputValue(CpCurveToPoly.aControlPts).asBool() curveFn = om.MFnNurbsCurve(inCurve) curveForm = curveFn.form curveDegree = curveFn.degree polyPts = None meshDataFn = om.MFnMeshData() meshDataFn.create() if useCvs: if curveForm == curveFn.kPeriodic: polyPts = curveFn.cvPositions()[:-curveDegree] else: polyPts = curveFn.cvPositions() else: polyPts = [] domain = curveFn.knotDomain param = domain[1] / float(inCount) t = 0.0 for i in range(inCount): polyPts.append(curveFn.getPointAtParam(t)) t += param if reverseNormal: polyPts = [pt for pt in reversed(polyPts)] # create(vertices, polygonCounts, polygonConnects, uValues=None, vValues=None, parent=kNullObj) -> MObject meshFn = om.MFnMesh() meshFn.create( polyPts, [len(polyPts)], [i for i in range(len(polyPts))], parent=meshDataFn.object()) out = data.outputValue(CpCurveToPoly.aOutput) out.setMObject(meshDataFn.object()) out.setClean() class CpHeIds(MayaNodeT): kNodeName = "creasePlusBevelHe" kNodeId = om.MTypeId(0x1157) aForceComp = None aInputMesh = None aIds = None def __init__(self): super(CpHeIds, self).__init__() self.numVertices = 0 self.numPolygons = 0 self.numNormals = 0 self.dummycompute = False @classmethod def creator(cls): return cls() @classmethod def initialize(cls): tAttr = om.MFnTypedAttribute() nAttr = om.MFnNumericAttribute() cls.aForceComp = nAttr.create("forceCompute", "fc", om.MFnNumericData.kBoolean, 0) nAttr.default = False nAttr.keyable = True cls.aInputMesh = tAttr.create("inMesh", "i", om.MFnData.kMesh) cls.aIds = tAttr.create("componentList", "cl", om.MFnComponentListData.kComponentList) tAttr.storable = False tAttr.writable = False MayaNodeT.addAttribute(cls.aForceComp) MayaNodeT.addAttribute(cls.aInputMesh) MayaNodeT.addAttribute(cls.aIds) def attrToPlug(self, attr): return om.MPlug(self.thisMObject(), attr) def setDependentsDirty(self, plug, affect): if plug == CpHeIds.aForceComp: if self.dummycompute == False: self.dummycompute = True affect.append(self.attrToPlug(CpHeIds.aIds)) else: self.dummycompute = False elif plug == CpHeIds.aInputMesh: affect.append(self.attrToPlug(CpHeIds.aIds)) def compute(self, plug, data): if plug != CpHeIds.aIds: return None doingit = False data.inputValue(CpHeIds.aForceComp) inMeshHandle = data.inputValue(CpHeIds.aInputMesh) inmesh = inMeshHandle.asMesh() meshFn = om.MFnMesh(inmesh) if self.dummycompute == True: doingit = True elif (self.numVertices != meshFn.numVertices or self.numPolygons != meshFn.numPolygons or self.numNormals != meshFn.numNormals): doingit = True if doingit == True: heIds = cPhardEdgeIds(inmesh) compObj = cPidsToComp(heIds, om.MFn.kMeshEdgeComponent)[1] outIdsHandle = data.outputValue(CpHeIds.aIds) outIdsHandle.setMObject(compObj) outIdsHandle.setClean() if self.dummycompute == True: forceCompplug = self.attrToPlug(CpHeIds.aForceComp) forceCompplug.setBool(False) def initializePlugin(obj): mplugin = om.MFnPlugin(obj, "Baidhir Hidair", "1.0") nodeName = None try: nodeName = CpHeIds.kNodeName mplugin.registerNode(CpHeIds.kNodeName, CpHeIds.kNodeId, CpHeIds.creator, CpHeIds.initialize) nodeName = CpCurveBevel.kNodeName mplugin.registerNode(CpCurveBevel.kNodeName, CpCurveBevel.kNodeId, CpCurveBevel.creator, CpCurveBevel.initialize) nodeName = CpCurveToPoly.kNodeName mplugin.registerNode(CpCurveToPoly.kNodeName, CpCurveToPoly.kNodeId, CpCurveToPoly.creator, CpCurveToPoly.initialize) except: raise Exception('failed to register node: ' + nodeName) def uninitializePlugin(obj): mplugin = om.MFnPlugin(obj) nodeName = None try: nodeName = CpHeIds.kNodeName mplugin.deregisterNode(CpHeIds.kNodeId) nodeName = CpCurveBevel.kNodeName mplugin.deregisterNode(CpCurveBevel.kNodeId) nodeName = CpCurveToPoly.kNodeName mplugin.deregisterNode(CpCurveToPoly.kNodeId) except: raise Exception('failed to deregister node: ' + nodeName)