##########################################################################
#
#  Copyright (c) 2008-2010, Image Engine Design Inc. All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are
#  met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#
#     * Neither the name of Image Engine Design nor the names of any
#       other contributors to this software may be used to endorse or
#       promote products derived from this software without specific prior
#       written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
#  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

from maya.OpenMaya import *
import maya.cmds
import math
import IECore
import IECoreMaya

class BakeTransform( IECore.Op ) :

	def __init__( self ) :

		IECore.Op.__init__( self, "Bakes transforms from one object onto another.",
			IECoreMaya.DAGPathParameter(
				name = "result",
				description = "The name of the baked transform",
				defaultValue = "",
				allowEmptyString = True,
			)
		)

		self.parameters().addParameters(
			[
				IECoreMaya.DAGPathParameter(
					name = "src",
					description = "The source transform node to bake from.",
					defaultValue = "",
					check = IECoreMaya.DAGPathParameter.CheckType.MustExist,
					allowEmptyString = False,
				),
				IECoreMaya.DAGPathParameter(
					name = "dst",
					description = "The destination transform node to apply the bake to. If this doesn't exist"
						"then it'll be created for you.",
					defaultValue = "",
					check = IECoreMaya.DAGPathParameter.CheckType.DontCare,
					allowEmptyString = False,
				),
				IECore.FrameListParameter(
					name = "frames",
					description = "The frame range over which to perform the bake."
						"Keyframes will be made at every frame in this range.",
					defaultValue = IECoreMaya.PlaybackFrameList( IECoreMaya.PlaybackFrameList.Range.Playback ),
				),
				IECore.BoolParameter(
					name = "lock",
					description = "If this is specified then the transform attributes which are"
						"keyframed on the destination object are also locked.",
					defaultValue = False,
				),
			]
		)

	@staticmethod
	def transferTransform( src, dst, setKey=True ) :

		worldMatrixConverter = IECoreMaya.FromMayaPlugConverter.create( str(src.fullPathName()) + ".worldMatrix" )
		worldMatrix = worldMatrixConverter.convert().value
		e = worldMatrix.rotate
		maya.cmds.xform( dst.fullPathName(), translation=tuple( worldMatrix.translate ), rotation=[math.degrees(x) for x in e], scale=tuple( worldMatrix.scale ) )
		maya.cmds.setKeyframe( dst.fullPathName(), attribute=["translate", "rotate", "scale"] )

	@staticmethod
	def lockTransform( transform ) :

		transformName = transform.fullPathName()
		maya.cmds.setAttr( str( transformName ) + ".translate", lock=True )
		maya.cmds.setAttr( str( transformName ) + ".rotate", lock=True )
		maya.cmds.setAttr( str( transformName ) + ".scale", lock=True )
		maya.cmds.setAttr( str( transformName ) + ".shear", lock=True )

	def doOperation( self, operands ) :

		if maya.cmds.objExists( operands.dst.value ) :
			dst = self.dst.getDAGPathValue()
		else :
			dst = maya.cmds.createNode( "transform", name=operands.dst.value, skipSelect=True )
			list = MSelectionList()
			list.add( dst )
			dst = MDagPath()
			list.getDagPath(0, dst)

		dstPath = str( dst.fullPathName() )

		src = self.src.getDAGPathValue()

		for f in self.frames.getFrameListValue().asList() :

			maya.cmds.currentTime( float( f ) )
			self.transferTransform( src, dst, True )

		# fix discontinuous rotations
		maya.cmds.filterCurve( dstPath + ".rotateX", dstPath + ".rotateY", dstPath + ".rotateZ" )

		if operands.lock.value :
			self.lockTransform( dst )

		return IECore.StringData( dstPath )

IECore.registerRunTimeTyped( BakeTransform )
