% JoystickDemo.m
%
%   JoystickDemo
%
%   Demonstrates the use of Joystick.dll (Windows) and  Joystick.mex (MacOS) to 
%   probe joystick controls and read their settings.  
%
%   Joystick demo currently supports three types of controls: Buttons, Hats and Axes. 
%   It does not support Trackball controls. (But Joystick .dll&.mex do)
% 
%   For a list of Joystick sub-functions type "Joystick" at the matlab prompt.  
%   For a list of supporting functions, type "help PsychJoystick" at the matlab prompt. 
% 

% HISTORY:
%
%   08/17/01    awi		wrote it
%   08/23/01    awi		increased font size at Denis Pelli's suggestion. 
%	11/27/01	awi		changed font on Mac to helvitica because it looks better.
%   4/15/01     awi     removed platform conditional for font name and made the font Arial.
%                       conditional execution only on Mac version.  
%   
%
% NOTES:
%
%   8/17/01 awi -  We do a lot of drawing on each frame, which drags down the frame update rate, but it still seems plenty fast enough
%         on my 933MHz PIII.  It is not necessary to redraw everything on the screen each frame, but we do, because I was too lazy
%         to separate drawing of updated from non-updated parts of the display.  For example, we don't need to redraw the 
%         button labels, calculate positions of stuff, etc on every frame of the drawing loop.  We could speed it up by 
%         separating within the update loop the invariable drawing from that dependent on the states of the joystick.  
%         A quick way to do that would be to declare variables within the functions as persistant and calculate some quantities 
%         and do some drawing only once on the first pass through the functions.
%
%   8/23/01 awi -  Also, the the drawing of the TrackBall is left empty.  I don't have joystick with a trackball on it to use in 
%           and debugging the demo.  'GetBall' and other trackball-related JOYSTICK sub functions remain untested for this same 
%           reason, though they are implemented.   
%       

if strcmp('PCWIN',computer)
       error('Win: Joystick not yet supported.');
end 

clear all;

%Open an offscreen Window for drawing joystick gauges, also set text properties
[w, wRect]=Screen(0,'OpenWindow');
[h, hRect]=Screen(w,'OpenOffscreenWindow');

wHeight = RectHeight(wRect);
wWidth = RectWidth(wRect);
fontName  = 'Arial';
Screen(w,'TextFont',fontName);
Screen(w,'TextSize',30);
cursorHomeX = 2*screen(w,'TextWidth','X');
cursorHomeY = cursorHomeX;


%scope out the joysticks and report what we find
NumberJoysticks = JOYSTICK('GetNumJoysticks');
screen(w,'DrawText',['Found ' int2str(NumberJoysticks) ' connected joysticks:'],cursorHomeX, cursorHomeY);

cursorY = 2*cursorHomeY;
for i = 1:NumberJoysticks;
    joystickName = JOYSTICK(i,'GetJoystickName');
    screen(w,'DrawText',['   ' joystickName],cursorHomeX, cursorY);
    cursorY = cursorY + cursorHomeY;
end 
screen(w,'DrawText','Press any mouse button to continue',cursorHomeX, wHeight - cursorHomeY);
[msX,msY,msBut] = GetMouse;
while ~any(msBut)
    [msX,msY,msBut] = GetMouse;
end
while any(msBut)
    [msX,msY,msBut] = GetMouse;
end
controls = {'Axes','Balls','Buttons','Hats'};
subRect = wRect;
subRect(RectTop)= 2*cursorHomeY;
dividers = floor(linspace(0,wWidth,5));
gaugeBoxes = struct(controls{1},[],controls{2},[],controls{3},[],controls{4},[]);
numEachBoxes = struct(controls{1},[],controls{2},[],controls{3},[],controls{4},[]);
for i = 1:NumberJoysticks  %loop over joysticks
    Screen(w,'WaitBlanking');
    Screen(w,'FillRect');
    Screen(h,'FillRect');
    Screen(w,'TextSize',30);
    if i<NumberJoysticks
        screen(w,'DrawText',['Joystick: ' int2str(i) '. Press mouse button for next joystick.'],cursorHomeX, cursorHomeY,BlackIndex(w));
    else
        screen(w,'DrawText',['Joystick: ' int2str(i) '. Press mouse button to end.'],cursorHomeX, cursorHomeY, BlackIndex(w));
    end
    Screen(w,'TextSize',20);
    %loop over controls and size boxes for each control gauge
    for j = 1:length(controls)  
        tempRect(RectTop)=subRect(RectTop)+cursorHomeY;
        tempRect(RectLeft)=dividers(j);
        tempRect(RectRight)=dividers(j+1);
        tempRect(RectBottom)=subRect(RectBottom);
        numBoxes = JOYSTICK(i,['GetNum' controls{j}]);
        numEachBoxes = setfield(numEachBoxes,controls{j},numBoxes);
        boxBounds = floor(linspace(tempRect(RectTop),RectHeight(tempRect),numBoxes+1));
        for k = 1:numBoxes
            gaugeBoxes = setfield(gaugeBoxes,{k},controls{j},[tempRect(RectLeft),boxBounds(k),tempRect(RectRight),boxBounds(k+1)]);
        end
    end
    pause(1);
    goLoop = 1;
    while goLoop
        for j = 1:length(controls) %loop over the control types
            for k = 1:getfield(numEachBoxes,controls{j}) %loop over each control of a type
                switch controls{j}
                case 'Axes'
                    axisState = JOYSTICK(i,'GetAxis',k);
                    DrawAxis(h,GetField(gaugeBoxes,{k},'Axes'), axisState, k);
                case 'Balls'
                    [ballStateX, ballStateY] = JOYSTICK(i,'GetBall',k);
                    DrawBall(h,GetField(gaugeBoxes,{k},'Balls'), ballStateX, ballStateY,k);
                case 'Buttons'
                    buttonState = JOYSTICK(i,'GetButton',k);
                    DrawButton(h,GetField(gaugeBoxes,{k},'Buttons'),buttonState,k);
                case 'Hats'
                    hatState = JOYSTICK(i,'GetHat',k);
                    DrawHat(h,GetField(gaugeBoxes,{k},'Hats'),hatState,k);
                end
            end
        end
        screen(w,'WaitBlanking');
        screen('CopyWindow',h,w,subRect,subRect);
        [msX,msY,msBut] = GetMouse;
        if any(msBut)
            while any(msBut)
                [msX,msY,msBut] = GetMouse;
            end
            goLoop = 0;
        end
    end
end
    

screen(h,'Close');
screen(w,'Close');


    
    

