#include #include #include #include #include #include #include #include #include #include #include #include "psys2d.h" #include "gfx-x.h" /*#include "math-help.h" */ int cleanup_and_exit=0; static int paused=0; static void ilimit(char *, int *, int, int); static void show_usage(char *); static void renderpsys(Gfx *, Particle_Sys *, unsigned char ); static void ilimit(char *name, int *var, int min, int max) { /* Range limit an integer between min/max sets to closest gives an explanation if *name is a non null (string) */ if (!name) { *var=((*var)>max)?max:(*var); *var=((*var)max) { printf("Limiting %s to max %d from %d\n", name, max, *var); *var=max; } else if (*var : Only show frames\n"); printf("\t-n : set number of particles to \n"); printf("\t-x : set x resolution\n"); printf("\t-y : set y resolution\n"); printf("\t-r : run in root window\n"); printf("\t-m : randomly change force modes\n"); printf("\t-b <0-255>: Set particle brightness\n"); printf("\t-f : Show frames per second\n"); printf("\t-c : Run with a colormap based on a given color\n" "\t : e.g. -c 0xffaa66 for shades of orange\ne" "\t : -c 0xaaccff for shades of something?!\n"); printf("hello world!\n"); exit(0); } static void renderpsys(Gfx *g, Particle_Sys *psys, unsigned char brightness) { Particle *p = psys->p; int pcount=psys->n_particles; /* can render to anywhere between 1 and xmax - 2 ( because we don't want particles to actually HIT the edges of the window as that messes with the blur algorithm - well, it makes it harder to write it if we can't just assume the left and right columns are always going to be zero. range is therefore MAX: (xmax - 1) MIN : 1 1 -> xmax-1 p->x is 0.0->1.0 hence : 1 + p->x * (cb->xmax - 3) */ while (pcount --) { p=psys->p + pcount; // using the #defined version // gfx_add_pixel(g, GFX_ADD_PIXEL(g, (int)(1 + p->x * (g->xres-3)), (int)(2 + p->y * (g->yres-3)), brightness); } } void setexitevt() { /* signal handler function to set flag to shut down program down immediately */ cleanup_and_exit=1; } void signalhandler() { /* catch all/any/everything! (might want to use sigaction for portability) */ signal(SIGHUP,setexitevt); signal(SIGINT,setexitevt); signal(SIGKILL,setexitevt); signal(SIGPIPE,setexitevt); signal(SIGALRM,setexitevt); signal(SIGTERM,setexitevt); signal(SIGXCPU,setexitevt); signal(SIGXFSZ,setexitevt); signal(SIGVTALRM,setexitevt); signal(SIGPROF,setexitevt); signal(SIGUSR1,setexitevt); signal(SIGUSR2,setexitevt); } void handle_keyboard_io(Gfx *g, Particle_Sys *p, int showkeys) { int key; int RENDKEY = 'R'; int DECKEY1 = '9'; int INCKEY1 = '0'; int DECKEY2 = 'o'; int INCKEY2 = 'p'; int DECKEY3 = 'l'; int INCKEY3 = ';'; int DECKEY4 = '.'; int INCKEY4 = '/'; int NEXFKEY = 'n'; int RESETKEY = 'r'; int DFLTKEY = 'd'; int QUITKEY = 'q'; int GRAVKEY = 'g'; int MODE1= '1'; int MODE2= '2'; int MODE3= '3'; int MODE4= '4'; int MODE5= '5'; int WHATKEY='h'; int PAUSEKEY=' '; while ((key =gfx_getkey(g)) || (showkeys==1)) { /* increase or decrease the control variables for the current force system */ if (key==DECKEY1) { psys_dec_var(p, 0); key=0;} if (key==INCKEY1) { psys_inc_var(p, 0); key=0;} if (key==DECKEY2) { psys_dec_var(p, 1); key=0;} if (key==INCKEY2) { psys_inc_var(p, 1); key=0;} if (key==RENDKEY) { g->renderer=!g->renderer; } if (key==DECKEY3) { psys_dec_var(p, 2); key=0;} if (key==INCKEY3) { psys_inc_var(p, 2); key=0;} if (key==DECKEY4) { psys_dec_var(p, 3); key=0;} if (key==INCKEY4) { psys_inc_var(p, 3); key=0;} if (key==NEXFKEY) { psys_set_rnd(p); key=0;} if (key==RESETKEY) { psys_reset_all_particles(p); key=0;} if (key==DFLTKEY) { psys_reset_defaults(p); key=0;} if (key==QUITKEY) { cleanup_and_exit=1; key=0;} if (key==GRAVKEY) { psys_toggle_gravity(p); key=0;} if (key==MODE1) { psys_set_gra(p); key =0; } if (key==MODE2) { psys_set_ang(p); key =0; } if (key==MODE3) { psys_set_oth(p); key =0; } if (key==MODE4) { psys_set_spr(p); key =0; } if (key==MODE5) { psys_set_stf(p); key =0; } if (key==PAUSEKEY) { paused=!paused; key=0; } if ((key==WHATKEY) || (showkeys==1)) { showkeys=0; printf("\n\n\n ---- KEYBOARD CONTOLS ----\n"); printf(" (Just press them randomly!)\n"); printf("CURRENT FORCE SYSTEM PARAMETER CONTROLS:\n"); printf(" Decrease/Increase variable 1 : '%c' / '%c'\n",DECKEY1,INCKEY1); printf(" Decrease/Increase variable 2 : '%c' / '%c'\n",DECKEY2,INCKEY2); printf(" Decrease/Increase variable 3 : '%c' / '%c'\n",DECKEY3,INCKEY3); printf(" Decrease/Increase variable 4 : '%c' / '%c'\n",DECKEY4,INCKEY4); printf(" Restore to defaults : '%c'\n", DFLTKEY); printf("\nFORCE SYSTEM:\n"); printf(" grav : '%c'\n", MODE1); printf(" angular : '%c'\n", MODE2); printf(" other (weird) : '%c'\n", MODE3); printf(" spring : '%c'\n", MODE4); printf(" cheesy starfield : '%c'\n", MODE5); printf(" Random : '%c'\n", NEXFKEY); printf(" Display this info : '%c'\n", WHATKEY); printf("\nGENERAL:\n"); printf(" Reset positions + velocities : '%c'\n", RESETKEY); printf(" Switch to other renderer : '%c'\n", RENDKEY); printf(" Toggle vertical gravity : '%c'\n", GRAVKEY); printf(" PAUSE/UNPAUSE : '%c'\n", PAUSEKEY); printf("QUIT : '%c'\n", QUITKEY); printf("\n\n\n\n"); printf("run program with -h to see a list of command line options\n"); printf(" e.g. -x 800 -y 600 or somesuch.\n\n\n"); printf("Any and all feedback is really welcome, so please \n"); printf("send patches, advice, ideas, thoughts etc. to\n"); printf("\tsr@pepcross.com\n"); printf("\n\n"); key=0; } #ifdef DEBUG if (key) printf("I don't know how to handle %c\n", key); #endif } } int main(int argc, char *argv[]) { int showusage=0; int optchar; Particle_Sys psys; struct timeval tp1,tp2; struct timezone tz; Gfx g; g.default_xres = 800; g.default_yres = 600; /* Defaults for Particle System */ int fperforcesys=0; /* Defaults for imaging */ unsigned char brightness=50; /* Variables required by frames/per/second calculations */ int frame=0; int framelimit=0; signalhandler(); showusage=0; gettimeofday(&tp1,&tz); // get starttime g.renderer = (tp1.tv_usec)&01; // randomize which renderer we use psys.n_particles=5000; psys_set_defaults(&psys); g.base_colour=0xccaaff; g.rootwin=0; /* DUMB ARGUMENT HANDLING */ while ((optchar = getopt(argc, argv, "i:m:fhRrn:x:y:b:c:l:")) != -1) switch (optchar) { case 'm' : fperforcesys=atoi(optarg); break; case 'l' : framelimit =atoi(optarg); break; case 'r' : g.rootwin =1; break; case 'R' : g.renderer =1; break; case 'n' : psys.n_particles=atoi(optarg); break; case 'x' : g.xres=atoi(optarg); break; case 'y' : g.yres=atoi(optarg); break; case 'h' : showusage=1; break; case 'b' : brightness=atoi(optarg); break; case 'c' : g.base_colour=strtol(optarg,0,16); break; case 'i' : psys.loadimage=(char *) malloc (strlen(optarg)); strcpy(psys.loadimage, optarg); break; default: showusage=1; } argc -= optind; argv += optind; if (showusage) show_usage(argv[-optind]); if (framelimit) printf("Showing %d frames and quitting\n", framelimit); ilimit("Number of frames before changing to next force mode", &fperforcesys, 0, 10000); ilimit("Number of frames to show", &framelimit, 0, 10000); ilimit("numParticles", &(psys.n_particles), 1, 2000000); #ifdef DEBUG printf("Running with brightness %d\n", brightness); #endif /* Setup structures */ if (!gfx_SetupGfx(&g)) { fprintf(stderr, "Unable to initialise graphics routines\n"); return 1; } psys_create_particles(&psys); /* Main loop - FIXME, should a use proper Xlib event loop really */ handle_keyboard_io(&g, &psys, 1); // init tz.tz_minuteswest=tz.tz_dsttime=0; /* Ignore timezone */ gettimeofday(&tp1, &tz); gettimeofday(&tp2, &tz); // per frame int delay =0; while (cleanup_and_exit==0 && (!framelimit || (frame0?delay:0); } if (cleanup_and_exit!=0) printf("Exiting due to received signal\n"); gfx_cleanup(&g); return 1; }