/*********************************************/
/*     BG3D EXPORTER FOR MAYA API			 */
/*       		   Main.c                    */
/* 		(c)2002 Pangea Software  			 */
/* 			By Brian Greenstone      		 */
/*********************************************/

//#include <MSimple.h>
//#include <codefragments.h>

#include "3dmath.h"


extern	FSSpec	gSharedLibSpec;
extern	int			gNumMaterials;
extern	MOMeshObject			*gVertexArrayObjects[];
extern	float		gFramesPerSecondFrac;
extern	MOMaterialObject			*gMaterials[];
extern	int			gNumTotalPoints,gNumTotalTriangles,gNumTotalVertexArrays,gNumDuplicateVerts;

/************************/
/*      PROTOTYPES      */
/************************/


static OSErr DoExportOptionsDialog(void);
static void Cleanup(void);
static void CreatePreviewWindow(void);
static void DrawPreviewCallback(void);
static CFBundleRef _CFXBundleCreateFromImageName (CFAllocatorRef allocator, const char* image_name);

/************************/
/*      VARIABLES       */
/************************/

#if DEBUG
WindowPtr	gDebugWindow = nil;
#endif


Boolean		gExportLayersSeparate 	= false;
Boolean		gShowNormals			= false;
Boolean		gUseVertexColors		= false;

WindowPtr			gPreviewWindow = nil;
OGLSetupOutputType	*gPreviewContext = nil;
float				gPreviewScale;

CFBundleRef 		gBundle = nil;
IBNibRef 			gNibs = nil;


/************************/
/*      CONSTANTS       */
/************************/

#define	MOVE_TO_FRONT		(WindowPtr)-1L
#define	NIL_STRING			"\p"




/******************** CREATE PREVIEW WINDOW ************************/

static void CreatePreviewWindow(void)
{
OGLSetupInputType		viewDef;

			/* CREATE THE WINDOW */
		
	OpenLibResource();	
	gPreviewWindow = GetNewCWindow(128, nil,MOVE_TO_FRONT);			
	CloseLibResource();
	
	
			/* SET OGL PARAMETERS */
			
	OGL_NewViewDef(&viewDef, gPreviewWindow);
	OGL_SetupWindow(&viewDef, &gPreviewContext, nil);

}


/********************* SHOW PREVIEW *************************/

void ShowPreview(Boolean wait)
{

	CalcFramesPerSecond();
	do
	{
		CalcFramesPerSecond();

		OGL_DrawScene(gPreviewContext, DrawPreviewCallback);


	}while(!Button() && wait);

}


/*********************** DRAW PREVIEW CALLBACK *********************/

static void DrawPreviewCallback(void)
{
int		i;
static float rotY = 0;
static float rotX = 0;
OGLMatrix4x4	m;

			/* SHOW SPINNING MODEL */
			
	OGL_PushState();
	
//	glDisable(GL_CULL_FACE);

	glEnable(GL_BLEND);	//---------
	
	rotX += gFramesPerSecondFrac * .4f;
	rotY += gFramesPerSecondFrac;
	OGLMatrix4x4_SetRotate_XYZ(&m, rotX, rotY, 0);
	glMultMatrixf((float *)&m);
	OGLMatrix4x4_SetScale(&m, gPreviewScale, gPreviewScale, gPreviewScale);
	glMultMatrixf((float *)&m);

	for (i = 0; i < gNumMaterials; i++)
	{
		if (gVertexArrayObjects[i])
		{
			MO_DrawGeometry_VertexArray(&gVertexArrayObjects[i]->objectData);
		}
	}
	
	OGL_PopState();
	
	
			/* SHOW SOME STATS */

			
	OGL_DrawString("\p#Verts: ", 10,10);
	OGL_DrawInt(gNumTotalPoints, 100, 10);

	OGL_DrawString("\p#Tris: ", 10,20);
	OGL_DrawInt(gNumTotalTriangles, 100, 20);
	

	OGL_DrawString("\p#Geom: ", 10,30);
	OGL_DrawInt(gNumTotalVertexArrays, 100, 30);

	OGL_DrawString("\p#Dups: ", 10,40);
	OGL_DrawInt(gNumDuplicateVerts, 100, 40);
	
}




