#-
# ==========================================================================
# Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors.  All 
# rights reserved.
#
# The coded instructions, statements, computer programs, and/or related 
# material (collectively the "Data") in these files contain unpublished 
# information proprietary to Autodesk, Inc. ("Autodesk") and/or its 
# licensors, which is protected by U.S. and Canadian federal copyright 
# law and by international treaties.
#
# The Data is provided for use exclusively by You. You have the right 
# to use, modify, and incorporate this Data into other products for 
# purposes authorized by the Autodesk software license agreement, 
# without fee.
#
# The copyright notices in the Software and this entire statement, 
# including the above license grant, this restriction and the 
# following disclaimer, must be included in all copies of the 
# Software, in whole or in part, and all derivative works of 
# the Software, unless such copies or derivative works are solely 
# in the form of machine-executable object code generated by a 
# source language processor.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. 
# AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED 
# WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF 
# NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
# PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR 
# TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS 
# BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, 
# DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK 
# AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY 
# OR PROBABILITY OF SUCH DAMAGES.
#
# ==========================================================================
#+

import sys
import math
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMayaUI as OpenMayaUI
import maya.OpenMayaRender as OpenMayaRender

glRenderer = OpenMayaRender.MHardwareRenderer.theRenderer()
glFT = glRenderer.glFunctionTable()

kPluginCmdName = "spNarrowPolyViewer"

kInitFlag = "-in"
kInitFlagLong = "-init"

kResultsFlag = "-r"
kResultsFlagLong = "-results"

kClearFlag = "-cl"
kClearFlagLong = "-clear"

kToleranceFlag = "-tol"
kToleranceFlagLong = "-tolerance"

