% ScreenDemo
%
% Demonstrates the use of Screen.mex to draw on-screen images,
% and control the CLUT (Color Look Up Table).
%
% See also MovieDemo, MovieDemo2, ScreenTest, TextDemo.

% 3/27/94	 dhb		Tests of DrawRect and DrawLine.
% 8/13/94	 dhb		Added whichScreen argument.
% 8/30/94	 dhb		Test DrawPoly.
% 6/10/95	 dhb		Added test of SetGamma and ClearScreen.
% 12/4/95  jdt		Wrote DrawDemo: face and clipping demos.
% 5/16/96  dhb    Changed to new calling form for Screen.
%          dhb    Added text prompts and removed some redundant tests.
% 5/27/96  dhb    Add test of ability to expand/contract into passed rect.
%          dhb    Add test of blit transfer mode, whose behavior I don't fully understand.
% 12/23/96 dgp    Corrected capitalization of 'Helvetica'.
% 12/23/96 dgp    Added list of some available fonts, as a test of Screen's text functions.
% 2/4/97   dhb    Pulled more advanced text tests into TestText.
%          dhb    OpenWindow instead of OpenScreen.
% 2/23/97  dhb    Changed name, updated usage to conform to 2.0 release.
%                 Removed some obscure functions.
% 3/9/97	 dgp		Show off enhanced ShowCursor and fat cursors
% 3/13/97  dhb    Minor cosmetic, removed some cursors and sped up that part.
% 3/26/97  dgp    Test GetImage vs PutImage.
% 3/37/97  dhb    Fixed text printing for PutImage test.
% 3/37/97  dgp    Use STD instead of VAR, since VAR requires Stat toolbox.
% 6/7/97   dgp    Cosmetic. Disabled the blanking test, which seemed out of place.
% 8/16/97  dgp		changed "text" to "theText" to avoid conflict with TEXT function.
% 1/26/98  dgp		Edited help text to mention MovieDemo.
% 2/14/98  dgp		Streamline. Deleted "clear to black". Deleted the obsolete timing code.
%					Put Get/PutImage test result in upper right, to make it more prominent.
%					Replaced MakeCosImage by explicit code.
%					Added gabor.
%					Tried to make the shapes more dramatic.
% 2/28/98 dgp	Folded in DrawDemo.
% 3/11/98 dgp	Updated for default white.
% 4/1/98  dgp	Now independent of pixelSize. Now tests all pixelSizes.
% 7/9/98  dgp  Cope when GetClut is not available.
% 3/8/00  emw  Added PC conditionals 
% 3/12/00 dgp  Fixed PC conditionals 
% 8/4/00  dhb  This now runs all the way through on my PC.  Output is
%              not perfect, but it doesn't crash.
% 6/27/01 awi  Changed ask calls to use GetChar instead of GetClicks because GetClicks fails when the 
%              psychtoolbox changes the screen's pixel depth.  Modified messages to user accordingly.               
% 4/03/01 awi  -modified screen 'PixelSizes' call on Windows to exclude 
%               non 16 & 32 bit modes from detected modes.
%               before what it did was to include 8 and 32 bit modes.
%              -restored third grating on Windows.
% 2/19/02 awi  reduced strech factor for elongagated grating from 8 to 4
%               because it does not fit on a small screen on Windows.  
% NOTES:
%
% 4/03/01 awi  We could restore GetClicks because it works on Windows now.

try
	
whichScreen=0;
pix=Screen(whichScreen,'PixelSizes');
if strcmp(computer,'PCWIN')
    % Win: some screen operations support only 8 and 32 bit pixel sizes.
	pix= intersect(pix, [8 32]);
end

ss=sprintf(' %d',pix);
ss=sprintf('This screen allows pixelSizes%s. Hit any key to begin test.',ss);
window=Screen(whichScreen,'OpenWindow');
Screen(window,'FillRect');
switch computer 
    case 'MAC2',
        fontName = 'Helvetica';
        fontSize = 24;
    case 'PCWIN'
        fontName = 'Tahoma';
        fontSize = 24;
    otherwise
        error(['Unsupported OS: ' computer]);
