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