1##-*****************************************************************************
2##
3## Copyright (c) 2009-2011,
4##  Sony Pictures Imageworks, Inc. and
5##  Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
6##
7## All rights reserved.
8##
9## Redistribution and use in source and binary forms, with or without
10## modification, are permitted provided that the following conditions are
11## met:
12## *       Redistributions of source code must retain the above copyright
13## notice, this list of conditions and the following disclaimer.
14## *       Redistributions in binary form must reproduce the above
15## copyright notice, this list of conditions and the following disclaimer
16## in the documentation and/or other materials provided with the
17## distribution.
18## *       Neither the name of Sony Pictures Imageworks, nor
19## Industrial Light & Magic nor the names of their contributors may be used
20## to endorse or promote products derived from this software without specific
21## prior written permission.
22##
23## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34##
35##-*****************************************************************************
36
37from maya import cmds as MayaCmds
38import maya.OpenMaya as OpenMaya
39import os
40import math
41
42# adds the current working directory so tools don't get confused about where we
43# are storing files
44def expandFileName(name):
45    return os.getcwd() + os.path.sep + name
46
47# compare the two floating point values
48def floatDiff(val1, val2, tolerance):
49    diff = math.fabs(val1 - val2)
50    if diff < math.pow(10, -tolerance):
51        return True
52    return False
53
54# function that returns a node object given a name
55def getObjFromName(nodeName):
56    selectionList = OpenMaya.MSelectionList()
57    selectionList.add( nodeName )
58    obj = OpenMaya.MObject()
59    selectionList.getDependNode(0, obj)
60    return obj
61
62# function that finds a plug given a node object and plug name
63def getPlugFromName(attrName, nodeObj):
64    fnDepNode = OpenMaya.MFnDependencyNode(nodeObj)
65    attrObj = fnDepNode.attribute(attrName)
66    plug = OpenMaya.MPlug(nodeObj, attrObj)
67    return plug
68
69# meaning of return value:
70#   0 if array1 = array2
71#   1 if array1 and array2 are of the same length, array1[i] == array2[i] for 0<=i<m<len, and array1[m] < array2[m]
72#  -1 if array1 and array2 are of the same length, array1[i] == array2[i] for 0<=i<m<len, and array1[m] > array2[m]
73#   2 if array1.length() < array2.length()
74#  -2 if array1.length() > array2.length()
75def compareArray(array1, array2):
76    len1 = array1.length()
77    len2 = array2.length()
78    if len1 > len2 : return -2
79    if len1 < len2 : return  2
80    for i in range(0, len1):
81        if array1[i] < array2[i] :
82            return 1
83        if array1[i] > array2[i] :
84            return -1
85    return 0
86
87# return True if the two point arrays are exactly the same
88def comparePointArray(array1, array2):
89    len1 = array1.length()
90    len2 = array2.length()
91    if len1 != len2 :
92        return False
93    for i in range(0, len1):
94        if not array1[i].isEquivalent(array2[i], 1e-6):
95            return False
96    return True
97
98# return True if the two meshes are identical
99def compareMesh( nodeName1, nodeName2 ):
100
101    # basic error checking
102    obj1 = getObjFromName(nodeName1)
103    if not obj1.hasFn(OpenMaya.MFn.kMesh):
104        return False
105    obj2 = getObjFromName(nodeName2)
106    if not obj2.hasFn(OpenMaya.MFn.kMesh):
107        return False
108
109    polyIt1 = OpenMaya.MItMeshPolygon( obj1 )
110    polyIt2 = OpenMaya.MItMeshPolygon( obj2 )
111
112    if polyIt1.count() != polyIt2.count():
113        return False
114
115    if polyIt1.polygonVertexCount() != polyIt2.polygonVertexCount():
116        return False
117
118    vertices1 = OpenMaya.MIntArray()
119    vertices2 = OpenMaya.MIntArray()
120    pointArray1 = OpenMaya.MPointArray()
121    pointArray2 = OpenMaya.MPointArray()
122
123    while  polyIt1.isDone()==False and polyIt2.isDone()==False :
124
125        # compare vertex indices
126        polyIt1.getVertices(vertices1)
127        polyIt2.getVertices(vertices2)
128        if compareArray(vertices1, vertices2) != 0:
129            return False
130
131        # compare vertex positions
132        polyIt1.getPoints(pointArray1)
133        polyIt2.getPoints(pointArray2)
134        if not comparePointArray( pointArray1, pointArray2 ):
135            return False
136
137        polyIt1.next()
138        polyIt2.next()
139
140    if polyIt1.isDone() and polyIt2.isDone() :
141        return True
142
143    return False
144
145# return True if the two Nurbs Surfaces are identical
146def compareNurbsSurface(nodeName1, nodeName2):
147
148    # basic error checking
149    obj1 = getObjFromName(nodeName1)
150    if not obj1.hasFn(OpenMaya.MFn.kNurbsSurface):
151        return False
152    obj2 = getObjFromName(nodeName2)
153    if not obj2.hasFn(OpenMaya.MFn.kNurbsSurface):
154        return False
155
156    fn1 = OpenMaya.MFnNurbsSurface(obj1)
157    fn2 = OpenMaya.MFnNurbsSurface(obj2)
158
159    # degree
160    if fn1.degreeU() != fn2.degreeU():
161        return False
162    if fn1.degreeV() != fn2.degreeV():
163        return False
164
165    # span
166    if fn1.numSpansInU() != fn2.numSpansInU():
167        return False
168    if fn1.numSpansInV() != fn2.numSpansInV():
169        return False
170
171    # form
172    if fn1.formInU() != fn2.formInU():
173        return False
174    if fn1.formInV() != fn2.formInV():
175        return False
176
177    # control points
178    if fn1.numCVsInU() != fn2.numCVsInU():
179        return False
180    if fn1.numCVsInV() != fn2.numCVsInV():
181        return False
182
183    cv1 = OpenMaya.MPointArray()
184    fn1.getCVs(cv1)
185    cv2 = OpenMaya.MPointArray()
186    fn2.getCVs(cv2)
187    if not comparePointArray(cv1, cv2):
188        return False
189
190    # knots
191    if fn1.numKnotsInU() != fn2.numKnotsInU():
192        return False
193    if fn1.numKnotsInV() != fn2.numKnotsInV():
194        return False
195
196    knotsU1 = OpenMaya.MDoubleArray()
197    fn1.getKnotsInU(knotsU1)
198    knotsV1 = OpenMaya.MDoubleArray()
199    fn1.getKnotsInV(knotsV1)
200    knotsU2 = OpenMaya.MDoubleArray()
201    fn2.getKnotsInU(knotsU2)
202    knotsV2 = OpenMaya.MDoubleArray()
203    fn2.getKnotsInV(knotsV2)
204
205    if compareArray( knotsU1, knotsU2 ) != 0:
206        return False
207
208    if compareArray( knotsV1, knotsV2 ) != 0:
209        return False
210
211    # trim curves
212    if fn1.isTrimmedSurface() != fn2.isTrimmedSurface():
213        return False
214
215    # may need to add more trim checks
216
217    return True
218
219
220# return True if the two locators are idential
221def compareLocator(nodeName1, nodeName2):
222
223    # basic error checking
224    obj1 = getObjFromName(nodeName1)
225    if not obj1.hasFn(OpenMaya.MFn.kLocator):
226        return False
227
228    obj2 = getObjFromName(nodeName2)
229    if not obj2.hasFn(OpenMaya.MFn.kLocator):
230        return False
231
232    if not floatDiff(MayaCmds.getAttr(nodeName1+'.localPositionX'),
233        MayaCmds.getAttr(nodeName2+'.localPositionX'), 4):
234        return False
235
236    if not floatDiff(MayaCmds.getAttr(nodeName1+'.localPositionY'),
237        MayaCmds.getAttr(nodeName2+'.localPositionY'), 4):
238        return False
239
240    if not floatDiff(MayaCmds.getAttr(nodeName1+'.localPositionZ'),
241        MayaCmds.getAttr(nodeName2+'.localPositionZ'), 4):
242        return False
243
244    if not floatDiff(MayaCmds.getAttr(nodeName1+'.localScaleX'),
245        MayaCmds.getAttr(nodeName2+'.localScaleX'), 4):
246        return False
247
248    if not floatDiff(MayaCmds.getAttr(nodeName1+'.localScaleY'),
249        MayaCmds.getAttr(nodeName2+'.localScaleY'), 4):
250        return False
251
252    if not floatDiff(MayaCmds.getAttr(nodeName1+'.localScaleZ'),
253        MayaCmds.getAttr(nodeName2+'.localScaleZ'), 4):
254        return False
255
256    return True
257
258
259# return True if the two cameras are identical
260def compareCamera( nodeName1, nodeName2 ):
261
262    # basic error checking
263    obj1 = getObjFromName(nodeName1)
264    if not obj1.hasFn(OpenMaya.MFn.kCamera):
265        return False
266
267    obj2 = getObjFromName(nodeName2)
268    if not obj2.hasFn(OpenMaya.MFn.kCamera):
269        return False
270
271    fn1 = OpenMaya.MFnCamera( obj1 )
272    fn2 = OpenMaya.MFnCamera( obj2 )
273
274    if fn1.filmFit() != fn2.filmFit():
275        print "differ in filmFit"
276        return False
277
278    if not floatDiff(fn1.filmFitOffset(), fn2.filmFitOffset(), 4):
279        print "differ in filmFitOffset"
280        return False
281
282    if fn1.isOrtho() != fn2.isOrtho():
283        print "differ in isOrtho"
284        return False
285
286    if not floatDiff(fn1.orthoWidth(), fn2.orthoWidth(), 4):
287        print "differ in orthoWidth"
288        return False
289
290    if not floatDiff(fn1.focalLength(), fn2.focalLength(), 4):
291        print "differ in focalLength"
292        return False
293
294    if not floatDiff(fn1.lensSqueezeRatio(), fn2.lensSqueezeRatio(), 4):
295        print "differ in lensSqueezeRatio"
296        return False
297
298    if not floatDiff(fn1.cameraScale(), fn2.cameraScale(), 4):
299        print "differ in cameraScale"
300        return False
301
302    if not floatDiff(fn1.horizontalFilmAperture(),
303        fn2.horizontalFilmAperture(), 4):
304        print "differ in horizontalFilmAperture"
305        return False
306
307    if not floatDiff(fn1.verticalFilmAperture(), fn2.verticalFilmAperture(), 4):
308        print "differ in verticalFilmAperture"
309        return False
310
311    if not floatDiff(fn1.horizontalFilmOffset(), fn2.horizontalFilmOffset(), 4):
312        print "differ in horizontalFilmOffset"
313        return False
314
315    if not floatDiff(fn1.verticalFilmOffset(), fn2.verticalFilmOffset(), 4):
316        print "differ in verticalFilmOffset"
317        return False
318
319    if not floatDiff(fn1.overscan(), fn2.overscan(), 4):
320        print "differ in overscan"
321        return False
322
323    if not floatDiff(fn1.nearClippingPlane(), fn2.nearClippingPlane(), 4):
324        print "differ in nearClippingPlane"
325        return False
326
327    if not floatDiff(fn1.farClippingPlane(), fn2.farClippingPlane(), 4):
328        print "differ in farClippingPlane"
329        return False
330
331    if not floatDiff(fn1.preScale(), fn2.preScale(), 4):
332        print "differ in preScale"
333        return False
334
335    if not floatDiff(fn1.postScale(), fn2.postScale(), 4):
336        print "differ in postScale"
337        return False
338
339    if not floatDiff(fn1.filmTranslateH(), fn2.filmTranslateH(), 4):
340        print "differ in filmTranslateH"
341        return False
342
343    if not floatDiff(fn1.filmTranslateV(), fn2.filmTranslateV(), 4):
344        print "differ in filmTranslateV"
345        return False
346
347    if not floatDiff(fn1.horizontalRollPivot(), fn2.horizontalRollPivot(), 4):
348        print "differ in horizontalRollPivot"
349        return False
350
351    if not floatDiff(fn1.verticalRollPivot(), fn2.verticalRollPivot(), 4):
352        print "differ in verticalRollPivot"
353        return False
354
355    if fn1.filmRollOrder() != fn2.filmRollOrder():
356        print "differ in filmRollOrder"
357        return False
358
359    if not floatDiff(fn1.filmRollValue(), fn2.filmRollValue(), 4):
360        print "differ in filmRollValue"
361        return False
362
363    if not floatDiff(fn1.fStop(), fn2.fStop(), 4):
364        print "differ in fStop"
365        return False
366
367    if not floatDiff(fn1.focusDistance(), fn2.focusDistance(), 4,):
368        print "differ in focusDistance"
369        return False
370
371    if not floatDiff(fn1.shutterAngle(), fn2.shutterAngle(), 4):
372        print "differ in shutterAngle"
373        return False
374
375    if fn1.usePivotAsLocalSpace() != fn2.usePivotAsLocalSpace():
376        print "differ in usePivotAsLocalSpace"
377        return False
378
379    if fn1.tumblePivot() != fn2.tumblePivot():
380        print "differ in tumblePivot"
381        return False
382
383    return True
384
385# return True if the two Nurbs curves are identical
386def compareNurbsCurve(nodeName1, nodeName2):
387    # basic error checking
388    obj1 = getObjFromName(nodeName1)
389    if not obj1.hasFn(OpenMaya.MFn.kNurbsCurve):
390        print nodeName1, "not a curve."
391        return False
392
393    obj2 = getObjFromName(nodeName2)
394    if not obj2.hasFn(OpenMaya.MFn.kNurbsCurve):
395        print nodeName2, "not a curve."
396        return False
397
398    fn1 = OpenMaya.MFnNurbsCurve(obj1)
399    fn2 = OpenMaya.MFnNurbsCurve(obj2)
400
401    if fn1.degree() != fn2.degree():
402        print nodeName1, nodeName2, "degrees differ."
403        return False
404
405    if fn1.numCVs() != fn2.numCVs():
406        print nodeName1, nodeName2, "numCVs differ."
407        return False
408
409    if fn1.numSpans() != fn2.numSpans():
410        print nodeName1, nodeName2, "spans differ."
411        return False
412
413    if fn1.numKnots() != fn2.numKnots():
414        print nodeName1, nodeName2, "numKnots differ."
415        return False
416
417    if fn1.form() != fn2.form():
418        print nodeName1, nodeName2, "form differ."
419        return False
420
421    cv1 = OpenMaya.MPointArray()
422    fn1.getCVs(cv1)
423    cv2 = OpenMaya.MPointArray()
424    fn2.getCVs(cv2)
425
426    if not comparePointArray(cv1, cv2):
427        print nodeName1, nodeName2, "points differ."
428        return False
429
430    # we do not need to compare knots, since they aren't stored in Alembic
431    # and are currently recreated as uniformly distributed between 0 and 1
432
433    return True
434