FreeWRL/FreeX3D  3.0.0
SnapshotTesting.c
1 /****************************************************************************
2  This file is part of the FreeWRL/FreeX3D Distribution.
3 
4  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
5 
6  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
18 ****************************************************************************/
19 
20 //#define USE_SNAPSHOT_TESTING 1
21 #ifndef USE_SNAPSHOT_TESTING
22 //stubs for options
23 void fwl_set_modeRecord()
24 {
25 }
26 void fwl_set_modeFixture()
27 {
28 }
29 void fwl_set_modePlayback()
30 {
31 }
32 void fwl_set_nameTest(char *nameTest)
33 {
34 }
35 #endif //ifndef USE_SNAPSHOT_TESTING
36 
37 
38 #ifdef USE_SNAPSHOT_TESTING
39 
40 /* SnapshotTesting
41 - a process to do regression testing
42 - implemented as an insertible 'layer' in freewrl
43 
44 http://freewrl.sourceforge.net/use.html
45 Commmand Line Options - Testing
46 
47 Developers working on desktop configurations of freewrl can automate testing by comparing
48 before- and after- snapshot images and log files.
49 
50 There are 3 steps to the testing process:
51 A) generate test playback files:
52  freewrl 1.wrl -R -N t1
53  generates /recording/t1.fwplay
54  In order to generate test fixtures, you need to take a snapshot of the graphics window
55  using the 'x' key, and/or for non-visual tests, log something to the log file by toggling
56  logging on with the "`" key, doing some functions that write to the console such as "/" command,
57  toggle logging off with "`", and press 'q' to exit gracefully.
58  (some temporary files will appear in /freewrl_tmp but are not needed).
59  During this sesssion the frame rate is slowed -to minimize the size of the .fwplay file
60  and speed up test playback- and your mouse and keyboard actions are recorded on each frame,
61  to the .fwplay file.
62 B) before making a change to the code, run the playback files to generate test fixtures:
63  freewrl -F -N t1
64  generates /fixture/t1.0001.bmp test fixture, assuming you hit the 'x' snapshot during the recording step,
65  and /fixture/t1.log if you toggled logging on during recording
66 C) after making each small code change:
67  i) re-run the playback files
68  freewrl -P -N t1
69  generates /playback/t1.0001.bmp and/or /playback/t1.log
70  ii) compare /playback/testname.* to the /fixture/testname.* files
71  For this you'll need a perl script doing a file compare between the /fixture and /playback versions.
72  If any tests break by not comparing identically playback to fixture,
73  that means you changed the functionality of the code.
74  Sometimes that's what you want. In that case check which tests failed to see if
75  there are unintended side-effects. If all OK, then generate new fixtures.
76  Sometimes you want to refactor code: change its structure without changing its functionality.
77  In this case if you break any test, roll back your last code change.
78 
79 Summary of testing command line options:
80 
81 -N or --nametest testname
82  Sets the .fwplay, snapshot image and logfile prefix to testname.
83  During recording /recording/testname.fwplay test playback file is generated,
84  and during fixture it's read, and /fixture/testname.0001.bmp (or .png) and/or /fixture/testname.log
85  is generated, depending on what actions you took during recording.
86  If you don't set this option, testname defaults to your scene basename,
87  except with the .suffix changed to _suffix. Example 1.wrl defaults to 1_wrl.fwplay.
88 -R or --record
89  Generates /recording/testname.fwplay test playback file.
90 -F or --fixture
91  Generates /fixture/testname.0001.bmp or .png, and/or /fixture/testname.log depending
92  on whether you did a snapshot and/or log command during recording.
93 -P or --playback
94  Identical to option -F or --fixture except puts test fixtures into /playback folder.
95 
96 */
97 
98 
99 
100 
101 #include <stdio.h>
102 #include <iglobal.h>
103 #include <internal.h>
104 void set_snapshotModeTesting(int value); //snapshot.c
105 int isSnapshotModeTesting(); //snapshot.c
106 
107 
108 #define FALSE 0
109 #define TRUE 1
110 
111 struct keypressTuple{
112  int key;
113  int type;
114 };
115 struct mouseTuple{
116  int mev;
117  unsigned int button;
118  float x;
119  float y;
120  int ix;
121  int iy;
122  int ID;
123 };
124 struct playbackRecord {
125  int frame;
126  double dtime;
127  //should we use more general Touch instead of mouse-specific?
128  int *mousetuples; //x,y,button chord
129  int mouseCount; //# mouse tuples
130  char *keystrokes;
131  int keyCount;
132 };
133 
134 typedef struct tSnapshotTesting{
135  void *prv;
136  } tSnapshotTesting;
137 static tSnapshotTesting SnapshotTesting;
138 
139 
140 typedef struct pSnapshotTesting{
141  FILE* recordingFile;
142  char* recordingFName;
143  int modeRecord;
144  int modeFixture;
145  int modePlayback;
146  int fwplayOpened;
147  char *nameTest;
148  int frameNum; //for Record, Playback - frame# =0 after scene loaded
149  struct playbackRecord* playback;
150  int playbackCount;
151 
152  struct keypressTuple keypressQueue[50]; //for Record,Playback where keypresses are applied just once per frame for consistency
153  int keypressQueueCount;
154  struct mouseTuple mouseQueue[50];
155  int mouseQueueCount;
156 
157 }* ppSnapshotTesting;
158 void *SnapshotTesting_constructor(){
159  void *v = MALLOCV(sizeof(struct pSnapshotTesting));
160  memset(v,0,sizeof(struct pSnapshotTesting));
161  return v;
162 }
163 void SnapshotTesting_init(struct tSnapshotTesting *t){
164  //public
165  //private
166  t->prv = SnapshotTesting_constructor();
167  {
168  ppSnapshotTesting p = (ppSnapshotTesting)t->prv;
169  p->recordingFile = NULL;
170  p->recordingFName = NULL;
171  p->modeRecord = FALSE;
172  p->modeFixture = FALSE;
173  p->modePlayback = FALSE;
174  p->nameTest = NULL;
175  p->frameNum = 0;
176  p->playbackCount = 0;
177  p->playback = NULL;
178  p->fwplayOpened = 0;
179 
180  p->keypressQueueCount=0;
181  p->mouseQueueCount=0;
182  }
183 }
184 void SnapshotTesting_setHandlers();
185 
186 static int rtestinit = 0;
187 static ppSnapshotTesting get_ppSnapshotTesting(){
188  if(!rtestinit){
189  SnapshotTesting_init(&SnapshotTesting);
190  rtestinit = 1;
191  ppSnapshotTesting p = (ppSnapshotTesting)SnapshotTesting.prv;
192  SnapshotTesting_setHandlers();
193  }
194  return (ppSnapshotTesting)SnapshotTesting.prv;
195 }
196 
197 int dequeueKeyPress(ppSnapshotTesting p,int *key, int *type){
198  if(p->keypressQueueCount > 0){
199  int i;
200  p->keypressQueueCount--;
201  *key = p->keypressQueue[0].key;
202  *type = p->keypressQueue[0].type;
203  for(i=0;i<p->keypressQueueCount;i++){
204  p->keypressQueue[i].key = p->keypressQueue[i+1].key;
205  p->keypressQueue[i].type = p->keypressQueue[i+1].type;
206  }
207  return 1;
208  }
209  return 0;
210 }
211 
212 void queueKeyPress(ppSnapshotTesting p, int key, int type){
213  if(p->keypressQueueCount < 50){
214  p->keypressQueue[p->keypressQueueCount].key = key;
215  p->keypressQueue[p->keypressQueueCount].type = type;
216  p->keypressQueueCount++;
217  }
218 }
219 
220 int dequeueMouse(ppSnapshotTesting p, int *mev, unsigned int *button, float *x, float *y){
221  if(p->mouseQueueCount > 0){
222  int i;
223  p->mouseQueueCount--;
224  *mev = p->mouseQueue[0].mev;
225  *button = p->mouseQueue[0].button;
226  *x = p->mouseQueue[0].x;
227  *y = p->mouseQueue[0].y;
228  for(i=0;i<p->mouseQueueCount;i++){
229  p->mouseQueue[i].mev = p->mouseQueue[i+1].mev;
230  p->mouseQueue[i].button = p->mouseQueue[i+1].button;
231  p->mouseQueue[i].x = p->mouseQueue[i+1].x;
232  p->mouseQueue[i].y = p->mouseQueue[i+1].y;
233  }
234  return 1;
235  }
236  return 0;
237 }
238 int dequeueMouseMulti(ppSnapshotTesting p, int *mev, unsigned int *button, int *ix, int *iy, int *ID){
239  if(p->mouseQueueCount > 0){
240  int i;
241  p->mouseQueueCount--;
242  *mev = p->mouseQueue[0].mev;
243  *button = p->mouseQueue[0].button;
244  *ix = p->mouseQueue[0].ix;
245  *iy = p->mouseQueue[0].iy;
246  *ID = p->mouseQueue[0].ID;
247  for(i=0;i<p->mouseQueueCount;i++){
248  p->mouseQueue[i].mev = p->mouseQueue[i+1].mev;
249  p->mouseQueue[i].button = p->mouseQueue[i+1].button;
250  p->mouseQueue[i].ix = p->mouseQueue[i+1].ix;
251  p->mouseQueue[i].iy = p->mouseQueue[i+1].iy;
252  p->mouseQueue[i].ID = p->mouseQueue[i+1].ID;
253  }
254  return 1;
255  }
256  return 0;
257 }
258 
259 void queueMouseMulti(ppSnapshotTesting p, const int mev, const unsigned int button, const int ix, const int iy, int ID){
260  if(p->mouseQueueCount < 50){
261  p->mouseQueue[p->mouseQueueCount].mev = mev;
262  p->mouseQueue[p->mouseQueueCount].button = button;
263  p->mouseQueue[p->mouseQueueCount].ix = ix;
264  p->mouseQueue[p->mouseQueueCount].iy = iy;
265  p->mouseQueue[p->mouseQueueCount].ID = ID;
266  p->mouseQueueCount++;
267  }
268 }
269 void queueMouse(ppSnapshotTesting p, const int mev, const unsigned int button, const float x, const float y){
270  if(p->mouseQueueCount < 50){
271  p->mouseQueue[p->mouseQueueCount].mev = mev;
272  p->mouseQueue[p->mouseQueueCount].button = button;
273  p->mouseQueue[p->mouseQueueCount].x = x;
274  p->mouseQueue[p->mouseQueueCount].y = y;
275  p->mouseQueueCount++;
276  }
277 }
278 
279 
280 void handleTESTING(const int mev, const unsigned int button, const float x, const float y)
281 {
282  ppSnapshotTesting p;
283  //ttglobal tg = gglobal();
284  //p = (ppSnapshotTesting)tg->SnapshotTesting.prv;
285  p = get_ppSnapshotTesting();
286 
287  //if(0)
288  if(p->modeRecord || p->modeFixture || p->modePlayback){
289  if(p->modeRecord){
290  queueMouse(p,mev,button,x,y);
291  }
292  //else ignor so test isn't ruined by random mouse movement during playback
293  return;
294  }
295  handle0(mev, button, x, y);
296 }
297 void fwl_do_keyPress0(int key, int type);
298 void fwl_do_rawKeyPressTESTING(int key, int type) {
299  ppSnapshotTesting p;
300  //ttglobal tg = gglobal();
301  //p = (ppSnapshotTesting)tg->SnapshotTesting.prv;
302  p = get_ppSnapshotTesting();
303 
304  if(p->modeRecord){
305  queueKeyPress(p,key,type);
306  }else{
307  fwl_do_keyPress0(key,type);
308  }
309 }
310 void fwl_handle_aqua_multiNORMAL(const int mev, const unsigned int button, int x, int y, int ID);
311 void fwl_handle_aqua_multiTESTING(const int mev, const unsigned int button, int x, int y, int ID)
312 {
313  ppSnapshotTesting p;
314  //ttglobal tg = gglobal();
315  //p = (ppSnapshotTesting)tg->SnapshotTesting.prv;
316  p = get_ppSnapshotTesting();
317 
318  if(p->modeRecord || p->modeFixture || p->modePlayback){
319  if(p->modeRecord){
320  queueMouseMulti(p,mev,button,x,y,ID);
321  }
322  //else ignor so test isn't ruined by random mouse movement during playback
323  return;
324  }
325  fwl_handle_aqua_multiNORMAL(mev, button, x, y, ID);
326 }
327 
328 void fwl_set_modeRecord()
329 {
330  ppSnapshotTesting p;
331  //ttglobal tg = gglobal();
332  //p = (ppSnapshotTesting)tg->SnapshotTesting.prv;
333  p = get_ppSnapshotTesting();
334  p->modeRecord = TRUE;
335 }
336 void fwl_set_modeFixture()
337 {
338  ppSnapshotTesting p;
339  //ttglobal tg = gglobal();
340  //p = (ppSnapshotTesting)tg->SnapshotTesting.prv;
341  p = get_ppSnapshotTesting();
342  p->modeFixture = TRUE;
343 }
344 void fwl_set_modePlayback()
345 {
346  ppSnapshotTesting p;
347  //ttglobal tg = gglobal();
348  //p = (ppSnapshotTesting)tg->SnapshotTesting.prv;
349  p = get_ppSnapshotTesting();
350  p->modePlayback = TRUE;
351 }
352 void fwl_set_nameTest(char *nameTest)
353 {
354  ppSnapshotTesting p;
355  //ttglobal tg = gglobal();
356  //p = (ppSnapshotTesting)tg->SnapshotTesting.prv;
357  p = get_ppSnapshotTesting();
358  p->nameTest = STRDUP(nameTest);
359 }
360 
361 char *nameLogFileFolderTESTING(char *logfilename, int size){
362  ppSnapshotTesting p;
363  ttglobal tg = gglobal();
364  //p = (ppSnapshotTesting)tg->SnapshotTesting.prv;
365  p = get_ppSnapshotTesting();
366 
367  if(p->modePlayback || p->modeFixture){
368  if(p->modePlayback)
369  strcat(logfilename,"playback");
370  else
371  strcat(logfilename,"fixture");
372  fw_mkdir(logfilename);
373  strcat(logfilename,"/");
374  if(p->nameTest){
375  // /fixture/test1.log
376  strcat(logfilename,p->nameTest);
377  }else if(tg->Mainloop.scene_name){
378  // /fixture/1_wrl.log
379  strcat(logfilename,tg->Mainloop.scene_name);
380  if(tg->Mainloop.scene_suff){
381  strcat(logfilename,"_");
382  strcat(logfilename,tg->Mainloop.scene_suff);
383  }
384  }
385  }else{
386  nameLogFileFolderNORMAL(logfilename,size);
387  }
388  return logfilename;
389 }
390 
391 
392 int fw_mkdir(char* path);
393 void fwl_RenderSceneUpdateScene0(double dtime);
394 void fwl_RenderSceneUpdateSceneTESTING() {
395  double dtime;
396  //ttglobal tg = gglobal();
397  //ppMainloop p = (ppMainloop)tg->Mainloop.prv;
398  ppSnapshotTesting p;
399  ttglobal tg = gglobal();
400  //p = (ppSnapshotTesting)tg->SnapshotTesting.prv;
401  p = get_ppSnapshotTesting();
402 
403 
404  dtime = Time1970sec();
405  if((p->modeRecord || p->modeFixture || p->modePlayback)) //commandline --record/-R and --playback/-P, for automated testing
406  {
407  //functional testing support options May 2013
408  //records frame#, dtime, keyboard, mouse to an ASCII .fwplay file for playback
409  //to record, run a scene file with -R or --record option
410  //copy the .fwplay between platforms
411  //before starting refactoring, run scenes with -F or --fixture option,
412  // and hit the 'x' key to save a snapshot one or more times per fixture run
413  //after each refactoring step, run scenes with -P or --playback option,
414  // and (with perl script) do a file compare(fixture_snapshot,playback_snapshot)
415  //
416  //on the command line use:
417  //-R to just record the .fwplay file
418  //-F to play recording and save as fixture
419  //-P to play recording and save as playback
420  //-R -F to record and save as fixture in one step
421  //command line long option equivalents: -R --record, -F --fixture, -P --playback
422  int key;
423  int type;
424  int mev,ix,iy,ID;
425  unsigned int button;
426  float x,y;
427  char buff[1000], keystrokes[200], mouseStr[1000];
428  int namingMethod;
429  char *folder;
430  char sceneName[1000];
431  //naming method for related files (and folders)
432  //0=default: recording.fwplay, fixture.bmp playback.bmp - will overwrite for each scene
433  //1=folders: 1_wrl/recording.fwplay, 1_wrl/fixture/17.bmp, 1_wrl/playback/17.bmp
434  //2=flattened: 1_wrl.fwplay, 1_wrl_fixture_17.bmp, 1_wrl_playback_17.bmp (17 is frame#)
435  //3=groupfolders: /tests, /recordings/*.fwplay, /fixtures/1_wrl_17.bmp /playbacks/1_wrl_17.bmp
436  //4=groupfolders: /tests, /recordings/*.fwplay, /fixtures/1_wrl_17.bmp /playbacks/1_wrl_17.bmp
437  // - 4 same as 3, except done to harmonize with linux/aqua naming approach:
438  // - fwl_set_SnapFile(path = {"fixture" | "playback" }); to set mytmp
439  // -
440  folder = NULL;
441  namingMethod = 4;
442  //if(p->frameNum == 1){
443  if(!p->fwplayOpened){
444  char recordingName[1000];
445  int j,k;
446  p->fwplayOpened = 1;
447  recordingName[0] = '\0';
448  sceneName[0] = '\0';
449  if(tg->Mainloop.scene_name){
450  strcat(sceneName,tg->Mainloop.scene_name);
451  if(tg->Mainloop.scene_suff){
452  strcat(sceneName,".");
453  strcat(sceneName,tg->Mainloop.scene_suff);
454  }
455  }
456  if(namingMethod==3 || namingMethod==4){
457  strcpy(recordingName,"recording");
458  fw_mkdir(recordingName);
459  strcat(recordingName,"/");
460  }
461  if(namingMethod>0){
462  if(p->nameTest){
463  strcat(recordingName,p->nameTest);
464  }else{
465  strcat(recordingName,tg->Mainloop.scene_name);
466  k = strlen(recordingName);
467  if(k){
468  //1.wrl -> 1_wrl
469  j = strlen(tg->Mainloop.scene_suff);
470  if(j){
471  strcat(recordingName,"_");
472  strcat(recordingName,tg->Mainloop.scene_suff);
473  }
474  }
475  }
476  }
477  if(namingMethod==1){
478  fw_mkdir(recordingName);
479  strcat(recordingName,"/recording"); //recording.fwplay a generic name, in case there's no scene name
480  }
481  if(namingMethod==0)
482  strcat(recordingName,"recording");
483  strcat(recordingName,".fwplay"); //1_wrl.fwplay
484  p->recordingFName = STRDUP(recordingName);
485 
486  if(p->modeFixture || p->modePlayback){
487  if(!p->modeRecord){
488  p->recordingFile = fopen(p->recordingFName, "r");
489  if(p->recordingFile == NULL){
490  printf("ouch recording file %s not found\n", p->recordingFName);
491  fw_exit(1);
492  }
493  if( fgets(buff, 1000, p->recordingFile) != NULL){
494  char window_widthxheight[100], equals[50];
495  int width, height;
496  //window_wxh = 600,400
497  if( sscanf(buff,"%s %s %d, %d\n",window_widthxheight,equals, &width,&height) == 4) {
498  if(width != tg->display.screenWidth || height != tg->display.screenHeight){
499  //right now all we can do is passively complain
500  printf("Ouch - the test playback window size is different than recording:\n");
501  printf("recording %d x %d playback %d x %d\n",width,height,
502  tg->display.screenWidth,tg->display.screenHeight);
503  printf("hit Enter:");
504  getchar();
505  }
506  }
507  }
508  if( fgets(buff, 1000, p->recordingFile) != NULL){
509  char scenefile[100], equals[50];
510  //scenefile = 1.wrl
511  if( sscanf(buff,"%s %s %s \n",scenefile,equals, sceneName) == 3) {
512  if(!tg->Mainloop.scene_name){
513  char* suff = NULL;
514  char* local_name = NULL;
515  char* url = NULL;
516  if(strlen(sceneName)) url = STRDUP(sceneName);
517  if(url){
518  splitpath_local_suffix(url, &local_name, &suff);
519  gglobal()->Mainloop.url = url;
520  gglobal()->Mainloop.scene_name = local_name;
521  gglobal()->Mainloop.scene_suff = suff;
522  fwl_resource_push_single_request(url);
523  }
524  }
525  }
526  }
527  }
528  }
529  }
530  int doEvents = (!fwl_isinputThreadParsing()) && (!fwl_isTextureParsing()) && fwl_isInputThreadInitialized();
531  //printf("frame %d doevents=%d\n",p->frameNum,p->doEvents);
532  if(!doEvents)
533  return; //for Record and Playback, don't start doing things until scene and textures are loaded
534  if(p->modeRecord)
535  if(dtime - tg->Mainloop.TickTime < .5) return; //slow down frame rate to 2fps to reduce empty meaningless records
536  p->frameNum++; //for record, frame relative to when scene is loaded
537 
538  if(p->modeRecord){
539  int i;
540  char temp[1000];
541  if(p->frameNum == 1){
542  p->recordingFile = fopen(p->recordingFName, "w");
543  if(p->recordingFile == NULL){
544  printf("ouch recording file %s not found\n", p->recordingFName);
545  fw_exit(1);
546  }
547  //put in a header record, passively showing window widthxheight
548  fprintf(p->recordingFile,"window_wxh = %d, %d \n",tg->display.screenWidth,tg->display.screenHeight);
549  fprintf(p->recordingFile,"scenefile = %s \n",tg->Mainloop.url); //sceneName);
550  }
551  strcpy(keystrokes,"\"");
552  while(dequeueKeyPress(p,&key,&type)){
553  sprintf(temp,"%d,%d,",key,type);
554  strcat(keystrokes,temp);
555  }
556  strcat(keystrokes,"\"");
557  strcpy(mouseStr,"\"");
558  i = 0;
559  while(dequeueMouseMulti(p,&mev, &button, &ix, &iy, &ID)){
560  sprintf(temp,"%d,%d,%d,%d,%d;",mev,button,ix,iy,ID);
561  strcat(mouseStr,temp);
562  i++;
563  }
564  strcat(mouseStr,"\"");
565  fprintf(p->recordingFile,"%d %.6lf %s %s\n",p->frameNum,dtime,keystrokes,mouseStr);
566  //in case we are -R -F together,
567  //we need to round dtime for -F like it will be coming out of .fwplay for -P
568  sprintf(temp,"%.6lf",dtime);
569  sscanf(temp,"%lf",&dtime);
570  //folder = "fixture";
571  folder = NULL;
572  }
573  if(p->modeFixture || p->modePlayback){
574  if(!p->modeRecord){
575  // playback[i] = {iframe, dtime, keystrokes or NULL, mouse (xy,button sequence) or NULL, snapshot URL or NULL, scenegraph_dump URL or NULL, ?other?}
576  if( fgets( buff, 1000, p->recordingFile ) != NULL ) {
577  if(sscanf(buff,"%d %lf %s %s\n",&p->frameNum,&dtime,keystrokes,mouseStr) == 4){ //,snapshotURL,scenegraphURL) == 6){
578  if(0) printf("%d %lf %s %s\n",p->frameNum,dtime,keystrokes,mouseStr);
579  }
580  }
581  }
582  if(p->modeFixture) folder = "fixture";
583  if(p->modePlayback) folder = "playback";
584  }
585  //for all 3 - read the keyboard string and the mouse string
586  if(p->modeRecord || p->modeFixture || p->modePlayback){
587  if(strlen(keystrokes)>2){ // "x,1," == 6
588  char *next,*curr;
589  //count the number of ','
590  //for(i=0,n=0;i<strlen(keystrokes);i++) if(keystrokes[i] == ',') n++; //(strlen(keystrokes) -2)/4;
591  //n /= 2; //each keystroke has 2 commas: (char),(type),
592  curr = &keystrokes[1]; //skip leading "
593  while(curr && strlen(curr)>1){
594  //for(i=0;i<n;i++){
595  //ii = i*4 +1;
596  //sscanf(&keystrokes[ii],"%d,%d",&key,&type);
597  sscanf(curr,"%d",&key);
598  next = strchr(curr,',');
599  curr = &next[1];
600  sscanf(curr,"%d",&type);
601  next = strchr(curr,',');
602  curr = &next[1];
603  if(p->modeFixture || p->modePlayback){
604  //we will catch the snapshot keybaord command and prepare the
605  //snapshot filename and folder/directory for fixture and playback
606  if(key == 'x'){
607  //prepare snapshot folder(scene/ + fixture ||playback)
608  // and file name(frame#)
609  char snapfile[5];
610 #ifdef _MSC_VER
611  char *suff = ".bmp";
612 #else
613  char *suff = ".snap";
614 #endif
615  sprintf(snapfile,"%d",p->frameNum);
616  if(namingMethod == 0){
617  //default: recording.bmp, playback.bmp
618  char snappath[100];
619  strcpy(snappath,folder);
620  strcat(snappath,suff);
621  fwl_set_SnapFile(snappath);
622  }
623  if(namingMethod==1){
624  //nested folder approach
625  //1=folders: 1_wrl/recording.fwplay, 1_wrl/fixture/17.bmp, 1_wrl/playback/17.bmp
626  int k,j;
627  char snappath[100];
628  strcpy(snappath,tg->Mainloop.scene_name);
629  k = strlen(snappath);
630  if(k){
631  //1.wrl -> 1_wrl
632  j = strlen(tg->Mainloop.scene_suff);
633  if(j){
634  strcat(snappath,"_");
635  strcat(snappath,tg->Mainloop.scene_suff);
636  }
637  }
638  strcat(snappath,"/");
639  strcat(snappath,folder);
640  fw_mkdir(snappath); //1_wrl/fixture
641  //fwl_set_SnapTmp(snappath); //sets the folder for snaps
642  strcat(snappath,"/");
643  strcat(snappath,snapfile);
644  strcat(snappath,suff); //".bmp");
645  //fwl_set_SnapFile(snapfile);
646  fwl_set_SnapFile(snappath); //1_wrl/fixture/17.bmp
647  }
648  if(namingMethod == 2){
649  //flattened filename approach with '_'
650  //if snapshot 'x' is on frame 17, and fixture,
651  // then 1_wrl_fixture_17.snap or .bmp
652  char snappath[100];
653  int j, k;
654  strcpy(snappath,tg->Mainloop.scene_name);
655  k = strlen(snappath);
656  if(k){
657  j= strlen(tg->Mainloop.scene_suff);
658  if(j){
659  strcat(snappath,"_");
660  strcat(snappath,tg->Mainloop.scene_suff);
661  }
662  strcat(snappath,"_");
663  }
664  strcat(snappath,folder);
665  strcat(snappath,"_");
666  strcat(snappath,snapfile);
667  strcat(snappath,suff); //".bmp");
668  fwl_set_SnapFile(snappath);
669  }
670  if(namingMethod == 3){
671  //group folder
672  //if snapshot 'x' is on frame 17, and fixture,
673  // then fixture/1_wrl_17.snap or .bmp
674  char snappath[100];
675  int j, k;
676  strcpy(snappath,folder);
677  fw_mkdir(snappath); // /fixture
678  strcat(snappath,"/");
679  strcat(snappath,tg->Mainloop.scene_name); // /fixture/1
680  k = strlen(tg->Mainloop.scene_name);
681  if(k){
682  j= strlen(tg->Mainloop.scene_suff);
683  if(j){
684  strcat(snappath,"_");
685  strcat(snappath,tg->Mainloop.scene_suff);
686  }
687  strcat(snappath,"_");
688  }
689  strcat(snappath,snapfile);
690  strcat(snappath,suff); //".bmp");
691  fwl_set_SnapFile(snappath); // /fixture/1_wrl_17.bmp
692  }
693  if(namingMethod == 4){
694  //group folder
695  //if snapshot 'x' is the first one .0001, and fixture,
696  // then fixture/1_wrl.0001.rgb or .bmp
697  char snappath[100];
698  char *sep = "_"; // "." or "_" or "/"
699  set_snapshotModeTesting(TRUE);
700  //if(isSnapshotModeTesting())
701  // printf("testing\n");
702  //else
703  // printf("not testing\n");
704  strcpy(snappath,folder);
705  fw_mkdir(snappath); // /fixture
706  fwl_set_SnapTmp(snappath);
707 
708  snappath[0] = '\0';
709  if(p->nameTest){
710  strcat(snappath,p->nameTest);
711  }else{
712  if(tg->Mainloop.scene_name){
713  strcat(snappath,tg->Mainloop.scene_name); // /fixture/1
714  if(tg->Mainloop.scene_suff)
715  {
716  strcat(snappath,sep); // "." or "_");
717  strcat(snappath,tg->Mainloop.scene_suff);
718  }
719  }
720  }
721  fwl_set_SnapFile(snappath); // /fixture/1_wrl.001.bmp
722 
723  }
724  }
725  }
726  fwl_do_keyPress0(key, type);
727  }
728  }
729  if(strlen(mouseStr)>2){
730  int i,ii,len;
731  int mev;
732  unsigned int button;
733  float x,y;
734  len = strlen(mouseStr);
735  ii=1;
736  do{
737  for(i=ii;i<len;i++)
738  if(mouseStr[i] == ';') break;
739 
740  sscanf(&mouseStr[ii],"%d,%d,%d,%d,%d;",&mev,&button,&ix,&iy,&ID);
741  fwl_handle_aqua_multiNORMAL(mev,button,ix,iy,ID);
742 
743  //printf("%d,%d,%f,%f;",mev,button,x,y);
744  ii=i+1;
745  }while(ii<len-1);
746  }
747  }
748  }
749  fwl_RenderSceneUpdateScene0(dtime);
750 }
751 extern void (*fwl_do_rawKeyPressPTR)(int key, int type);
752 extern void (*fwl_handle_aqua_multiPTR)(const int mev, const unsigned int button, int x, int y, int ID);
753 extern void (*fwl_RenderSceneUpdateScenePTR)();
754 extern void (*handlePTR)(const int mev, const unsigned int button, const float x, const float y);
755 extern char * (*nameLogFileFolderPTR)(char *logfilename, int size);
756 void SnapshotTesting_setHandlers(){
757  fwl_do_rawKeyPressPTR = fwl_do_rawKeyPressTESTING;
758  fwl_handle_aqua_multiPTR = fwl_handle_aqua_multiTESTING;
759  fwl_RenderSceneUpdateScenePTR = fwl_RenderSceneUpdateSceneTESTING;
760  handlePTR = handleTESTING;
761  nameLogFileFolderPTR = nameLogFileFolderTESTING;
762 }
763 
764 #endif //USE_SNAPSHOT_TESTING
Definition: Viewer.h:174