end
Screen(window,'TextFont',fontName);
Screen(window,'TextSize',fontSize);
Ask(window,ss,[],[],'GetChar');
Screen(window,'Close');
for pixelSize=pix
	% Open window on the screen; choose colors and font
	window=Screen(whichScreen,'OpenWindow',[],[],pixelSize);
    screen(window,'FillRect');
	black=BlackIndex(window);
	white=WhiteIndex(window);
	gray=(black+white)/2;
	Screen(window,'TextFont',fontName);
	Screen(window,'TextSize',fontSize);
	Ask(window,sprintf('Testing pixelSize %d. Hit any key to begin. (Hit command-period to quit at any time.)',pixelSize),[],[],'GetChar');
	Screen(window,'FillRect',gray);
	windowRect=Screen(window,'Rect');
	ShowCursor(0);	% arrow cursor
	HideCursor;

	% Prepare reversed CLUT
	if strcmp(computer,'PCWIN')
        % Win: we cannot get the CLUT using a screen number when no window is open.
		normalClut=(0:255)'*ones(1,3);
	else
		normalClut=Screen(whichScreen,'GetClut');
		if isempty(normalClut)
			normalClut=ClutDefault(whichScreen);
		end
	end
	reversedClut=flipud(normalClut);
	
	% Compute a cosine grating
	n=128;
	grating=(1+cos((1:n)*2*pi*4/n))/2;
	grating=black+(white-black)*grating;
	grating=ones(n,1)*grating;
	grating=grating';	% transpose
	grating=round(grating);
	
	% Put the grating on the screen, in two places
	[m,n]=size(grating);
	rect=OffsetRect([0,0,n,m],100,100);
    
    %1
    SysBeep;
    GetChar;
	Screen(window,'PutImage',grating,rect);
  
    
	windowRect=Screen(window,'Rect');
	rect=AlignRect([0,0,n,n],windowRect,RectRight,RectBottom);
	rect=OffsetRect(rect,-100,-100);
    
    %2
    SysBeep;
    GetChar;
    Screen(window,'PutImage',grating,rect);
    
	
	% As a check, read back a grating. Is it the same as what we wrote?
	g1=double(Screen(window,'GetImage',rect));
	g2=g1(:,:,1); % if we got RGB, we only need one of the layers
	g2=g2-grating;
	rms=sqrt(mean(std(g2).^2));
	if rms>0
		theText=sprintf('(GetImage differed from PutImage by %f rms.)\n',rms);
	else
		theText=sprintf('(GetImage read back PutImage perfectly.)\n');
	end
	
	% Draw text in upper right corner
	windowRect=Screen(window,'Rect');
	height=Screen(window,'TextWidth','x'); % estimate x-height by width of "x".
	width=Screen(window,'TextWidth',[theText 'xx']);
	r=[0 0 width 2*height];
	r=AlignRect(r,windowRect,RectRight,RectTop);
	Screen(window,'DrawText',theText,r(RectLeft),r(RectBottom));
    
	% Show a 3rd grating, stretched.
	%r=OffsetRect([0,0,n/8,8*m],100+n/2-n/16,0); %last arg was 250
    r=OffsetRect([0,0,n/4,4*m],100+n/2-n/16,0); %last arg was 250
    
    %3
    SysBeep;
    GetChar;
	Screen(window,'PutImage',grating,r);
   
	% Show a 4th grating, with Gaussian envelope
	x=-150:150;
	n=length(x);
	grating=sin(x*2*pi*5/n);		% sin
	g=exp(-0.5*(x./(n/6)).^2);	% gaussian
	grating=g'*(grating.*g);
	grating=black+(white-black)*0.5*(grating+1);
	grating=round(grating);
	rect=CenterRect([0,0,n,n],windowRect);
 
    %4
     SysBeep;
    GetChar;
	Screen(window,'PutImage',grating,rect);
	
	% Use pen to draw a face
	Ask(window,'Hit any key to draw a face',[],[],'GetChar');
	Screen(window,'FillRect');
	siz=150;
	rect=CenterRect([0 0 2*siz 2*siz],windowRect);
	penWidth = 10;
	penHeight = 10;
	Screen(window,'FrameRect',black,rect,penWidth,penHeight);
	siz = 40;
	penWidth = 15;
	penHeight = 5;
	rect=OffsetRect(CenterRect([0 0 siz 2*siz],windowRect),-1.5*siz,-20);
	Screen(window,'FrameOval',black,rect,penWidth,penHeight);
	rect=OffsetRect(CenterRect([0 0 siz 2*siz],windowRect),1.5*siz,-20);
	Screen(window,'FrameOval',black,rect,penWidth,penHeight);
	siz = 50;
	penWidth = 1;
	penHeight = 15;
	rect=OffsetRect(CenterRect([0 0 2*siz 2*siz],windowRect),0,siz);
	Screen(window,'FrameArc',black,rect,90,180,penWidth,penHeight);
	
	% Draw some Euclidean shapes
	Ask(window,'Hit any key to draw shapes',[],[],'GetChar');
	Screen(window,'DrawText',theText,20,r(RectBottom)-20,gray);
	Screen(window,'FillRect');
	lightGray=0.75*white+0.25*black;
	Screen(window,'DrawLine',lightGray,0,0,1000,1000,2);
	Screen(window,'FillOval',lightGray,[100 100 300 400]);
	Screen(window,'FillPoly',gray,[0 400; 640 300; 400 500 ]);
	
	% Set clipping region and draw the shapes again.
	% They only show through the clipping region
	Ask(window,'Hit any key to show effect of disc-shaped clipping region',[],[],'GetChar');
	Screen(window,'FillRect');
	rect=[150,150,450,450];
	Screen(window,'SetDrawingRegion',rect,1);				% clip
	Screen(window,'DrawLine',lightGray,0,0,1000,1000,2);
	Screen(window,'FillOval',lightGray,[100 100 300 400]);
	Screen(window,'FillPoly',gray,[0 400 ; 640 300 ; 400 500 ]);
	Screen(window,'SetDrawingRegion',windowRect,0); % don't clip
   
	if strcmp(computer,'MAC2')
		% Test ShowCursor. 
		Ask(window,'Hit any key to show some cursors',[],[],'GetChar');
		Screen(window,'FillRect',white,[400,200,500,300]);
		for i=[0:5 128 300:303 400:401 0]
			WaitSecs(0.5);
			SetMouse(450,250,window);
			ShowCursor(i);
			Screen(window,'FillRect',[],[500,200,700,300]);
			Screen(window,'DrawText',sprintf('Cursor %d',i),520,260);
		end
		Screen(window,'FillRect',[],[500,200,700,300]);
	end 

	if (pixelSize==32) & strcmp(computer,'PCWIN')
		Ask(window,'Win: 32-bit-mode clut operations not supported. Hit any key to continue',[],[],'GetChar');
		screen(window,'FillRect')
	else
		% Write CLUT
		HideCursor;
		Screen(window,'SetClut',normalClut);
		Ask(window,'Hit any key to reverse the CLUT',[],[],'GetChar');
		Screen(window,'SetClut',reversedClut);
		Ask(window,'Hit any key to restore CLUT',[],[],'GetChar');
		Screen(window,'SetClut',normalClut);
	end 

	if strcmp(computer,'MAC2')
		% Load video driver gamma correction table.  Should invert screen.
		% Change in gamma only takes effect after next CLUT load.
		Ask(window,'Hit any key to invert gamma',[],[],'GetChar');
		Screen(window,'Gamma',[255:-1:0]');
		Screen(window,'SetClut',normalClut);
		Ask(window,'Hit any key to restore gamma',[],[],'GetChar');
		Screen(window,'Gamma',[0:255]');
		Screen(window,'SetClut',normalClut);
	end 

	% Clear the screen
	Ask(window,'Hit any key to fill screen with black',[],[],'GetChar');
	Screen(window,'FillRect',black)

	% Close things up
	Ask(window,'Hit any key to continue',white,black,'GetChar');
	ShowCursor;
	Screen(window,'Close');
end

catch

clear mex
error(lasterr);

end