/*********************** DO EXPORT OPTIONS DIALOG ************************/
//
// Returns 1 if user cancels
//

static OSErr DoExportOptionsDialog(void)
{
DialogPtr	myDialog;
Boolean		dialogDone = false;
Boolean		cancel = false;
DialogItemType	itemHit; 
ControlRef		ctrlHandle;

			/* OPEN THE DIALOG */
			
	OpenLibResource();

	myDialog = GetNewDialog(128,nil,MOVE_TO_FRONT);
	if (myDialog == nil)
	{
		MayaDisplayError("DoExportOptionsDialog(): GetNewDialog failed!");
		CloseLibResource();	
		SysBeep(0);
		return(1);
	}

	AutoSizeDialog(myDialog);
	

				/* SET CONTROL VALUES */
					
	GetDialogItemAsControl(myDialog,3,&ctrlHandle);					
	SetControlValue(ctrlHandle,gExportLayersSeparate);

	GetDialogItemAsControl(myDialog,4,&ctrlHandle);					
	SetControlValue(ctrlHandle,gUseVertexColors);

	GetDialogItemAsControl(myDialog,5,&ctrlHandle);					
	SetControlValue(ctrlHandle,gShowNormals);



				/* DO IT */
				
	while(!dialogDone)
	{
		ModalDialog(nil, &itemHit);
		switch (itemHit)
		{
			case 	1:									// hit ok
					dialogDone = true;
					break;
					
			case	2:									// cancel
					cancel = true;
					dialogDone = true;
					break;					
					
			case	3:
					gExportLayersSeparate = !gExportLayersSeparate;
					GetDialogItemAsControl(myDialog,itemHit,&ctrlHandle);					
					SetControlValue(ctrlHandle,gExportLayersSeparate);
					break;

			case	4:
					gUseVertexColors = !gUseVertexColors;
					GetDialogItemAsControl(myDialog,itemHit,&ctrlHandle);					
					SetControlValue(ctrlHandle,gUseVertexColors);
					break;

			case	5:
					gShowNormals = !gShowNormals;
					GetDialogItemAsControl(myDialog,itemHit,&ctrlHandle);					
					SetControlValue(ctrlHandle,gShowNormals);
					break;
					
		}
		
	}

			/* CLEAN UP */

	DisposeDialog(myDialog);
	CloseLibResource();
	
	return(cancel);
}




/******************** LINKER FIRST TIME ***************************/
//
// Initial entry point called by linker
//

#include <mach-o/ldsyms.h>
#include <mach-o/dyld.h>

#pragma CALL_ON_LOAD InitMachOLibrary


void InitMachOLibrary ()
{
OSErr		theResult;
long		tmpDirID;
SInt16		tmpVRef;
CFBundleRef theBundle;
SInt32		result;
short		localizedResRefNum, fixResRefNum;

	SInt16      alertItemHit;

	const struct macho_header* header = (void *)&_mh_dylib_header;
    const char* imagename   = 0;	
    int			cnt			= _dyld_image_count();
	int			idx1;
	
				/* DETERMINE IMAGE NAME */
				
    for (idx1 = 1; idx1 < cnt; idx1++)
	{
		if ((void *)_dyld_get_image_header(idx1) == (void *)header)
			imagename = _dyld_get_image_name(idx1);
	}
	
	if (imagename == 0)
		StandardAlert(kAlertStopAlert, "\pBG3D InitMachOLibrary: could not find image name! ", NULL, NULL, &alertItemHit);
	
	
			/* GET THE BUNDLE OF A HEADER */
			
	theBundle = _CFXBundleCreateFromImageName (kCFAllocatorDefault, imagename);
    
	result = CFBundleOpenBundleResourceFiles(theBundle, &localizedResRefNum, &fixResRefNum);	// you can call UseRefFile on the returned resRefNum 
	
			
			/* MANUALLY FIND OUR REZ FILE */

	theResult = FindFolder( kOnSystemDisk, kUsersFolderType, false, &tmpVRef, &tmpDirID );
	if (theResult != noErr)
		StandardAlert(kAlertStopAlert, "\pBG3D InitMachOLibrary: FindFolder() could not find Users folder! ", NULL, NULL, &alertItemHit);
	
	theResult = FSMakeFSSpec(tmpVRef, tmpDirID, "\p:Shared:Alias:maya:plug-ins:plugin.rsrc", &gSharedLibSpec);
	if (theResult != noErr)
		StandardAlert(kAlertStopAlert, "\pBG3D InitMachOLibrary: FindFolder() could not find plugin.rsrc in plug-ins folder! ", NULL, NULL, &alertItemHit);

	OGL_Boot();
}

