
/* 
	ssClassBlob.m - This is a sample NiteLite module which illustrates how a 
	NiteLite module is written. See the shell file 'ssClassModule.m' and the 
	document 'ToolsAPI.wn' for more information. You are welcome to use any 
	code in this file in your development of a MetroTools' NiteLite module.
	
	Author: Ron Miller
	Date: 6/17/92
	Version: 1.0  
	Copyright: 1992 Metrosoft, All Rights Reserved.
*/

#import	<libc.h>
#import <dpsclient/wraps.h>
#import <dpsclient/event.h>
#import <appkit/Application.h>
#import <appkit/Control.h>
#import <appkit/Button.h>
#import <appkit/Slider.h>
#import "ssClassBlob.h"

/* saved settings structure */
typedef struct
	{
		int		delayTime;
		int		nSegs;
	} blobSetRec, *blobSetPtr;

static void GetCurvePoints(curveRec *curves, int index, int nCurves, NXPoint *pts);

@implementation ssClassBlob

/* IB methods */
- NSegTextControl:sender
{
	nSegs = [sender intValue];
	if( nSegs < [nSegSlider minValue] )
		nSegs = [nSegSlider minValue];
	if( nSegs > [nSegSlider maxValue] )
		nSegs = [nSegSlider maxValue];
		
	[nSegSlider setIntValue:nSegs];
	[nSegText setIntValue:nSegs];
	[screenSaver ssModChanged];
	
    return self;
}

- DelayControl:sender
{
	delayTime = [(Control*)sender intValue];
	[(mtClassNiteLite*)screenSaver ssModChanged];
	
    return self;
}

- NSegSlideControl:sender
{
	NXEvent	*evt;
	int		n;
	
	n = [(Control*)sender intValue];
	[(Control*)nSegText setIntValue:n];
	
	evt = [NXApp currentEvent];
	if( evt->type == NX_MOUSEUP )
	{
		nSegs = n;
		[(mtClassNiteLite*)screenSaver ssModChanged];
	}
	
    return self;
}

/* NiteLite module methods */
- initSelf:(BOOL)ifOnly
{
	return( self );
}

- doActivate:(mtClassNiteLite*)ssTool
{
	screenSaver = ssTool;
	
	return( self );
}

- doDeactivate
{
	return( self );
}

- unload
{
	return( self );
}

- getSettings: (void**)data: (int*)size
{
	blobSetPtr	settings;
	
	settings = (blobSetPtr)malloc( sizeof(blobSetRec) );
	settings->delayTime = delayTime;
	settings->nSegs = nSegs;
	
	*data = (void*)settings;
	*size = sizeof(blobSetRec);
	
	return( self );
}

- setSettings: (void*)data: (int)size
{
	if( data == NULL || size != sizeof(blobSetRec) )
	{
		delayTime = 0;
		nSegs = 3;
	}
	else
	{
		delayTime = ((blobSetPtr)data)->delayTime;
		nSegs = ((blobSetPtr)data)->nSegs;
		if( nSegs > MAXSEGS )
			nSegs = MAXSEGS;
	}
	
	[(Control*)delaySlider setIntValue:delayTime];
	[(Control*)nSegSlider setIntValue:nSegs];
	[(Control*)nSegText setIntValue:nSegs];
	
	return( self );
}

- getControlsWindow:(Window**)theWind
{
	*theWind = toolWind;
	
	return( self );
}

- prepDraw:(BOOL)inFore
{
	dispTime = 0;
	blob.isNew = YES;
		
	return( self );
}

- drawFrame:(View*)theView:(NXRect*)obsList:(int)nRects:(BOOL*)didDraw:
	(NXColor)backColor
{
	unsigned	curTime;
	NXRect		bounds;
	
	*didDraw = NO;
	
	curTime = currentTimeInMs();
	if( dispTime > curTime )
		dispTime = curTime;
	if( curTime < (dispTime+delayTime) )
		return( self );
	
	*didDraw = YES;
	dispTime = curTime;
	
	[theView getBounds:&bounds];
	if( blob.isNew )
		[self initBlob:&bounds];
	
	[self drawBlob];
	[self incBlob:&bounds];
	
	return( self );
}

- endDraw
{
	return( self );
}


/* support methods and routines */

