File: joystick.c/*
joystick.c
A basic test of reading various attributes of a
joystick and displaying them using primitives and
fonts. Also tests setting video modes, and menus.
*/
#define CPWDLL_EXTERN
#include <cpw.h>
/* for testing : switch between a joystick callback and a timer / polling */
/* #define USE_JOY_CALLBACK 1 */
/* font face */
static CpwFontFace font;
/* joystick info */
static CpwJoystickList list;
static CpwJoystickInfo info;
/* available video modes info */
static CpwVideoList vlist;
/* handy window characteristics holder */
static CpwWindowInfo windowInfo = { 1,100,100,250,250 };
/* performance marks */
static uint_32 m1, m2, m3;
/****************************************************/
/* 2D Matrix Setup */
/****************************************************/
void set2DMatrix( void )
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( 0, windowInfo.width, 0, windowInfo.height );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
/****************************************************/
/* 3D Matrix Setup */
/****************************************************/
void set3DMatrix( void )
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60, windowInfo.width / windowInfo.height, 1, 100 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
/****************************************************/
/* Draw Window One */
/****************************************************/
void drawWindowOne( pCpw cpw )
{
uint_32 i;
uint_32 fscale;
char buf[10];
#ifndef USE_JOY_CALLBACK
cpwEnterMark( cpw, m2 );
cpwJoystickPoll( cpw, &info );
cpwExitMark( cpw, m2 );
#endif
cpwEnterMark( cpw, m1 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
set2DMatrix();
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_SCALE, 1.0 );
glScaled( windowInfo.width / 250.0, windowInfo.height / 300.0, 1.0 );
fscale = (int)( 5.0 * ( ( windowInfo.width / 250.0 ) + ( windowInfo.height / 300.0 ) ) );
/* x-axis */
glColor3d( 0.0, 1.0, 0.2 );
glPushMatrix();
glTranslated( 20.0, 200.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_WIDTH, 20.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_HEIGHT, 60.0 );
cpwDrawPrimitive( cpw, CPW_PRIM_2D_RECTANGLE );
glPopMatrix();
glColor3d( 0.4, 0.4, 1.0 );
glPushMatrix();
glTranslated( 21.0, 201.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_WIDTH, 18.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_HEIGHT, (float)58.0 *
( (float) MCpwJoystickXAxis( info ) / (float) MCpwJoystickAxisRangeMax( list ) ) );
cpwDrawPrimitive( cpw, CPW_PRIM_2D_FILLEDRECTANGLE );
glPopMatrix();
glPushMatrix();
glRasterPos2d( 15.0, 185.0 );
cpwFontMode( cpw, CPW_FONTOPT_SIZE, fscale );
cpwDrawFont( cpw, font, "X-Axis", 1 );
glPopMatrix();
/* y-axis */
glColor3d( 0.0, 1.0, 0.2 );
glPushMatrix();
glTranslated( 60.0, 200.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_WIDTH, 20.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_HEIGHT, 60.0 );
cpwDrawPrimitive( cpw, CPW_PRIM_2D_RECTANGLE );
glPopMatrix();
glColor3d( 0.4, 0.4, 1.0 );
glPushMatrix();
glTranslated( 61.0, 201.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_WIDTH, 18.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_HEIGHT, (float) 58.0 *
( (float) MCpwJoystickYAxis( info ) / (float) MCpwJoystickAxisRangeMax( list ) ) );
cpwDrawPrimitive( cpw, CPW_PRIM_2D_FILLEDRECTANGLE );
glPopMatrix();
glPushMatrix();
glRasterPos2d( 55.0, 185.0 );
cpwFontMode( cpw, CPW_FONTOPT_SIZE, fscale );
cpwDrawFont( cpw, font, "Y-Axis", 1 );
glPopMatrix();
/* z-axis */
glColor3d( 0.0, 1.0, 0.2 );
glPushMatrix();
glTranslated( 100.0, 200.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_WIDTH, 20.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_HEIGHT, 60.0 );
cpwDrawPrimitive( cpw, CPW_PRIM_2D_RECTANGLE );
glPopMatrix();
glColor3d( 0.4, 0.4, 1.0 );
glPushMatrix();
glTranslated( 101.0, 201.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_WIDTH, 18.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_HEIGHT, (float)58.0 *
( (float) MCpwJoystickZAxis( info ) / (float) MCpwJoystickAxisRangeMax( list ) ) );
cpwDrawPrimitive( cpw, CPW_PRIM_2D_FILLEDRECTANGLE );
glPopMatrix();
glPushMatrix();
glRasterPos2d( 95.0, 185.0 );
cpwFontMode( cpw, CPW_FONTOPT_SIZE, fscale );
cpwDrawFont( cpw, font, "Z-Axis", 1 );
glPopMatrix();
/* buttons */
for ( i = 1; i <= MCpwJoystick1ButtonCount( list ); i++ ) {
glColor3d( 0.0, 1.0, 0.2 );
glPushMatrix();
glTranslated( 10 + ( i * 20.0 ), 150.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_INNERRADIUS, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_OUTERRADIUS, 8.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_SLICES, 10.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_STACKS, 1.0 );
cpwDrawPrimitive( cpw, CPW_PRIM_3D_SOLIDDISK );
glPopMatrix();
glPushMatrix();
glRasterPos2d( 2 + ( i * 20.0 ), 130.0 );
cpwFontMode( cpw, CPW_FONTOPT_SIZE, fscale );
sprintf( buf, "%2d", i );
cpwDrawFont( cpw, font, buf, 1 );
glPopMatrix();
if ( MCpwJoystick1Button( info, i ) )
glColor3d( 0.8, 0.0, 0.0 );
else
glColor3d( 0.0, 1.0, 0.2 );
glPushMatrix();
glTranslated( 10 + ( i * 20.0 ), 150.0, 0.0 );
//glTranslated( 11 + ( i * 20.0 ), 151.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_OUTERRADIUS, 6.0 );
cpwDrawPrimitive( cpw, CPW_PRIM_3D_SOLIDDISK );
glPopMatrix();
}
/* z-rotation */
glColor3d( 0.0, 1.0, 0.2 );
glPushMatrix();
glTranslated( 140.0, 200.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_WIDTH, 20.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_HEIGHT, 60.0 );
cpwDrawPrimitive( cpw, CPW_PRIM_2D_RECTANGLE );
glPopMatrix();
glColor3d( 0.4, 0.4, 1.0 );
glPushMatrix();
glTranslated( 141.0, 201.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_WIDTH, 18.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_HEIGHT, (float)58.0 *
( (float) MCpwJoystickZRot( info ) / (float) MCpwJoystickRotRangeMax( list ) ) );
cpwDrawPrimitive( cpw, CPW_PRIM_2D_FILLEDRECTANGLE );
glPopMatrix();
glPushMatrix();
glRasterPos2d( 137.0, 185.0 );
cpwFontMode( cpw, CPW_FONTOPT_SIZE, fscale );
cpwDrawFont( cpw, font, "Z-Rot", 1 );
glPopMatrix();
/* first pov hat position */
glPushMatrix();
glColor3d( 0.4, 0.4, 1.0 );
glTranslated( 200.0, 250.0, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_INNERRADIUS, 0.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_OUTERRADIUS, 15.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_SLICES, 10.0 );
cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_STACKS, 1.0 );
cpwDrawPrimitive( cpw, CPW_PRIM_3D_WIREDISK );
glPopMatrix();
glPushMatrix();
glTranslated( 200.0, 250.0, 0.0 );
if ( MCpwJoystickPov( list, 1 ) ) {
switch( MCpwJoystickPov1( info ) ) {
case CPW_POV_CENTERED:
glRotatef( 90, 1, 0, 0 );
break;
case CPW_POV_UP:
break;
case CPW_POV_UPRIGHT:
glRotatef( -45, 0, 0, 1 );
break;
case CPW_POV_RIGHT:
glRotatef( -90, 0, 0, 1 );
break;
case CPW_POV_DOWNRIGHT:
glRotatef( -135, 0, 0, 1 );
break;
case CPW_POV_DOWN:
glRotatef( 180, 0, 0, 1 );
break;
case CPW_POV_DOWNLEFT:
glRotatef( 135, 0, 0, 1 );
break;
case CPW_POV_LEFT:
glRotatef( 90, 0, 0, 1 );
break;
case CPW_POV_UPLEFT:
glRotatef( 45, 0, 0, 1 );
break;
}
}
glColor3d( 0.0, 1.0, 0.0 );
glBegin( GL_POLYGON );
glVertex3f( -4, 0.0, 0.0 );
glVertex3f( 0, 15.0, 0.0 );
glVertex3f( 4, 0.0, 0.0 );
glEnd();
glPopMatrix();
glPushMatrix();
glRasterPos2d( 187.0, 220.0 );
cpwFontMode( cpw, CPW_FONTOPT_SIZE, fscale );
cpwDrawFont( cpw, font, "Pov-1", 1 );
glPopMatrix();
cpwExitMark( cpw, m1 );
}
/****************************************************/
/* Window Draw Event callback */
/****************************************************/
void draw( pCpw cpw, uint_32 winid )
{
switch( winid ) {
case 1:
drawWindowOne( cpw );
break;
}
cpwSwapWindowBuffers( cpw, winid );
}
/****************************************************/
/* Window Create / Destroy Event callback */
/****************************************************/
/* the window's context is set current prior to this call,
do any init we need per window */
void window( pCpw cpw, uint_32 winid, bool flag )
{
/* creation event */
if ( flag == true ) {
//glShadeModel( GL_SMOOTH );
glDepthFunc( GL_LEQUAL );
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
glEnable( GL_LINE_SMOOTH );
//glEnable( GL_POLYGON_SMOOTH );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glClearColor( 0.0, 0.0, 0.0, 1.0 );
switch( winid ) {
case 1:
break;
}
return;
}
/* window close event */
if ( flag == false ) {
cpwDestroyWindow( cpw, winid );
return;
}
}
/****************************************************/
/* Window Resize Event callback */
/****************************************************/
void reshape( pCpw cpw, uint_32 winid, uint_32 width, uint_32 height )
{
if ( height == 0 ) { height=1; }
windowInfo.width = width;
windowInfo.height = height;
set2DMatrix();
glViewport( 0, 0, width, height );
}
/****************************************************/
/* Joystick callback */
/****************************************************/
void joystick( pCpw cpw, CpwJoystickInfo * iinfo )
{
memcpy( &info, iinfo, sizeof( info ) );
cpwPostWindowRedisplay( cpw, 1 );
}
/****************************************************/
/* Mainloop callback */
/****************************************************/
void mainloop( pCpw cpw, bool eventspending )
{
}
/****************************************************/
/* Timer callback */
/****************************************************/
void timer( pCpw cpw, uint_32 id )
{
cpwPostWindowRedisplay( cpw, 1 );
}
/****************************************************/
/* Video Modes */
/****************************************************/
static uint_32 lastChecked;
static uint_32 defMode;
bool changeVideoMode( pCpw cpw, uint_32 videoMode )
{
CpwVideoHints hint;
hint.width = vlist.list[videoMode]->width;
hint.height = vlist.list[videoMode]->height;
hint.depth = vlist.list[videoMode]->depth;
/* change the video mode */
if ( !cpwChangeVideoMode( cpw, hint ) )
return false;
return true;
}
void setupVideoMenu( pCpw cpw, uint_32 submenu )
{
char buf[100];
uint_32 count = 0;
if ( !cpwListVideoModes( cpw, &vlist ) ) return;
cpwAddMenuEntry( cpw, submenu, "Reset", 20, false );
while ( count < vlist.size ) {
if ( vlist.list[count]->active == true ) {
sprintf( buf, "%d-bit %dx%d", vlist.list[count]->depth,
vlist.list[count]->width,
vlist.list[count]->height );
cpwAddMenuEntry( cpw, submenu, buf, 21+count, true );
lastChecked = 21+count;
defMode = 21+count;
} else {
sprintf( buf, "%d-bit %dx%d", vlist.list[count]->depth,
vlist.list[count]->width,
vlist.list[count]->height );
cpwAddMenuEntry( cpw, submenu, buf, 21+count, false );
}
count++;
}
return;
}
/****************************************************/
/* Menu Select callback */
/****************************************************/
void menuselect( pCpw cpw, uint_32 winid, uint_32 menuid, uint_32 entryid )
{
bool res = false;
if ( entryid == 4 ) cpwBreakMainLoop( cpw );
if ( entryid >= 20 && entryid <= vlist.size + 21 ) {
/* change video mode */
if ( entryid == 20 )
res = cpwResetVideoMode( cpw );
else
res = changeVideoMode( cpw, entryid-21 );
}
if ( res ) {
if ( entryid == 20 ) {
cpwCheckMenuEntry( cpw, menuid, defMode );
cpwUncheckMenuEntry( cpw, menuid, lastChecked );
lastChecked = defMode;
return;
}
cpwCheckMenuEntry( cpw, menuid, entryid );
cpwUncheckMenuEntry( cpw, menuid, lastChecked );
lastChecked = entryid;
}
}
/****************************************************/
/* Main */
/****************************************************/
int main(int argc, char* argv[])
{
pCpw cpw;
uint_32 win, topmenu, submenu1, submenu2;
cpw = null;
/****************************************************/
/* Init */
/****************************************************/
cpwInitContext( &cpw ); /* create the context and init it */
cpwInitWindowProperty( cpw, CPW_WINDOWPROP_EXPECTMENU, 0, 0 );
cpwInitWindowProperty( cpw, CPW_WINDOWPROP_POSITION, 100, 100 );
cpwInitWindowProperty( cpw, CPW_WINDOWPROP_SIZE, 300, 250 );
/****************************************************/
/* Creaing Windows */
/****************************************************/
win = cpwCreateWindowEx( cpw, "Joystick Test", windowInfo.x, windowInfo.y,
windowInfo.width, windowInfo.height );
/****************************************************/
/* Joysticks */
/****************************************************/
memset( &list, 0, sizeof( CpwJoystickList ) );
memset( &info, 0, sizeof( CpwJoystickInfo ) );
/* ask for one joystick and setup some custom ranges */
MCpwJoysticksRequested( list, 1 );
/* set some custom axis and rotation ranges */
/* (using helper macros in cpw_macros.h) */
MCpwJoystickAxisRange( list, 0, 100 );
MCpwJoystickRotRange( list, 0, 359 );
MCpwJoystickVelRange( list, 0, 100 );
MCpwJoystickAccelRange( list, 0, 100 );
/* init a joystick if one is present */
if ( !cpwInitJoysticks( cpw, &list ) ) {
printf( "No joystick support found.\n" );
}
/* save the id of the joystick we found in info structure */
info.id = MCpwJoystick1Id( list );
#ifdef USE_JOY_CALLBACK
/* init a joystick callback for every 50 milliseconds */
cpwJoystickCallback( cpw, joystick, MCpwJoystick1Id( list ), 50 );
#endif
/****************************************************/
/* Window Menus */
/****************************************************/
topmenu = cpwCreateMenu( cpw, menuselect );
submenu1 = cpwCreateSubMenu( cpw );
submenu2 = cpwCreateSubMenu( cpw );
cpwAddMenuEntry( cpw, submenu1, "Open", 1, false );
cpwAddMenuEntry( cpw, submenu1, "Close", 2, false );
cpwAddMenuSeperator( cpw, submenu1, 3 );
cpwAddMenuEntry( cpw, submenu1, "Print", 3, false );
cpwAddMenuSeperator( cpw, submenu1, 5 );
cpwAddMenuEntry( cpw, submenu1, "Exit", 4, false );
setupVideoMenu( cpw, submenu2 );
cpwAddSubMenu( cpw, topmenu, "Control", submenu1, 100 );
cpwAddSubMenu( cpw, topmenu, "Screen", submenu2, 102 );
cpwAssignMenuToWindow( cpw, topmenu, win );
/****************************************************/
/* Event Callbacks */
/****************************************************/
cpwCreateCallback( cpw, window );
cpwDisplayCallback( cpw, draw );
cpwReshapeCallback( cpw, reshape );
cpwMainLoopCallback( cpw, mainloop, 1000 );
/****************************************************/
/* Timers */
/****************************************************/
#ifndef USE_JOY_CALLBACK
cpwTimerCallback( cpw, 10, 1, true, timer );
#endif
/****************************************************/
/* Fonts */
/****************************************************/
cpwFontMode( cpw, CPW_FONTOPT_PIXELMAP, 0 ); /* we only support this type right now */
cpwFontMode( cpw, CPW_FONTOPT_ALIGNLEFT, 0 );
cpwFontMode( cpw, CPW_FONTOPT_PIXELMAP_GLFORMAT, GL_LUMINANCE );
font = cpwLoadFont( cpw, "arial.ttf", CPW_FONTLOC_HOST, "", "" );
if ( font == 0 )
printf("Could not load TrueType font file Arial.\n");
/****************************************************/
/* Performance Timing */
/****************************************************/
m1 = cpwAddMark( cpw, "draw window", true );
m2 = cpwAddMark( cpw, "joystick poll", true );
m3 = cpwAddMark( cpw, "total time ", true );
/****************************************************/
/* FPS */
/****************************************************/
cpwFpsInit( cpw );
/****************************************************/
/* MainLoop */
/****************************************************/
cpwEnterMark( cpw, m3 );
cpwMainLoop( cpw );
cpwExitMark( cpw, m3 );
/****************************************************/
/* Exit and Free */
/****************************************************/
cpwFreeVideoList( cpw, &vlist );
cpwFreeContext( &cpw );
return 0;
}