//////////
//
//	File:		VRBackBuffer.c
//
//	Contains:	Sample code showing how to work with orientation of QuickTime VR back buffer.
//
//	Written by:	Ken Doyle
//	Revised by: Tim Monroe
//
//	Copyright:	© 1999 by Apple Computer, Inc., all rights reserved.
//
//	Change History (most recent first):
//
//	   <2>	 	03/20/00	rtm		made changes to get things running under CarbonLib
//	   <1>	 	06/26/99	rtm		first file 
//	   
//	This file contains functions that illustrate how to determine whether the back buffer is oriented
//	vertically or horizontally, and how to draw a picture accordingly.
//
//////////

//////////
//	   
// header files
//	   
//////////

#include "VRBackBuffer.h"


//////////
//
// VRBB_InitWindowData
// Initialize any window-specific data.
//
//////////

ApplicationDataHdl VRBB_InitWindowData (WindowObject theWindowObject)
{
#pragma unused(theWindowObject)

	ApplicationDataHdl	myAppData;
	
	myAppData = (ApplicationDataHdl)NewHandleClear(sizeof(ApplicationDataRecord));
	if (myAppData != NULL) {
		(**myAppData).fPicture = NULL;
		(**myAppData).fPictureWidth = kDefaultEmbPictWidth;
		(**myAppData).fBackBufferProc = NewQTVRBackBufferImagingUPP(VRBB_BackBufferImagingProc);
		(**myAppData).fCurrMenuItem = 0;
	}

	return(myAppData);
}


//////////
//
// VRBB_DumpWindowData
// Dispose of any window-specific data.
//
//////////

void VRBB_DumpWindowData (WindowObject theWindowObject)
{
	ApplicationDataHdl		myAppData = NULL;

	myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject);
	if (myAppData == NULL)
		return;

	// if we have a lingering picture, dump it
	if ((**myAppData).fPicture != NULL) {
		KillPicture ((**myAppData).fPicture);
		(**myAppData).fPicture = NULL;
	}
	
	DisposeQTVRBackBufferImagingUPP((**myAppData).fBackBufferProc);
}
	
	
//////////
//
// VRBB_InstallBackBufferImagingProc
// Install a back buffer imaging procedure.
//
//////////

OSErr VRBB_InstallBackBufferImagingProc (QTVRInstance theInstance, WindowObject theWindowObject, short thePictResID, Boolean theIsHoriz)
{
	ApplicationDataHdl		myAppData;
	QTVRAreaOfInterest		myArea;
	float					myWidth, myHeight;
	Rect					myPictRect;
	OSErr					myErr = noErr;

	// initialize; clean up any existing back buffer procedure
	if ((theInstance == NULL) || (theWindowObject == NULL)) 
		return(paramErr);

	myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject);
	if (myAppData == NULL) 
		return(paramErr);

	HLock((Handle)myAppData);
	
	VRBB_CleanUpBackBuffer(theWindowObject);

	// get the picture to embed	
	(**myAppData).fPicture = GetPicture(thePictResID);
	if ((**myAppData).fPicture == NULL) {
		VRBB_CleanUpBackBuffer(theWindowObject);
		goto bail;
	}

	DetachResource((Handle)(**myAppData).fPicture);
	
	myPictRect = (*(**myAppData).fPicture)->picFrame;
#if TARGET_OS_WIN32
	myPictRect.top = EndianU16_BtoN(myPictRect.top);
	myPictRect.left = EndianU16_BtoN(myPictRect.left);
	myPictRect.bottom = EndianU16_BtoN(myPictRect.bottom);
	myPictRect.right = EndianU16_BtoN(myPictRect.right);
#endif
	
	MacOffsetRect(&myPictRect, -myPictRect.left, -myPictRect.top);

	// set the area of interest	
	myWidth = kDefaultEmbPictWidth;
	
	if (theIsHoriz)
		myHeight = myWidth * (((float)myPictRect.bottom) / ((float)myPictRect.right));
	else
		myHeight = myWidth * (((float)myPictRect.right) / ((float)myPictRect.bottom));

	// center the picture on the current pan and tilt angles
	myArea.panAngle = QTVRGetPanAngle(theInstance) + (myWidth/2);
	myArea.tiltAngle = QTVRGetTiltAngle(theInstance) + (myHeight/2);

	myArea.width = myWidth;
	myArea.height = myHeight;

	// if the back buffer is oriented horizontally, set the appropriate flag
	myArea.flags = theIsHoriz ? kQTVRBackBufferHorizontal : 0;

	// install our procedure
	myErr = QTVRSetBackBufferImagingProc(theInstance, (**myAppData).fBackBufferProc, 1, &myArea, (SInt32)theWindowObject);

bail:
	HUnlock((Handle)myAppData);
	return(myErr);
}
	

//////////
//
// VRBB_CleanUpBackBuffer
//
//////////

OSErr VRBB_CleanUpBackBuffer (WindowObject theWindowObject)
{
	ApplicationDataHdl		myAppData;
	OSErr					myErr = paramErr;

	if (theWindowObject == NULL) 
		goto bail;
	
	myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject);
	if (myAppData == NULL)
		goto bail;
	
	// if we have a lingering picture, dump it
	if ((**myAppData).fPicture != NULL) {
		KillPicture ((**myAppData).fPicture);
		(**myAppData).fPicture = NULL;
	}
	
	// clear any back-buffer procedure
	myErr = QTVRSetBackBufferImagingProc((**theWindowObject).fInstance, NULL, 0, NULL, 0);

	// make sure the back buffer is clean
	myErr = QTVRRefreshBackBuffer((**theWindowObject).fInstance, 0);
	
bail:
	return(myErr);
}


//////////
//
// VRBB_BackBufferImagingProc
// The back buffer imaging procedure: draw the current picture into the back buffer.
//
//////////

PASCAL_RTN OSErr VRBB_BackBufferImagingProc (QTVRInstance theInstance, Rect *theRect, UInt16 theAreaIndex, UInt32 theFlagsIn, UInt32 *theFlagsOut, long theRefCon)
{
#pragma unused(theAreaIndex)
	WindowObject			myWindowObject = (WindowObject)theRefCon;
	ApplicationDataHdl		myAppData = NULL;
	Boolean					myIsDrawing = theFlagsIn & kQTVRBackBufferRectVisible;
	OSErr					myErr = paramErr;
	
	// assume we're not going to draw anything
	*theFlagsOut = 0;
	
	if ((theInstance == NULL) || (myWindowObject == NULL)) 
		goto bail;

	myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(myWindowObject);
	if (myAppData == NULL) 
		goto bail;

	if (myIsDrawing) {
		if ((**myAppData).fPicture != NULL) {
			DrawPicture((**myAppData).fPicture, theRect);
			*theFlagsOut = kQTVRBackBufferFlagDidDraw;		// if we drew something, tell QuickTime VR
		}
	}
	
	myErr = noErr;
	
bail:	
	return(myErr);
}


//////////
//
// VRBB_IsBackBufferHorizontal
// Is the back buffer oriented horizontally?
//
//////////

Boolean VRBB_IsBackBufferHorizontal (QTVRInstance theInstance)
{
	UInt32		myGeometry;
	UInt16		myResolution;
	UInt32		myCachePixelFormat;
	SInt16		myCacheSize;
	OSErr		myErr = noErr;

	if (theInstance == NULL)
		return(false);

	myErr = QTVRGetBackBufferSettings(theInstance, &myGeometry, &myResolution, &myCachePixelFormat, &myCacheSize);
	if (myErr != noErr)
		return(false);
	else
		return(myGeometry == kQTVRHorizontalCylinder);
}