class narrowPolyViewer(OpenMayaMPx.MPx3dModelView):
	def __init__(self):
		OpenMayaMPx.MPx3dModelView.__init__(self)

		self.fOldCamera = OpenMaya.MDagPath()
		self.fCameraList = OpenMaya.MDagPathArray()
		self.fCurrentPass = 0
		self.fDrawManips = True
		self.fOldDisplayStyle = OpenMayaUI.M3dView.kWireFrame
		self.fLightTest = False
		self.fListList = OpenMaya.MDagPathArray()
		self.tol = 10.0

		self.setMultipleDrawEnable(True)

	def multipleDrawPassCount(self):
		return self.fCameraList.length() + 1

	def setCameraList(self, cameraList):
		setMultipleDrawEnable(True)
		self.fCameraList.clear()
		
		for i in range(cameraList.length()):
			self.fCameraList.append(cameraList[i])

		self.refresh()

	def removeAllCameras(self):
		self.fCameraList.clear()
		self.refresh()

	def getCameraHUDName(self):
		cameraPath = OpenMaya.MDagPath()
		self.getCamera(cameraPath)		

		cameraPath.pop()
		
		hudName = "spNarrowPolyViewer: " + cameraPath.partialPathName()
		return hudName

	def setIsolateSelect(self, list):
		self.setViewSelected(True)
		return self.setObjectsToView(list)

	def setIsolateSelectOff(self):
		return self.setViewSelected(False)

	def preMultipleDraw(self):
		self.fCurrentPass = 0
		self.fDrawManips = False

		dagPath = OpenMaya.MDagPath()

		try:
			oldCamera = OpenMaya.MDagPath()
			self.getCamera(oldCamera)

			self.fOldCamera = oldCamera

			displayHUD(False)

			sList = OpenMaya.MSelectionList()
			OpenMaya.MGlobal.getActiveSelectionList(sList)
			
			sList.getDagPath(0, dagPath)
		except:
			# sys.stderr.write("ERROR: spNarrowPolyViewer.preMultipleDraw b\n")
			pass

		try:
			itMeshPolygon = OpenMaya.MItMeshPolygon(dagPath, OpenMaya.cvar.MObject_kNullObj)
			
			if None == itMeshPolygon:
				return;
			
			self.beginGL()

			while not itMeshPolygon.isDone():
				points = OpenMaya.MPointArray()
				itMeshPolygon.getPoints(points, OpenMaya.MSpace.kWorld)
				length = points.length()
				
				if length == 3:
					for i in range(length):
						p = points[i]
						p1 = points[(i+1)%length]
						p2 = points[(i+2)%length]
						
						v1 = OpenMaya.MVector(p1 - p)
						v2 = OpenMaya.MVector(p2 - p)
						
						angle = v1.angle(v2) * 180.0 / math.pi
						
						if math.fabs(angle - self.tol) < 0.0001 or angle < self.tol:
							glFT.glBegin( OpenMayaRender.MGL_POLYGON )
							glFT.glVertex3f(points[0].x, points[0].y, points[0].z)
							glFT.glVertex3f(points[1].x, points[1].y, points[1].z)
							glFT.glVertex3f(points[2].x, points[2].y, points[2].z)
							
							glFT.glNormal3f(points[0].x, points[0].y, points[0].z)
							glFT.glNormal3f(points[1].x, points[1].y, points[1].z)
							glFT.glNormal3f(points[2].x, points[2].y, points[2].z)
							
							glFT.glTexCoord3f(points[0].x, points[0].y, points[0].z)
							glFT.glTexCoord3f(points[1].x, points[1].y, points[1].z)
							glFT.glTexCoord3f(points[2].x, points[2].y, points[2].z)
							glFT.glEnd()

				itMeshPolygon.next()

			self.endGL()
		except:
			# sys.stderr.write("ERROR: spNarrowPolyViewer.preMultipleDraw c\n")
			pass

	def postMultipleDraw(self):
		try:
			self.setCamera(self.fOldCamera)
			self.fDrawManips = True
			self.updateViewingParameters()
		except:
			sys.stderr.write("ERROR: spNarrowPolyViewer.postMultipleDraw\n")
			raise

	def preMultipleDrawPass(self, index):
		self.fCurrentPass = index

		try:
			self.setDisplayAxis(False)
			self.setDisplayAxisAtOrigin(False)
			self.setDisplayCameraAnnotation(False)

			dagPath = OpenMaya.MDagPath()
		
			if self.fCurrentPass == 0:
				self.getCamera(dagPath)
			else:
				nCameras = self.fCameraList.length()
				if self.fCurrentPass <= nCameras:
					dagPath = self.fCameraList[self.fCurrentPass-1]
				else:
					sys.stderr.write("ERROR: ...too many passes specified\n")
					return
		
			self.setCameraInDraw(dagPath)

			self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayEverything, True)
			
			if dagPath == self.fOldCamera:
				self.fDrawManips = True
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayGrid, True)

				self.setFogEnabled(True)
				
				self.setBackgroundFogEnabled(False)
				
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayLights, True)
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayCameras, True)
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayIkHandles, True)
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayDimensions, True)
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplaySelectHandles, True)
				
				textPos = OpenMaya.MPoint(0.0, 0.0, 0.0)
				str = "Main View"
				self.drawText(str, textPos, OpenMayaUI.M3dView.kLeft)
			else:
				self.fDrawManips = False
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayGrid, False)

				self.setFogEnabled(True)
				
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayLights, False)
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayCameras, False)
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayIkHandles, False)
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayDimensions, False)
				self.setObjectDisplay(OpenMayaUI.M3dView.kDisplaySelectHandles, False)
		except:
			sys.stderr.write("ERROR: spNarrowPolyViewer.preMultipleDrawPass\n")
			raise
		
		# note do not have light test in here
		
		# self.setLightingMode(OpenMayaUI.kLightDefault)
		
		if ((self.fCurrentPass % 2) == 0):
			self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayNurbsSurfaces, True );
			self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayNurbsCurves, True );
			
		self.updateViewingParameters()

	def postMultipleDrawPass(self, index):
		self.setObjectDisplay(OpenMayaUI.M3dView.kDisplayEverything, True)

	def okForMultipleDraw(self, dagPath):
		if not self.fDrawManips and dagPath.hasFn(OpenMaya.MFn.kManipulator3D):
			return False
		return True

	def multipleDrawPassCount(self):
		return self.fCameraList.length() + 1
		
	def viewType(self):
		return "spNarrowPolyViewer";




