
/*
    RotatorCamera.m

    RotatorCamera is an N3DCamera that tracks the mouse to rotate the
    contents of the camera using a N3DRotator.

    You may freely copy, distribute, and reuse the code in this example.
    C disclaims any warranty of any kind, expressed or implied, as to its
    fitness for any particular use.
*/

#import "Graph.h"

#define MOUSE_MASK (NX_LMOUSEDOWNMASK|NX_LMOUSEDRAGGEDMASK|NX_LMOUSEUPMASK)

@implementation RotatorCamera

/*
 * As we track the mouse, we use a N3DRotator object to calculate the new
 * viewing transforms, and then apply those to the camera's world shape.
 * If our window's delegate is interested, we notify it that we've changed
 * the document.
 */
- mouseDown:(NXEvent *)event {
    N3DRotator *rotator = [[N3DRotator allocFromZone:[self zone]] initWithCamera:self];
    RtMatrix rotationXForm;
    RtMatrix inverseRotationXForm;
    NXEvent newEvent;
    NXPoint oldLocation, newLocation;

    oldLocation = event->location;
    [self convertPoint:&oldLocation fromView:nil];
    [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
    do {
	newEvent = *[NXApp getNextEvent:MOUSE_MASK];
	newLocation = newEvent.location;
	[self convertPoint:&newLocation fromView:nil];
	if (oldLocation.x != newLocation.x || oldLocation.y != newLocation.y) {
	    [rotator trackMouseFrom:&oldLocation to:&newLocation
		rotationMatrix:rotationXForm andInverse:inverseRotationXForm];
	    [worldShape concatTransformMatrix:rotationXForm premultiply:NO];
	    [self display];
	    if ([[window delegate] respondsTo:@selector(docChanged)])
		[[window delegate] docChanged];
	}
	oldLocation = newLocation;
    } while (newEvent.type != NX_LMOUSEDOWN && newEvent.type != NX_LMOUSEUP);
    [rotator free];
    return self;
}

@end
