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