class narrowPolyViewerCmd(OpenMayaMPx.MPxModelEditorCommand):
	def __init__(self):
		OpenMayaMPx.MPxModelEditorCommand.__init__(self)
		self.fCameraList = OpenMaya.MDagPathArray()

	def appendSyntax(self):
		try:
			theSyntax = self._syntax()
			theSyntax.addFlag(kInitFlag, kInitFlagLong)
			theSyntax.addFlag(kResultsFlag, kResultsFlagLong)
			theSyntax.addFlag(kClearFlag, kClearFlagLong)
			theSyntax.addFlag(kToleranceFlag, kToleranceFlagLong, OpenMaya.MSyntax.kDouble)

		except:
			sys.stderr.write( "ERROR: creating syntax for model editor command: %s" % kPluginCmdName )

	def doEditFlags(self):
		try:
			user3dModelView = self.modelView()

			if user3dModelView.viewType() == kPluginCmdName:
				argData = self._parser()
	
				if argData.isFlagSet(kInitFlag):
					self.initTests(user3dModelView)
				elif argData.isFlagSet(kResultsFlag):
					self.testResults(user3dModelView)
				elif argData.isFlagSet(kClearFlag):
					self.clearResults(user3dModelView)
				elif argData.isFlagSet(kToleranceFlag):
					tol = argData.flagArgumentDouble(kToleranceFlag, 0)
					user3dModelView.tol = tol
					user3dModelView.refresh(True, True)
				else:
					return OpenMaya.kUnknownParameter
		except:
			sys.stderr.write( "ERROR: in doEditFlags for model editor command: %s" % kPluginCmdName )

	def initTests(self, view):
		clearResults(self, view)
		
		# Add every camera into the scene.  Don't change the main camera,
		# it is OK that it gets reused.
		#
		cameraPath = OpenMaya.MDagPath()
		dagIterator = OpenMaya.MItDag(OpenMaya.MItDag.kDepthFirst, OpenMaya.MFn.kCamera)

		while not dagIterator.isDone():
			try:
				dagIterator.getPath(cameraPath)
				camera = OpenMaya.MFnCamera(cameraPath)
			except:
				continue

			OpenMaya.MGlobal.displayInfo(camera.fullPathName())
			self.fCameraList.append(cameraPath)

			dagIterator.next()

		try:
			view.setCameraList(self.fCameraList)
		except:
			OpenMaya.MGlobal.displayError("Could not set list of cameras\n")
			raise

		view.refresh()

	def testResults(self, view):
		print "fCameraLIst.length() = %d " % (self.fCameraList.length(), )
		length = self.fCameraList.length()

	def clearResults(self, view):
		view.removeAllCameras()
		self.fCameraList.clear()



def cmdCreator():
	return OpenMayaMPx.asMPxPtr( narrowPolyViewerCmd() )

def viewerCreator():
	return OpenMayaMPx.asMPxPtr( narrowPolyViewer() )

# initialize the script plug-in
def initializePlugin(mobject):
	mplugin = OpenMayaMPx.MFnPlugin(mobject)
	try:
		mplugin.registerModelEditorCommand( kPluginCmdName, cmdCreator, viewerCreator)
	except:
		sys.stderr.write( "Failed to register model editor command: %s" % kPluginCmdName )
		raise

# uninitialize the script plug-in
def uninitializePlugin(mobject):
	mplugin = OpenMayaMPx.MFnPlugin(mobject)
	try:
		mplugin.deregisterModelEditorCommand( kPluginCmdName )
	except:
		sys.stderr.write( "Failed to deregister model editor command: %s" % kPluginCmdName )
		raise
	
