Blender V2.61 - r43446

MultiTest.c

Go to the documentation of this file.
00001 
00027 #define FALSE 0
00028 
00029 #ifdef WIN32
00030 
00031 #pragma warning(disable: 4244 4305)
00032 #endif
00033 
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <stdio.h>
00037 #include <math.h>
00038 
00039 #include "GL.h"
00040 
00041 #include "MEM_guardedalloc.h"
00042 
00043 #include "GHOST_C-api.h"
00044 
00045 #ifdef USE_BMF
00046 #  include "BMF_Api.h"
00047 #else
00048 #  include "BLF_api.h"
00049    extern int datatoc_bfont_ttf_size;
00050    extern char datatoc_bfont_ttf[];
00051 
00052    /* cheat */
00053    char U[1024]= {0};
00054 #endif
00055 
00056 #include "Util.h"
00057 #include "Basic.h"
00058 #include "ScrollBar.h"
00059 #include "EventToBuf.h"
00060 
00061 #include "WindowData.h"
00062 
00063 /***/
00064 
00065 typedef struct _MultiTestApp MultiTestApp;
00066 typedef struct _LoggerWindow LoggerWindow;
00067 
00068 void loggerwindow_log(LoggerWindow *lw, char *line);
00069 
00070 void multitestapp_toggle_extra_window(MultiTestApp *app);
00071 void multitestapp_free_extrawindow(MultiTestApp *app);
00072 LoggerWindow *multitestapp_get_logger(MultiTestApp *app);
00073 GHOST_SystemHandle multitestapp_get_system(MultiTestApp *app);
00074 void multitestapp_exit(MultiTestApp *app);
00075 
00076 
00077 
00078 void rect_bevel_side(int rect[2][2], int side, float *lt, float *dk, float *col, int width) {
00079     int ltidx= (side/2)%4;
00080     int dkidx= (ltidx + 1 + (side&1))%4;
00081     int i, corner;
00082     
00083     glBegin(GL_LINES);
00084     for (i=0; i<width; i++) {
00085         float ltf= pow(lt[i], 1.0/2.2), dkf= pow(dk[i], 1.0/2.2);
00086         float stf= (dkidx>ltidx)?dkf:ltf;
00087         int lx= rect[1][0]-i-1;
00088         int ly= rect[0][1]+i;
00089         
00090         glColor3f(col[0]*stf, col[1]*stf, col[2]*stf);
00091         for (corner=0; corner<4; corner++) {
00092             int x= (corner==0 || corner==1)?(rect[0][0]+i):(rect[1][0]-i-1);
00093             int y= (corner==0 || corner==3)?(rect[0][1]+i):(rect[1][1]-i-1);
00094 
00095             if (ltidx==corner)
00096                 glColor3f(col[0]*ltf, col[1]*ltf, col[2]*ltf);
00097             if (dkidx==corner)
00098                 glColor3f(col[0]*dkf, col[1]*dkf, col[2]*dkf);
00099 
00100             glVertex2i(lx, ly);
00101             glVertex2i(lx= x, ly= y);
00102         }
00103     }
00104     glEnd();
00105     
00106     glColor3fv(col);
00107     glRecti(rect[0][0]+width, rect[0][1]+width, rect[1][0]-width, rect[1][1]-width);
00108 }
00109 
00110 void rect_bevel_smooth(int rect[2][2], int width) {
00111     float *lt= malloc(sizeof(*lt)*width);
00112     float *dk= malloc(sizeof(*dk)*width);
00113     float col[4];
00114     int i;
00115     
00116     for (i=0; i<width; i++) {
00117         float v= width-1?((float) i/(width-1)):0;
00118         lt[i]= 1.2 + (1.0-1.2)*v;
00119         dk[i]= 0.2 + (1.0-0.2)*v;
00120     }
00121     
00122     glGetFloatv(GL_CURRENT_COLOR, col);
00123     
00124     rect_bevel_side(rect, 3, lt, dk, col, width);
00125     
00126     free(lt);
00127     free(dk);
00128 }
00129 
00130     /*
00131      * MainWindow
00132      */
00133 
00134 typedef struct {
00135     MultiTestApp        *app;
00136 
00137     GHOST_WindowHandle  win;
00138     
00139     int     size[2];
00140     
00141     int     lmouse[2], lmbut[3];
00142     
00143     int     tmouse[2];
00144 } MainWindow;
00145 
00146 static void mainwindow_log(MainWindow *mw, char *str) {
00147     loggerwindow_log(multitestapp_get_logger(mw->app), str);
00148 }
00149 
00150 static void mainwindow_do_draw(MainWindow *mw) {
00151     GHOST_ActivateWindowDrawingContext(mw->win);
00152     
00153     if (mw->lmbut[0]) {
00154         glClearColor(0.5, 0.5, 0.5, 1);
00155     } else {
00156         glClearColor(1, 1, 1, 1);
00157     }       
00158     glClear(GL_COLOR_BUFFER_BIT);
00159     
00160     glColor3f(0.5, 0.6, 0.8);
00161     glRecti(mw->tmouse[0]-5, mw->tmouse[1]-5, mw->tmouse[0]+5, mw->tmouse[1]+5);
00162     
00163     GHOST_SwapWindowBuffers(mw->win);
00164 }
00165 
00166 static void mainwindow_do_reshape(MainWindow *mw) {
00167     GHOST_RectangleHandle bounds= GHOST_GetClientBounds(mw->win);
00168 
00169     GHOST_ActivateWindowDrawingContext(mw->win);
00170 
00171     mw->size[0]= GHOST_GetWidthRectangle(bounds);
00172     mw->size[1]= GHOST_GetHeightRectangle(bounds);
00173     
00174     glViewport(0, 0, mw->size[0], mw->size[1]);
00175 
00176     glMatrixMode(GL_PROJECTION);
00177     glLoadIdentity();
00178     glOrtho(0, mw->size[0], 0, mw->size[1], -1, 1);
00179     glTranslatef(0.375, 0.375, 0.0);
00180 
00181     glMatrixMode(GL_MODELVIEW);
00182     glLoadIdentity();
00183 }
00184 
00185 static void mainwindow_do_key(MainWindow *mw, GHOST_TKey key, int press) {
00186     switch(key) {
00187     case GHOST_kKeyC:
00188         if (press)
00189             GHOST_SetCursorShape(mw->win, (GHOST_TStandardCursor) (rand()%(GHOST_kStandardCursorNumCursors)));
00190         break;
00191     case GHOST_kKeyLeftBracket:
00192         if (press)
00193             GHOST_SetCursorVisibility(mw->win, 0);
00194         break;
00195     case GHOST_kKeyRightBracket:
00196         if (press)
00197             GHOST_SetCursorVisibility(mw->win, 1);
00198         break;
00199     case GHOST_kKeyE:
00200         if (press)
00201             multitestapp_toggle_extra_window(mw->app);
00202         break;
00203     case GHOST_kKeyQ:
00204         if (press)
00205             multitestapp_exit(mw->app);
00206         break;
00207     case GHOST_kKeyT:
00208         if (press)
00209             mainwindow_log(mw, "TextTest~|`hello`\"world\",<>/");
00210         break;
00211     case GHOST_kKeyR:
00212         if (press) {
00213             int i;
00214             
00215             mainwindow_log(mw, "Invalidating window 10 times");
00216             for (i=0; i<10; i++)
00217                 GHOST_InvalidateWindow(mw->win);
00218         }
00219         break;
00220     case GHOST_kKeyF11:
00221         if (press) {
00222             GHOST_SetWindowOrder(mw->win, GHOST_kWindowOrderBottom);
00223         }
00224         break;
00225     }
00226 }
00227 
00228 static void mainwindow_do_move(MainWindow *mw, int x, int y) {
00229     mw->lmouse[0]= x, mw->lmouse[1]= y;
00230     
00231     if (mw->lmbut[0]) {
00232         mw->tmouse[0]= x, mw->tmouse[1]= y;
00233         GHOST_InvalidateWindow(mw->win);
00234     }
00235 }
00236 
00237 static void mainwindow_do_button(MainWindow *mw, int which, int press) {
00238     if (which==GHOST_kButtonMaskLeft) {
00239         mw->lmbut[0]= press;
00240         mw->tmouse[0]= mw->lmouse[0], mw->tmouse[1]= mw->lmouse[1];
00241         GHOST_InvalidateWindow(mw->win);
00242     } else if (which==GHOST_kButtonMaskLeft) {
00243         mw->lmbut[1]= press;
00244     } else if (which==GHOST_kButtonMaskLeft) {
00245         mw->lmbut[2]= press;
00246     }
00247 }
00248 
00249 static void mainwindow_handle(void *priv, GHOST_EventHandle evt) {
00250     MainWindow *mw= priv;
00251     GHOST_TEventType type= GHOST_GetEventType(evt);
00252     char buf[256];
00253     
00254     event_to_buf(evt, buf);
00255     mainwindow_log(mw, buf);
00256     
00257     switch (type) {
00258     case GHOST_kEventCursorMove: {
00259         GHOST_TEventCursorData *cd= GHOST_GetEventData(evt);
00260         int x, y;
00261         GHOST_ScreenToClient(mw->win, cd->x, cd->y, &x, &y);
00262         mainwindow_do_move(mw, x, mw->size[1]-y-1);
00263         break;
00264     }
00265     case GHOST_kEventButtonDown:
00266     case GHOST_kEventButtonUp: {
00267         GHOST_TEventButtonData *bd= GHOST_GetEventData(evt);
00268         mainwindow_do_button(mw, bd->button, (type == GHOST_kEventButtonDown));
00269         break;
00270     }
00271     case GHOST_kEventKeyDown:
00272     case GHOST_kEventKeyUp: {
00273         GHOST_TEventKeyData *kd= GHOST_GetEventData(evt);
00274         mainwindow_do_key(mw, kd->key, (type == GHOST_kEventKeyDown));
00275         break;
00276     }
00277 
00278     case GHOST_kEventWindowUpdate:
00279         mainwindow_do_draw(mw);
00280         break;
00281     case GHOST_kEventWindowSize:
00282         mainwindow_do_reshape(mw);
00283         break;
00284     }
00285 }
00286 
00287 
00288 
00289 static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, GHOST_TUns64 time) {
00290     MainWindow *mw= GHOST_GetTimerTaskUserData(task);
00291     char buf[64];
00292     
00293     sprintf(buf, "timer: %6.2f", (double) ((GHOST_TInt64) time)/1000);
00294     mainwindow_log(mw, buf);
00295 }
00296 
00297 MainWindow *mainwindow_new(MultiTestApp *app) {
00298     GHOST_SystemHandle sys= multitestapp_get_system(app);
00299     GHOST_WindowHandle win;
00300     
00301     win= GHOST_CreateWindow(sys, "MultiTest:Main", 40, 40, 400, 400, 
00302         GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL, 
00303         FALSE, FALSE);
00304     
00305     if (win) {
00306         MainWindow *mw= MEM_callocN(sizeof(*mw), "mainwindow_new");
00307         mw->app= app;
00308         mw->win= win;
00309         
00310         GHOST_SetWindowUserData(mw->win, windowdata_new(mw, mainwindow_handle));
00311         
00312         GHOST_InstallTimer(sys, 1000, 10000, mainwindow_timer_proc, mw);
00313         
00314         return mw;
00315     } else {
00316         return NULL;
00317     }
00318 }
00319 
00320 void mainwindow_free(MainWindow *mw) {
00321     GHOST_SystemHandle sys= multitestapp_get_system(mw->app);
00322 
00323     windowdata_free(GHOST_GetWindowUserData(mw->win));
00324     GHOST_DisposeWindow(sys, mw->win);
00325     MEM_freeN(mw);
00326 }
00327 
00328     /*
00329      * LoggerWindow
00330      */
00331 
00332 struct _LoggerWindow {
00333     MultiTestApp        *app;
00334 
00335     GHOST_WindowHandle  win;
00336 
00337 #ifdef USE_BMF  
00338     BMF_Font    *font;
00339 #else
00340     int         font;
00341 #endif
00342     int         fonttexid;
00343     int         fontheight;
00344     
00345     int         size[2];
00346     
00347     int         ndisplines;
00348     int         textarea[2][2];
00349     ScrollBar   *scroll;
00350     
00351     char        **loglines;
00352     int         nloglines, logsize;
00353     
00354     int         lmbut[3];
00355     int         lmouse[2];
00356 };
00357 
00358 #define SCROLLBAR_PAD 2
00359 #define SCROLLBAR_WIDTH 14
00360 #define TEXTAREA_PAD 2
00361 static void loggerwindow_recalc_regions(LoggerWindow *lw) {
00362     int nscroll[2][2];
00363     
00364     nscroll[0][0]= SCROLLBAR_PAD;
00365     nscroll[0][1]= SCROLLBAR_PAD;
00366     nscroll[1][0]= nscroll[0][0] + SCROLLBAR_WIDTH;
00367     nscroll[1][1]= lw->size[1] - SCROLLBAR_PAD - 1;
00368 
00369     lw->textarea[0][0]= nscroll[1][0] + TEXTAREA_PAD;
00370     lw->textarea[0][1]= TEXTAREA_PAD;
00371     lw->textarea[1][0]= lw->size[0] - TEXTAREA_PAD - 1;
00372     lw->textarea[1][1]= lw->size[1] - TEXTAREA_PAD - 1;
00373 
00374     lw->ndisplines= (lw->textarea[1][1]-lw->textarea[0][1])/lw->fontheight;
00375 
00376     scrollbar_set_thumbpct(lw->scroll, (float) lw->ndisplines/lw->nloglines);
00377     scrollbar_set_rect(lw->scroll, nscroll);
00378 }
00379 
00380 static void loggerwindow_setup_window_gl(LoggerWindow *lw) {
00381     glViewport(0, 0, lw->size[0], lw->size[1]);
00382 
00383     glMatrixMode(GL_PROJECTION);
00384     glLoadIdentity();
00385     glOrtho(0, lw->size[0], 0, lw->size[1], -1, 1);
00386     glTranslatef(0.375, 0.375, 0.0);
00387 
00388     glMatrixMode(GL_MODELVIEW);
00389     glLoadIdentity();
00390 }
00391 
00392 static void loggerwindow_do_reshape(LoggerWindow *lw) {
00393     GHOST_RectangleHandle bounds= GHOST_GetClientBounds(lw->win);
00394 
00395     GHOST_ActivateWindowDrawingContext(lw->win);
00396     
00397     lw->size[0]= GHOST_GetWidthRectangle(bounds);
00398     lw->size[1]= GHOST_GetHeightRectangle(bounds);
00399     
00400     loggerwindow_recalc_regions(lw);
00401     loggerwindow_setup_window_gl(lw);
00402 }
00403 
00404 static void loggerwindow_do_draw(LoggerWindow *lw) {
00405     int i, ndisplines, startline;
00406     int sb_rect[2][2], sb_thumb[2][2];
00407         
00408     GHOST_ActivateWindowDrawingContext(lw->win);
00409     
00410     glClearColor(1, 1, 1, 1);
00411     glClear(GL_COLOR_BUFFER_BIT);
00412 
00413     glColor3f(0.8, 0.8, 0.8);
00414     rect_bevel_smooth(lw->textarea, 4);
00415     
00416     scrollbar_get_rect(lw->scroll, sb_rect);
00417     scrollbar_get_thumb(lw->scroll, sb_thumb);
00418     
00419     glColor3f(0.6, 0.6, 0.6);
00420     rect_bevel_smooth(sb_rect, 1);
00421     
00422     if (scrollbar_is_scrolling(lw->scroll)) {
00423         glColor3f(0.6, 0.7, 0.5);
00424     } else {
00425         glColor3f(0.9, 0.9, 0.92);
00426     }
00427     rect_bevel_smooth(sb_thumb, 1);
00428     
00429     startline= scrollbar_get_thumbpos(lw->scroll)*(lw->nloglines-1);
00430     ndisplines= min_i(lw->ndisplines, lw->nloglines-startline);
00431 
00432     if (lw->fonttexid!=-1) {
00433         glBindTexture(GL_TEXTURE_2D, lw->fonttexid);
00434         
00435         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00436         glEnable(GL_BLEND);
00437         glEnable(GL_TEXTURE_2D);        
00438     }
00439     glColor3f(0, 0, 0);
00440     for (i=0; i<ndisplines; i++) {
00441             /* stored in reverse order */
00442         char *line= lw->loglines[(lw->nloglines-1)-(i+startline)];
00443         int x_pos= lw->textarea[0][0] + 4;
00444         int y_pos= lw->textarea[0][1] + 4 + i*lw->fontheight;
00445 
00446 #ifdef USE_BMF      
00447         if (lw->fonttexid==-1) {
00448             glRasterPos2i(x_pos, y_pos);
00449             BMF_DrawString(lw->font, line);
00450         } else {
00451             BMF_DrawStringTexture(lw->font, line, x_pos, y_pos, 0.0);
00452         }
00453 #else
00454         BLF_position(lw->font, x_pos, y_pos, 0.0);
00455         BLF_draw(lw->font, line, 256); // XXX
00456 #endif
00457     }
00458 
00459 #ifdef USE_BMF
00460     if (lw->fonttexid!=-1) {
00461         glDisable(GL_TEXTURE_2D);       
00462         glDisable(GL_BLEND);
00463     }
00464 #endif
00465 
00466     GHOST_SwapWindowBuffers(lw->win);
00467 }
00468 
00469 static void loggerwindow_do_move(LoggerWindow *lw, int x, int y) {
00470     lw->lmouse[0]= x, lw->lmouse[1]= y;
00471     
00472     if (scrollbar_is_scrolling(lw->scroll)) {
00473         scrollbar_keep_scrolling(lw->scroll, y);
00474         GHOST_InvalidateWindow(lw->win);
00475     }
00476 }
00477 
00478 static void loggerwindow_do_button(LoggerWindow *lw, int which, int press) {
00479     if (which==GHOST_kButtonMaskLeft) {
00480         lw->lmbut[0]= press;
00481         
00482         if (press) {
00483             if (scrollbar_contains_pt(lw->scroll, lw->lmouse)) {
00484                 scrollbar_start_scrolling(lw->scroll, lw->lmouse[1]);               
00485                 GHOST_SetCursorShape(lw->win, GHOST_kStandardCursorUpDown);
00486                 GHOST_InvalidateWindow(lw->win);
00487             }
00488         } else {
00489             if (scrollbar_is_scrolling(lw->scroll)) {
00490                 scrollbar_stop_scrolling(lw->scroll);
00491                 GHOST_SetCursorShape(lw->win, GHOST_kStandardCursorDefault);
00492                 GHOST_InvalidateWindow(lw->win);
00493             }
00494         }
00495     } else if (which==GHOST_kButtonMaskMiddle) {
00496         lw->lmbut[1]= press;
00497     } else if (which==GHOST_kButtonMaskRight) {
00498         lw->lmbut[2]= press;
00499     }
00500 }
00501 
00502 static void loggerwindow_do_key(LoggerWindow *lw, GHOST_TKey key, int press) {
00503     switch (key) {
00504     case GHOST_kKeyQ:
00505         if (press)
00506             multitestapp_exit(lw->app);
00507         break;
00508     }
00509 }
00510 
00511 static void loggerwindow_handle(void *priv, GHOST_EventHandle evt) {
00512     LoggerWindow *lw= priv;
00513     GHOST_TEventType type= GHOST_GetEventType(evt);
00514     
00515     switch(type) {
00516     case GHOST_kEventCursorMove: {
00517         GHOST_TEventCursorData *cd= GHOST_GetEventData(evt);
00518         int x, y;
00519         GHOST_ScreenToClient(lw->win, cd->x, cd->y, &x, &y);
00520         loggerwindow_do_move(lw, x, lw->size[1]-y-1);
00521         break;
00522     }
00523     case GHOST_kEventButtonDown:
00524     case GHOST_kEventButtonUp: {
00525         GHOST_TEventButtonData *bd= GHOST_GetEventData(evt);
00526         loggerwindow_do_button(lw, bd->button, (type == GHOST_kEventButtonDown));
00527         break;
00528     }
00529     case GHOST_kEventKeyDown:
00530     case GHOST_kEventKeyUp: {
00531         GHOST_TEventKeyData *kd= GHOST_GetEventData(evt);
00532         loggerwindow_do_key(lw, kd->key, (type == GHOST_kEventKeyDown));
00533         break;
00534     }
00535         
00536     case GHOST_kEventWindowUpdate:
00537         loggerwindow_do_draw(lw);
00538         break;
00539     case GHOST_kEventWindowSize:
00540         loggerwindow_do_reshape(lw);
00541         break;
00542     }
00543 }
00544 
00545 
00546 
00547 LoggerWindow *loggerwindow_new(MultiTestApp *app) {
00548     GHOST_SystemHandle sys= multitestapp_get_system(app);
00549     GHOST_TUns32 screensize[2];
00550     GHOST_WindowHandle win;
00551     
00552     GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]);
00553     win= GHOST_CreateWindow(sys, "MultiTest:Logger", 40, screensize[1]-432,
00554         800, 300, GHOST_kWindowStateNormal, 
00555         GHOST_kDrawingContextTypeOpenGL, FALSE, FALSE);
00556     
00557     if (win) {
00558         LoggerWindow *lw= MEM_callocN(sizeof(*lw), "loggerwindow_new");
00559         int bbox[2][2];
00560         lw->app= app;
00561         lw->win= win;
00562 
00563 #ifdef USE_BMF
00564         lw->font= BMF_GetFont(BMF_kScreen12);
00565         lw->fonttexid= BMF_GetFontTexture(lw->font);
00566 
00567         BMF_GetBoundingBox(lw->font, &bbox[0][0], &bbox[0][1], &bbox[1][0], &bbox[1][1]);
00568         lw->fontheight= rect_height(bbox);
00569 #else
00570         lw->font= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
00571         BLF_size(lw->font, 11, 72);
00572         lw->fontheight= BLF_height(lw->font, "A_");
00573 #endif
00574         
00575         lw->nloglines= lw->logsize= 0;
00576         lw->loglines= MEM_mallocN(sizeof(*lw->loglines)*lw->nloglines, "loglines");
00577         
00578         lw->scroll= scrollbar_new(2, 40);
00579         
00580         GHOST_SetWindowUserData(lw->win, windowdata_new(lw, loggerwindow_handle));
00581 
00582         loggerwindow_do_reshape(lw);
00583 
00584         return lw;
00585     } else {
00586         return NULL;
00587     }
00588 }
00589 
00590 void loggerwindow_log(LoggerWindow *lw, char *line) {
00591     if (lw->nloglines==lw->logsize) {
00592         lw->loglines= memdbl(lw->loglines, &lw->logsize, sizeof(*lw->loglines));
00593     }
00594     
00595     lw->loglines[lw->nloglines++]= string_dup(line);
00596     scrollbar_set_thumbpct(lw->scroll, (float) lw->ndisplines/lw->nloglines);
00597     
00598     GHOST_InvalidateWindow(lw->win);
00599 }
00600 
00601 void loggerwindow_free(LoggerWindow *lw) {
00602     GHOST_SystemHandle sys= multitestapp_get_system(lw->app);
00603     int i;
00604 
00605     for (i=0; i<lw->nloglines; i++) {
00606         MEM_freeN(lw->loglines[i]);
00607     }
00608     MEM_freeN(lw->loglines);
00609     
00610     windowdata_free(GHOST_GetWindowUserData(lw->win));
00611     GHOST_DisposeWindow(sys, lw->win);
00612     MEM_freeN(lw);
00613 }
00614 
00615     /*
00616      * ExtraWindow
00617      */
00618 
00619 
00620 typedef struct {
00621     MultiTestApp        *app;
00622 
00623     GHOST_WindowHandle  win;
00624     
00625     int     size[2];
00626 } ExtraWindow;
00627 
00628 static void extrawindow_do_draw(ExtraWindow *ew) {
00629     GHOST_ActivateWindowDrawingContext(ew->win);
00630 
00631     glClearColor(1, 1, 1, 1);
00632     glClear(GL_COLOR_BUFFER_BIT);
00633     
00634     glColor3f(0.8, 0.8, 0.8);
00635     glRecti(10, 10, ew->size[0]-10, ew->size[1]-10);
00636     
00637     GHOST_SwapWindowBuffers(ew->win);
00638 }
00639 
00640 static void extrawindow_do_reshape(ExtraWindow *ew) {
00641     GHOST_RectangleHandle bounds= GHOST_GetClientBounds(ew->win);
00642 
00643     GHOST_ActivateWindowDrawingContext(ew->win);
00644 
00645     ew->size[0]= GHOST_GetWidthRectangle(bounds);
00646     ew->size[1]= GHOST_GetHeightRectangle(bounds);
00647     
00648     glViewport(0, 0, ew->size[0], ew->size[1]);
00649 
00650     glMatrixMode(GL_PROJECTION);
00651     glLoadIdentity();
00652     glOrtho(0, ew->size[0], 0, ew->size[1], -1, 1);
00653     glTranslatef(0.375, 0.375, 0.0);
00654 
00655     glMatrixMode(GL_MODELVIEW);
00656     glLoadIdentity();
00657 }
00658 
00659 static void extrawindow_do_key(ExtraWindow *ew, GHOST_TKey key, int press) {
00660     switch (key) {
00661     case GHOST_kKeyE:
00662         if (press)
00663             multitestapp_toggle_extra_window(ew->app);
00664         break;
00665     }
00666 }
00667 
00668 static void extrawindow_spin_cursor(ExtraWindow *ew, GHOST_TUns64 time) {
00669     GHOST_TUns8 bitmap[16][2];
00670     GHOST_TUns8 mask[16][2];
00671     double ftime= (double) ((GHOST_TInt64) time)/1000;
00672     float angle= fmod(ftime, 1.0) * 3.1415*2;
00673     int i;
00674     
00675     memset(&bitmap, 0, sizeof(bitmap));
00676     memset(&mask, 0, sizeof(mask));
00677     
00678     bitmap[0][0] |= mask[0][0] |= 0xF;
00679     bitmap[1][0] |= mask[1][0] |= 0xF;
00680     bitmap[2][0] |= mask[2][0] |= 0xF;
00681     bitmap[3][0] |= mask[3][0] |= 0xF;
00682     
00683     for (i=0; i<7; i++) {
00684         int x = 7 + cos(angle)*i;
00685         int y = 7 + sin(angle)*i;
00686         
00687         mask[y][x/8] |= (1 << (x%8));
00688     }
00689     for (i=0; i<64; i++) {
00690         float v= (i/63.0) * 3.1415*2;
00691         int x = 7 + cos(v)*7;
00692         int y = 7 + sin(v)*7;
00693         
00694         mask[y][x/8] |= (1 << (x%8));
00695     }
00696     
00697     GHOST_SetCustomCursorShape(ew->win, bitmap, mask, 0, 0);
00698 }
00699 
00700 static void extrawindow_handle(void *priv, GHOST_EventHandle evt) {
00701     ExtraWindow *ew= priv;
00702     GHOST_TEventType type= GHOST_GetEventType(evt);
00703     char buf[256];
00704     
00705     event_to_buf(evt, buf);
00706     loggerwindow_log(multitestapp_get_logger(ew->app), buf);
00707     
00708     switch (type) {
00709     case GHOST_kEventKeyDown:
00710     case GHOST_kEventKeyUp: {
00711         GHOST_TEventKeyData *kd= GHOST_GetEventData(evt);
00712         extrawindow_do_key(ew, kd->key, (type == GHOST_kEventKeyDown));
00713         break;
00714     }
00715 
00716     case GHOST_kEventCursorMove: {
00717         extrawindow_spin_cursor(ew, GHOST_GetEventTime(evt));
00718         break;
00719     }
00720     
00721     case GHOST_kEventWindowClose:
00722         multitestapp_free_extrawindow(ew->app);
00723         break;
00724     case GHOST_kEventWindowUpdate:
00725         extrawindow_do_draw(ew);
00726         break;
00727     case GHOST_kEventWindowSize:
00728         extrawindow_do_reshape(ew);
00729         break;
00730     }
00731 }
00732 
00733 
00734 
00735 ExtraWindow *extrawindow_new(MultiTestApp *app) {
00736     GHOST_SystemHandle sys= multitestapp_get_system(app);
00737     GHOST_WindowHandle win;
00738     
00739     win= GHOST_CreateWindow(sys, "MultiTest:Extra", 500, 40, 400, 400, 
00740         GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL,
00741         FALSE, FALSE);
00742     
00743     if (win) {
00744         ExtraWindow *ew= MEM_callocN(sizeof(*ew), "mainwindow_new");
00745         ew->app= app;
00746         ew->win= win;
00747         
00748         GHOST_SetWindowUserData(ew->win, windowdata_new(ew, extrawindow_handle));
00749         
00750         return ew;
00751     } else {
00752         return NULL;
00753     }
00754 }
00755 
00756 void extrawindow_free(ExtraWindow *ew) {
00757     GHOST_SystemHandle sys= multitestapp_get_system(ew->app);
00758 
00759     windowdata_free(GHOST_GetWindowUserData(ew->win));
00760     GHOST_DisposeWindow(sys, ew->win);
00761     MEM_freeN(ew);
00762 }
00763 
00764     /*
00765      * MultiTestApp
00766      */
00767     
00768 struct _MultiTestApp {
00769     GHOST_SystemHandle  sys;
00770     MainWindow          *main;
00771     LoggerWindow        *logger;
00772     ExtraWindow         *extra;
00773     
00774     int                 exit;
00775 };
00776 
00777 static int multitest_event_handler(GHOST_EventHandle evt, GHOST_TUserDataPtr data) {
00778     MultiTestApp *app= data;
00779     GHOST_WindowHandle win;
00780     
00781     win= GHOST_GetEventWindow(evt);
00782     if (win && !GHOST_ValidWindow(app->sys, win)) {
00783         loggerwindow_log(app->logger, "WARNING: bad event, non-valid window\n");
00784         return 1;
00785     }
00786         
00787     if (win) {
00788         WindowData *wb= GHOST_GetWindowUserData(win);
00789         
00790         windowdata_handle(wb, evt);
00791     } else {
00792         GHOST_TEventType type= GHOST_GetEventType(evt);
00793         
00794             /* GHOST_kEventQuit are the only 'system' events,
00795              * that is, events without a window.
00796              */
00797         switch(type) {
00798         case GHOST_kEventQuit:
00799             app->exit= 1;
00800             break;
00801             
00802         default:
00803             fatal("Unhandled system event: %d (%s)\n", type, eventtype_to_string(type));
00804             break;
00805         }
00806     }
00807     
00808     return 1;
00809 }
00810 
00811 
00812 
00813 MultiTestApp *multitestapp_new(void) {
00814     MultiTestApp *app= MEM_mallocN(sizeof(*app), "multitestapp_new");
00815     GHOST_EventConsumerHandle consumer= GHOST_CreateEventConsumer(multitest_event_handler, app);
00816 
00817     app->sys= GHOST_CreateSystem();
00818     if (!app->sys)
00819         fatal("Unable to create ghost system");
00820 
00821     if (!GHOST_AddEventConsumer(app->sys, consumer))    
00822         fatal("Unable to add multitest event consumer ");
00823         
00824     app->main= mainwindow_new(app);
00825     if (!app->main) 
00826         fatal("Unable to create main window");
00827         
00828     app->logger= loggerwindow_new(app);
00829     if (!app->logger)
00830         fatal("Unable to create logger window");
00831 
00832     app->extra= NULL;       
00833     app->exit= 0;
00834     
00835     return app;
00836 }
00837 
00838 LoggerWindow *multitestapp_get_logger(MultiTestApp *app) {
00839     return app->logger; 
00840 }
00841 
00842 GHOST_SystemHandle multitestapp_get_system(MultiTestApp *app) {
00843     return app->sys;
00844 }
00845 
00846 void multitestapp_free_extrawindow(MultiTestApp *app) {
00847     extrawindow_free(app->extra);
00848     app->extra= NULL;
00849 }
00850 
00851 void multitestapp_toggle_extra_window(MultiTestApp *app) {
00852     if (app->extra) {
00853         multitestapp_free_extrawindow(app);
00854     } else {
00855         app->extra= extrawindow_new(app);
00856     }
00857 }
00858 
00859 void multitestapp_exit(MultiTestApp *app) {
00860     app->exit= 1;
00861 }
00862 
00863 void multitestapp_run(MultiTestApp *app) {
00864     while (!app->exit) {
00865         GHOST_ProcessEvents(app->sys, 1);
00866         GHOST_DispatchEvents(app->sys);
00867     }
00868 }
00869 
00870 void multitestapp_free(MultiTestApp *app) {
00871     mainwindow_free(app->main);
00872     loggerwindow_free(app->logger);
00873     GHOST_DisposeSystem(app->sys);
00874     MEM_freeN(app);
00875 }
00876 
00877     /***/
00878     
00879 int main(int argc, char **argv) {
00880 #ifndef USE_BMF
00881     BLF_init(11, 72);
00882 #endif
00883 
00884     MultiTestApp *app= multitestapp_new();
00885     
00886     multitestapp_run(app);
00887     multitestapp_free(app);
00888     
00889     return 0;
00890 }