/**************** CFX BUNDLE CREATE FROM IMAGE NAME ********************/
//
// This should work for bundles, framework application and packages
//

static CFBundleRef _CFXBundleCreateFromImageName (CFAllocatorRef allocator, const char* image_name)
{
  CFURLRef myBundleExecutableURL = CFURLCreateFromFileSystemRepresentation (allocator, image_name, strlen(image_name), false);
  if (myBundleExecutableURL == 0)
    return 0;
            
  CFURLRef myBundleContentsMacOSURL = CFURLCreateCopyDeletingLastPathComponent (allocator, myBundleExecutableURL); // Delete Versions/Current/Executable
  CFRelease (myBundleExecutableURL);
  if (myBundleContentsMacOSURL == 0)
    return 0;
   
  CFURLRef myBundleContentsURL = CFURLCreateCopyDeletingLastPathComponent (allocator, myBundleContentsMacOSURL); // Delete Current
  CFRelease (myBundleContentsMacOSURL);
  if (myBundleContentsURL == 0)
    return 0;
           
  CFURLRef theBundleURL = CFURLCreateCopyDeletingLastPathComponent (allocator, myBundleContentsURL); // Delete Versions
  CFRelease (myBundleContentsURL);
  if (theBundleURL == 0)
    return 0;
  
  CFBundleRef result = CFBundleCreate (allocator, theBundleURL);
  CFRelease (theBundleURL);
     
  return result;
}


/*********************** CLEANUP *************************/
//
// Called when plug-in is done and ready to return
//

static void Cleanup(void)
{
int		i;

	if (gPreviewContext)
		OGL_DisposeWindowSetup(&gPreviewContext);

	if (gPreviewWindow)
	{
		DisposeWindow(gPreviewWindow);
		gPreviewWindow = nil;
	}


		/* DISPOSE OF THE MATERIAL METAOBJECTS */
		
	for (i = 0; i < gNumMaterials; i++)
	{
		if (gMaterials[i])
		{
			MO_DisposeObjectReference(gMaterials[i]);
			gMaterials[i] = nil;
		}
	}


}



/******************** PLUGIN ENTRY *************************/
//
// This is what gets called from the "doIt" function in Maya.cpp
//

void PluginEntry(void)
{
GrafPtr		oldPort;
GDHandle	oldGD;
GWorldPtr	oldGW;

	
				/*******************/
    			/* INIT SOME STUFF */
				/*******************/
        
	GetPort(&oldPort);												// keep this to restore when return
	GetGWorld (&oldGW,&oldGD);

				/* INIT MY STUFF */
			
	MayaDisplayMessage("Initializing things...");
									    			
	InitFile();


			/****************************/
			/* DO EXPORT OPTIONS DIALOG */
			/****************************/
			
	MayaDisplayMessage("Do Export Options Dialog...");
			
	if (DoExportOptionsDialog() != noErr)
		goto bail;
	
      
      		/* CREATE OPENGL PREVIEW WINDOW */

	CreatePreviewWindow();
      		
    
    		/***************/
    		/* PROCESS IT! */
    		/***************/
    		  
	ProcessMayaData();
      		
      		
      		/* RETURN OK */
      		
bail:      		
	SetPort(oldPort);
	SetGWorld(oldGW,oldGD);
	
	Cleanup();
	
}