- initBlob:(NXRect*)frame
{
	int		i, j;
	
	blob.isNew = NO;
	for( i=0; i<MAXSEGS; i++ )
	{
		for( j=0; j<2; j++ )
		{
			blob.segs[i].ctlPts[j].x = 
				(float)(random() % (int)(frame->size.width/4)) + 
				((frame->size.width*3)/8);
			blob.segs[i].ctlPts[j].y = 
				(float)(random() % (int)(frame->size.height/4)) + 
				((frame->size.height*3)/8);
				
			blob.segs[i].ctlIncs[j].x = (float)((random() % 40) - 20);
			if(blob.segs[i].ctlIncs[j].x<2 && blob.segs[i].ctlIncs[j].x>-2)
				blob.segs[i].ctlIncs[j].x = 2;
				
			blob.segs[i].ctlIncs[j].y = (float)((random() % 40) - 20);
			if(blob.segs[i].ctlIncs[j].y<2 && blob.segs[i].ctlIncs[j].y>-2)
				blob.segs[i].ctlIncs[j].y = 2;
		}
	}
	
	blob.hVal = ((float)(random() % 257)) / 256;
	blob.sVal = ((float)(random() % 129)) / 256 + .5;
	blob.bVal = .5;
	
	blob.hInc = .0031;
	blob.sInc = .0023;
	blob.bInc = .0011;
	
	return( self );
}

- drawBlob
{
	int		i;
	NXPoint	pts[4];
	
	PSnewpath();
	PSsethsbcolor( blob.hVal, blob.sVal, blob.bVal );
	
	for( i=0; i<nSegs; i++ )
	{
		GetCurvePoints( blob.segs, i, nSegs, pts );
		
		if( i==0 )
			PSmoveto( pts[0].x, pts[0].y );
			
		PScurveto(pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
	}
	
	PSclosepath();
	PSfill();
	
	return( self );
}

- incBlob:(NXRect*)frame
{
	int		i, j;
	
	for( i=0; i<MAXSEGS; i++ )
	{
		for( j=0; j<2; j++ )
		{
			blob.segs[i].ctlPts[j].x += blob.segs[i].ctlIncs[j].x;
			if( blob.segs[i].ctlPts[j].x < 0.0 )
			{
				blob.segs[i].ctlPts[j].x = -blob.segs[i].ctlPts[j].x;
				blob.segs[i].ctlIncs[j].x = -blob.segs[i].ctlIncs[j].x;
			}
			else if( blob.segs[i].ctlPts[j].x > frame->size.width )
			{
				blob.segs[i].ctlPts[j].x = 
					(2*frame->size.width) - blob.segs[i].ctlPts[j].x;
				blob.segs[i].ctlIncs[j].x = -blob.segs[i].ctlIncs[j].x;
			}
			
			blob.segs[i].ctlPts[j].y += blob.segs[i].ctlIncs[j].y;
			if( blob.segs[i].ctlPts[j].y < 0.0 )
			{
				blob.segs[i].ctlPts[j].y = -blob.segs[i].ctlPts[j].y;
				blob.segs[i].ctlIncs[j].y = -blob.segs[i].ctlIncs[j].y;
			}
			else if( blob.segs[i].ctlPts[j].y > frame->size.height )
			{
				blob.segs[i].ctlPts[j].y = 
					(2*frame->size.height) - blob.segs[i].ctlPts[j].y;
				blob.segs[i].ctlIncs[j].y = -blob.segs[i].ctlIncs[j].y;
			}
		}
	}
	
	blob.hVal += blob.hInc;
	if( blob.hVal > 1.0 )
		blob.hVal = blob.hVal - 1.0;
	
	blob.sVal += blob.sInc;
	if( blob.sVal > 1.0 )
	{
		blob.sVal = 2.0 - blob.sVal;
		blob.sInc = -blob.sInc;
	}
	else if( blob.sVal < .5 )
	{
		blob.sVal = 1.0 - blob.sVal;
		blob.sInc = -blob.sInc;
	}
	
	blob.bVal += blob.bInc;
	if( blob.bVal > 1.0 )
	{
		blob.bVal = 2.0 - blob.bVal;
		blob.bInc = -blob.bInc;
	}
	else if( blob.bVal < 0.0 )
	{
		blob.bVal = -blob.bVal;
		blob.bInc = -blob.bInc;
	}
	
	return( self );
}


static void GetCurvePoints( curveRec *curves, int index, int nCurves, NXPoint *pts )
{
	NXPoint	ancPt1, ancPt2;
	NXPoint	ctlPt1, ctlPt2;
	
	if( index==0 )
		ctlPt1 = curves[nCurves-1].ctlPts[1];
	else
		ctlPt1 = curves[index-1].ctlPts[1];
	ctlPt2 = curves[index].ctlPts[0];
	
	ancPt1.x = (ctlPt1.x + ctlPt2.x) / 2;
	ancPt1.y = (ctlPt1.y + ctlPt2.y) / 2;
	
	ctlPt1 = curves[index].ctlPts[1];
	if( index >= (nCurves-1) )
		ctlPt2 = curves[0].ctlPts[0];
	else
		ctlPt2 = curves[index+1].ctlPts[0];
		
	ancPt2.x = (ctlPt1.x + ctlPt2.x) / 2;
	ancPt2.y = (ctlPt1.y + ctlPt2.y) / 2;
	
	pts[0] = ancPt1;
	pts[1] = curves[index].ctlPts[0];
	pts[2] = curves[index].ctlPts[1];
	pts[3] = ancPt2;
}


@end
