• Main Page
  • Namespaces
  • Classes
  • Files
  • File List

application.cpp

Go to the documentation of this file.
00001 #include "application.h"
00002 #include "console.h"
00003 #include "event.h"
00004 #include "eventhandler.h"
00005 #include "hotspot.h"
00006 #include <string.h>
00007 #include <malloc.h>
00008 #include <gccore.h>
00009 #include <ogcsys.h>
00010 #include <wiiuse/wpad.h>
00011 #include <algorithm>
00012 #include <iterator>
00013 #include <vector>
00014 
00015 namespace wit {
00016 
00017 // default font declarations
00018 struct Sans16_Registrar { Sans16_Registrar(); };
00019 struct Sans16_B_Registrar { Sans16_B_Registrar(); };
00020 struct Sans16_I_Registrar { Sans16_I_Registrar(); };
00021 struct Sans16_B_I_Registrar { Sans16_B_I_Registrar(); };
00022 
00023 
00078 struct EventHandlerNode {
00079     EventHandler* handler;
00080     int controllerID;
00081     EventHandlerNode* next;
00082 };
00083 
00084 struct TimerNode {
00085     EventHandler* handler;
00086     int framesRemaining;
00087     void* data;
00088     TimerNode* next;
00089 };
00090 
00091 class ApplicationPrivate {
00092 friend class Application;
00093 public:
00094     int features, screenWidth, powerControllerID;
00095     bool currentBuffer, doShutdown, doReset, doPower, abortGxOnReset;
00096     bool autoHomeMenu, homeMenuOpen;
00097     GXRModeObj videoMode;
00098     void* framebuffer[2];
00099     void* gxfifo;
00100     Console* console;
00101     EventHandlerNode* focus;
00102     EventHandlerNode* eventFilters;
00103     TimerNode* timers;
00104     TimerNode* addTimers;
00105 }; 
00106 
00107 static Application* witInstance = 0; 
00108 static ApplicationPrivate* witPrivate = 0;
00110 void wit_render_all();
00111 
00112 static void wit_power_button_callback()
00113 {
00114     witPrivate->doPower = true;
00115     witPrivate->powerControllerID = -1;
00116     if(witPrivate->features & UseGX && witPrivate->abortGxOnReset) GX_AbortFrame();
00117 }
00118 
00119 static void wit_reset_button_callback()
00120 {
00121     witPrivate->doReset = true;
00122     if(witPrivate->features & UseGX && witPrivate->abortGxOnReset) GX_AbortFrame();
00123 }
00124 
00125 static void wit_remote_power_button_callback(int id)
00126 {
00127     witPrivate->doPower = true;
00128     witPrivate->powerControllerID = id;
00129     if(witPrivate->features & UseGX && witPrivate->abortGxOnReset) GX_AbortFrame();
00130 }
00131 
00135 Application::Application(int features)
00136 {
00137     // initialize private data
00138     witInstance = this;
00139     witPrivate = d = new ApplicationPrivate;
00140     memset(d, 0, sizeof(ApplicationPrivate));
00141     d->features = features;
00142     d->abortGxOnReset = true;
00143 
00144     // initialize framebuffer
00145     VIDEO_Init();
00146     VIDEO_GetPreferredMode(&d->videoMode);
00147     if(CONF_GetAspectRatio() == CONF_ASPECT_16_9) {
00148         d->videoMode.viWidth = VI_MAX_WIDTH_PAL - 12;
00149         d->videoMode.viXOrigin = 8;
00150     }
00151     VIDEO_Configure(&d->videoMode);
00152     d->framebuffer[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(&d->videoMode));
00153     VIDEO_ClearFrameBuffer(&d->videoMode, d->framebuffer[0], 0x800080);
00154     if(features & UseDoubleBuffer) {
00155         d->framebuffer[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(&d->videoMode));
00156         VIDEO_ClearFrameBuffer(&d->videoMode, d->framebuffer[1], 0x800080);
00157     }
00158     d->currentBuffer = false;
00159     VIDEO_SetNextFramebuffer(d->framebuffer[0]);
00160     VIDEO_SetBlack(false);
00161     VIDEO_Flush();
00162 
00163     if(features & UseWiiRemote) {
00164         WPAD_Init();
00165         for(int i = 0; i < WPAD_MAX_WIIMOTES; i++) {
00166             if(features & UsePointer) {
00167                 WPAD_SetDataFormat(i, WPAD_FMT_BTNS_ACC_IR);
00168                 WPAD_SetVRes(i, d->videoMode.fbWidth, d->videoMode.xfbHeight);
00169             } else if(features & UseMotion) {
00170                 WPAD_SetDataFormat(i, WPAD_FMT_BTNS_ACC);
00171             }
00172         }
00173     }
00174 
00175     if(features & UseGameCube) {
00176         PAD_Init();
00177     }
00178 
00179     if(features & UseSound) {
00180         //InitAudio();
00181     }
00182 
00183     if(features & UseFAT) {
00184         //FatInitDefault();
00185     }
00186 
00187     VIDEO_WaitVSync();
00188     if(d->videoMode.viTVMode & VI_NON_INTERLACE)
00189         VIDEO_WaitVSync();
00190 
00191     if(features & UseGX) {
00192         d->gxfifo = memalign(262144, 32);
00193         memset(d->gxfifo, 0, 262144);
00194         GX_Init(d->gxfifo, 262144);
00195         GX_SetBlendMode(GX_BM_BLEND,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR);
00196         GX_SetCopyClear((GXColor){ 0, 0, 0, 0xFF }, 0xFFFFFF);
00197         GX_SetViewport(0, 0, d->videoMode.fbWidth, d->videoMode.efbHeight, 0, 1);
00198         GX_SetScissor(0, 0, d->videoMode.fbWidth, d->videoMode.efbHeight);
00199         GX_SetDispCopyGamma(GX_GM_1_0);
00200         GX_SetCullMode(GX_CULL_NONE);
00201         GX_SetDispCopyDst(d->videoMode.fbWidth, GX_SetDispCopyYScale(GX_GetYScaleFactor(d->videoMode.efbHeight,d->videoMode.xfbHeight)));
00202         GX_SetCopyFilter(d->videoMode.aa, d->videoMode.sample_pattern, GX_TRUE, d->videoMode.vfilter);
00203         GX_SetVtxAttrFmt(GX_VTXFMT7, GX_VA_POS, GX_POS_XY, GX_F32, 0);
00204         GX_SetVtxAttrFmt(GX_VTXFMT7, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
00205         GX_SetVtxAttrFmt(GX_VTXFMT7, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
00206         if(d->videoMode.aa)
00207             GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR);
00208         else
00209             GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
00210         
00211         // Also load default fonts
00212         Sans16_Registrar s16r;
00213         /*Sans16_B_Registrar s16br;
00214         Sans16_I_Registrar s16ir;
00215         Sans16_B_I_Registrar s16bir;*/
00216     }
00217 
00218     if(features & UseConsole) {
00219         d->console = new Console(&d->videoMode);
00220     } else {
00221         d->console = 0;
00222     }
00223 
00224     // install callbacks
00225     SYS_SetResetCallback(wit_reset_button_callback);
00226     SYS_SetPowerCallback(wit_power_button_callback);
00227     if(features & UseWiiRemote)
00228         WPAD_SetPowerButtonCallback(wit_remote_power_button_callback);
00229 }
00230 
00234 Application::~Application()
00235 {
00236     // shut down display
00237     if(d->features & UseGX) {
00238         GX_AbortFrame();
00239         GX_Flush();
00240     }
00241     VIDEO_Flush();
00242 
00243     // clean up data structures
00244     EventHandlerNode* next;
00245     while(d->focus) {
00246         next = d->focus->next;
00247         delete d->focus;
00248         d->focus = next;
00249     }
00250     while(d->eventFilters) {
00251         next = d->eventFilters->next;
00252         delete d->eventFilters;
00253         d->eventFilters = next;
00254     }
00255     TimerNode* nextTimer;
00256     while(d->timers) {
00257         nextTimer = d->timers->next;
00258         delete d->timers;
00259         d->timers = nextTimer;
00260     }
00261     while(d->addTimers) {
00262         nextTimer = d->addTimers->next;
00263         delete d->addTimers;
00264         d->addTimers = nextTimer;
00265     }
00266     delete d->console; 
00267     free(d->gxfifo);
00268     delete d;
00269 }
00270 
00276 Application* Application::instance()
00277 {
00278     return witInstance;
00279 }
00280 
00285 Console* Application::console() const
00286 {
00287     return d->console;
00288 }
00289 
00294 int Application::features() const
00295 {
00296     return d->features;
00297 }
00298 
00302 void* Application::framebuffer() const
00303 {
00304     return d->framebuffer[d->currentBuffer ? 1 : 0];
00305 }
00306 
00310 int Application::screenWidth() const
00311 {
00312     return d->videoMode.fbWidth;
00313 }
00314 
00318 int Application::screenHeight() const
00319 {
00320     return d->videoMode.xfbHeight;
00321 }
00322 
00332 void Application::setAutoHomeMenu(bool on)
00333 {
00334     d->autoHomeMenu = on;
00335 }
00336 
00344 bool Application::autoHomeMenu() const
00345 {
00346     return d->autoHomeMenu;
00347 }
00348 
00368 void Application::showHomeMenu()
00369 {
00370     setHomeMenuVisible(true);
00371 }
00372 
00381 void Application::hideHomeMenu()
00382 {
00383     setHomeMenuVisible(false);
00384 }
00385 
00394 void Application::homeMenuEvent(Event* event)
00395 {
00396     // TODO: implement Wii-style home menu
00397 }
00398 
00406 void Application::setHomeMenuVisible(bool on)
00407 {
00408     // TODO: capture framebuffer
00409     d->homeMenuVisible = on;
00410 }
00411 
00418 bool Application::isHomeMenuVisible() const
00419 {
00420     return d->homeMenuVisible;
00421 }
00422 
00426 void Application::reboot()
00427 {
00428     d->doShutdown = true;
00429     SYS_ResetSystem(SYS_RESTART, 0, 0);
00430 }
00431 
00440 void Application::shutdown(ShutdownMode mode)
00441 {
00442     d->doShutdown = true;
00443     if(mode == Shutdown_Idle)
00444         SYS_ResetSystem(SYS_POWEROFF_IDLE, 0, 0);
00445     else if(mode == Shutdown_Standby)
00446         SYS_ResetSystem(SYS_POWEROFF_STANDBY, 0, 0);
00447     else
00448         SYS_ResetSystem(SYS_POWEROFF, 0, 0);
00449 }
00450 
00454 void Application::returnToMenu()
00455 {
00456     d->doShutdown = true;
00457     SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
00458 }
00459 
00463 void Application::quit()
00464 {
00465     d->doShutdown = true;
00466 }
00467 
00468 static void wit_Application_wpad_cb(s32 chan, const WPADData* data)
00469 {
00470     static const unsigned int remoteMap[] = {
00471         0, WPAD_BUTTON_UP, WPAD_BUTTON_DOWN, WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT, WPAD_BUTTON_1, WPAD_BUTTON_2,
00472         WPAD_BUTTON_A, WPAD_BUTTON_B, 0, 0, 0, 0, 0, 0, 0, 0, WPAD_BUTTON_MINUS, WPAD_BUTTON_PLUS, WPAD_BUTTON_HOME, 0
00473     }; 
00474     static const unsigned int nunchukMap[] = {
00475         0, 0, 0, 0, 0, 0, 0, 0, 0, WPAD_NUNCHUK_BUTTON_C, 0, 0, WPAD_NUNCHUK_BUTTON_Z, 0, 0, 0, 0, 0, 0, 0, 0
00476     }; 
00477     static const unsigned int classicMap[] = {
00478         0, WPAD_CLASSIC_BUTTON_UP, WPAD_CLASSIC_BUTTON_DOWN, WPAD_CLASSIC_BUTTON_LEFT, WPAD_CLASSIC_BUTTON_RIGHT,
00479         0, 0, WPAD_CLASSIC_BUTTON_A, WPAD_CLASSIC_BUTTON_B, 0, WPAD_CLASSIC_BUTTON_X, WPAD_CLASSIC_BUTTON_Y, 0,
00480         WPAD_CLASSIC_BUTTON_ZL, WPAD_CLASSIC_BUTTON_ZR, WPAD_CLASSIC_BUTTON_FULL_L, WPAD_CLASSIC_BUTTON_FULL_R,
00481         WPAD_CLASSIC_BUTTON_MINUS, WPAD_CLASSIC_BUTTON_PLUS, WPAD_CLASSIC_BUTTON_HOME, 0
00482     }; 
00483     static const unsigned int guitarMap[] = {
00484         0, WPAD_GUITAR_HERO_3_BUTTON_STRUM_UP, WPAD_GUITAR_HERO_3_BUTTON_STRUM_DOWN, 0, 0,
00485         WPAD_GUITAR_HERO_3_BUTTON_YELLOW, WPAD_GUITAR_HERO_3_BUTTON_GREEN, WPAD_GUITAR_HERO_3_BUTTON_BLUE,
00486         WPAD_GUITAR_HERO_3_BUTTON_RED, WPAD_GUITAR_HERO_3_BUTTON_ORANGE, 0, 0, 0, 0, 0, 0, 0,
00487         WPAD_GUITAR_HERO_3_BUTTON_MINUS, WPAD_GUITAR_HERO_3_BUTTON_PLUS, 0, 0
00488     }; 
00489 
00490     int features = witInstance->features();
00491 
00492     if(data->btns_d ^ data->btns_u) {
00493         for(int i = 1; i < Button_Max; i++) {
00494             if(data->btns_d & remoteMap[i])
00495                 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, WiiRemote, chan, i));
00496             else if(data->btns_u & remoteMap[i])
00497                 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, WiiRemote, chan, i));
00498 
00499             if(data->exp.type == WPAD_EXP_NUNCHUK && data->exp.nunchuk.btns & nunchukMap[i])
00500                 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, Nunchuk, chan, i));
00501             else if(data->exp.type == WPAD_EXP_NUNCHUK && data->exp.nunchuk.btns_released & nunchukMap[i])
00502                 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, Nunchuk, chan, i));
00503 
00504             if(data->exp.type == WPAD_EXP_CLASSIC && data->exp.classic.btns & classicMap[i])
00505                 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, Classic, chan, i));
00506             else if(data->exp.type == WPAD_EXP_CLASSIC && data->exp.classic.btns_released & classicMap[i])
00507                 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, Classic, chan, i));
00508 
00509             if(data->exp.type == WPAD_EXP_GUITARHERO3 && data->exp.gh3.btns & guitarMap[i])
00510                 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, Guitar, chan, i));
00511             else if(data->exp.type == WPAD_EXP_GUITARHERO3 && data->exp.gh3.btns_released & guitarMap[i])
00512                 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, Guitar, chan, i));
00513         }
00514     }
00515 
00516     if(features & UseJoysticks) {
00517         // TODO: Only announce joystick events if the values change
00518         if(data->exp.type == WPAD_EXP_NUNCHUK) {
00519             JoystickEvent* stickEvent = new JoystickEvent(Nunchuk, chan);
00520             stickEvent->setByAngle(data->exp.nunchuk.js.ang, data->exp.nunchuk.js.mag);
00521             witInstance->postEvent(stickEvent);
00522         } else if(data->exp.type == WPAD_EXP_GUITARHERO3) {
00523             JoystickEvent* stickEvent = new JoystickEvent(Guitar, chan);
00524             stickEvent->setByAngle(data->exp.gh3.js.ang, data->exp.gh3.js.mag);
00525             witInstance->postEvent(stickEvent);
00526             witInstance->postEvent(new AnalogEvent(Guitar, chan, Analog_Whammy, data->exp.gh3.whammy_bar));
00527         } else if(data->exp.type == WPAD_EXP_CLASSIC) {
00528             JoystickEvent* stickEvent = new JoystickEvent(Classic, chan);
00529             stickEvent->setByAngle(data->exp.classic.ljs.ang, data->exp.classic.ljs.mag);
00530             witInstance->postEvent(stickEvent);
00531             stickEvent = new JoystickEvent(Classic, chan, true);
00532             stickEvent->setByAngle(data->exp.classic.rjs.ang, data->exp.classic.rjs.mag);
00533             witInstance->postEvent(stickEvent);
00534             witInstance->postEvent(new AnalogEvent(Classic, chan, Analog_Left, data->exp.classic.l_shoulder));
00535             witInstance->postEvent(new AnalogEvent(Classic, chan, Analog_Right, data->exp.classic.r_shoulder));
00536         }
00537     }
00538 
00539     if(features & UsePointer) {
00540         if(data->ir.valid) {
00541             witInstance->postEvent(new PointerEvent(chan, data->ir.x, data->ir.y, data->ir.z));
00542         } else {
00543             witInstance->postEvent(new PointerEvent(chan, -1.0f, -1.0f, -1.0f));
00544         }
00545     }
00546 
00547     if(features & UseMotion) {
00548         float x = data->accel.x / 1024.0;
00549         float y = data->accel.y / 1024.0;
00550         float z = data->accel.z / 1024.0;
00551         witInstance->postEvent(new MotionEvent(WiiRemote, chan, x, y, z, data->orient.pitch, data->orient.roll));
00552         if(data->exp.type == WPAD_EXP_NUNCHUK) {
00553             x = data->exp.nunchuk.accel.x / 1024.0;
00554             y = data->exp.nunchuk.accel.y / 1024.0;
00555             z = data->exp.nunchuk.accel.z / 1024.0;
00556             witInstance->postEvent(new MotionEvent(Nunchuk, chan, x, y, z, data->exp.nunchuk.orient.pitch, data->exp.nunchuk.orient.roll));
00557         }
00558         /*if(data->exp.type == WPAD_EXP_WIIBOARD) {
00559             // data->exp.wb
00560             x = data->exp.wb.x;
00561             y = data->exp.wb.y;
00562             z = (data->exp.wb.tl + data->exp.wb.tr + data->exp.wb.bl + data->exp.wb.br) / 4.0f; // weight
00563             witInstance->postEvent(new MotionEvent(BalanceBoard, chan, x, y, z, 0, 0));
00564         }*/
00565     }
00566 }
00567 
00568 static void wit_Application_gcpad_cb(s32 chan, const PADStatus* data)
00569 {
00570     static const unsigned int gcMap[] = {
00571         0, PAD_BUTTON_UP, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT, 0, 0,
00572         PAD_BUTTON_A, PAD_BUTTON_B, 0, PAD_BUTTON_X, PAD_BUTTON_Y, PAD_TRIGGER_Z, 0, 0,
00573         PAD_TRIGGER_L, PAD_TRIGGER_R, 0, 0, 0, PAD_BUTTON_START
00574     }; 
00575 
00576     static u16 oldbuttons[PAD_CHANMAX] = { 0, 0, 0, 0 };
00577 
00578     if(data->err == PAD_ERR_NO_CONTROLLER) return;
00579 
00580     int features = witInstance->features();
00581 
00582     if(data->button != oldbuttons[chan]) {
00583         u16 changed = (data->button ^ oldbuttons[chan]);
00584         u16 press = changed & data->button;
00585         u16 release = changed & oldbuttons[chan];
00586         oldbuttons[chan] = data->button;
00587         for(int i = 0; i < Button_Max; i++) {
00588             if(press & gcMap[i]) {
00589                 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, GameCube, chan+4, i));
00590             } else if(release & gcMap[i]) {
00591                 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, GameCube, chan+4, i));
00592             }
00593         }
00594     }
00595 
00596     if(features & UseJoysticks) {
00597         // TODO: only output joystick events if the values have changed
00598         JoystickEvent* stickEvent = new JoystickEvent(GameCube, chan+4);
00599         stickEvent->setByPosition(data->stickX, data->stickY);
00600         witInstance->postEvent(stickEvent);
00601         stickEvent = new JoystickEvent(GameCube, chan+4, true);
00602         stickEvent->setByPosition(data->substickX, data->substickY);
00603         witInstance->postEvent(stickEvent);
00604         witInstance->postEvent(new AnalogEvent(GameCube, chan+4, Analog_Left, data->triggerL / 256.0f));
00605         witInstance->postEvent(new AnalogEvent(GameCube, chan+4, Analog_Right, data->triggerR / 256.0f));
00606         witInstance->postEvent(new AnalogEvent(GameCube, chan+4, Analog_A, data->analogA / 256.0f));
00607         witInstance->postEvent(new AnalogEvent(GameCube, chan+4, Analog_B, data->analogB / 256.0f));
00608     }
00609 }
00610 
00611 static inline bool doStop() { return witPrivate->doShutdown || witPrivate->doPower || witPrivate->doReset; }
00612 
00620 void Application::run()
00621 {
00622     // Create these variables here (even if we're not going to use them) so we
00623     // have them here on the stack instead of having to allocate them as needed.
00624     PADStatus gcpad[PAD_CHANMAX];
00625     WPADData wpadData;
00626 
00627     d->doShutdown = false;
00628     while(!d->doShutdown) {
00629         // Handle Wii Remote events
00630         if(!doStop() && d->features & UseWiiRemote) { 
00631             for(int i = WPAD_CHAN_0; !doStop() && i < WPAD_MAX_WIIMOTES; i++) {
00632                 while(!doStop() && WPAD_ReadEvent(i, &wpadData) >= WPAD_ERR_NONE) 
00633                     wit_Application_wpad_cb(i, &wpadData);
00634             }
00635         }
00636 
00637         // Handle GameCube controller events
00638         if(!doStop() && d->features & UseGameCube) {
00639             PAD_Read(gcpad);
00640             for(int i = 0; !doStop() && i < PAD_CHANMAX; i++) {
00641                 wit_Application_gcpad_cb(i, &gcpad[i]);
00642             }
00643         }
00644 
00645         // Handle power-button presses
00646         if(d->doPower) {
00647             powerButtonPressed(d->powerControllerID);
00648             d->doPower = false;
00649         } else if(d->doReset) {
00650             resetButtonPressed();
00651             d->doReset = false;
00652         }
00653 
00654         // Do rendering
00655         wit_render_all();
00656         if(!d->doShutdown) {
00657             if(d->features & UseGX) {
00658                 GX_DrawDone();
00659                 GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
00660                 GX_Flush();
00661                 GX_CopyDisp(framebuffer(),GX_TRUE);
00662             }
00663             if(d->features & UseDoubleBuffer) {
00664                 VIDEO_SetNextFramebuffer(framebuffer());
00665                 VIDEO_Flush();
00666                 d->currentBuffer = !d->currentBuffer;
00667                 if(d->features & UseConsole)
00668                     console()->setFramebuffer(framebuffer());
00669             } else {
00670                 VIDEO_Flush();
00671             }
00672             
00673             // Only process timers if the home menu is not visible
00674             if(!d->homeMenuVisible) {
00675                 // Add timers scheduled during event handling
00676                 if(d->addTimers) {
00677                     // Find the end of the linked list
00678                     TimerNode* timer = d->addTimers;
00679                     while(timer->next) timer = timer->next;
00680                     timer->next = d->timers;
00681                     d->timers = d->addTimers;
00682                     d->addTimers = 0;
00683                 }
00684 
00685                 // Check for expiring timers
00686                 TimerNode* timer = d->timers;
00687                 TimerNode* previousTimer = 0;
00688                 TimerNode* nextTimer;
00689                 while(timer) {
00690                     if(--timer->framesRemaining < 0) {
00691                         timer->handler->timerTriggered(timer->data);
00692                         if(previousTimer) {
00693                             previousTimer->next = timer->next;
00694                         } else {
00695                             d->timers = timer->next;
00696                         }
00697                         nextTimer = timer->next;
00698                         delete timer;
00699                         timer = nextTimer;
00700                     } else {
00701                         previousTimer = timer;
00702                         timer = timer->next;
00703                     }
00704                 }
00705 
00706                 // Append timers scheduled during timer dispatch
00707                 if(previousTimer) {
00708                     previousTimer->next = d->addTimers;
00709                 } else {
00710                     d->timers = d->addTimers;
00711                 }
00712                 d->addTimers = 0;
00713             }
00714 
00715             VIDEO_WaitVSync();
00716         }
00717     }
00718 }
00719 
00720 static bool wit_Application_distribute_event(Event* event, EventHandlerNode* node)
00721 {
00722     while(node) {
00723         bool cancel = node->handler->event(event);
00724         if(cancel) return true;
00725         node = node->next;
00726     }
00727     return false;
00728 }
00729 
00730 static HotspotList lastHotspots[4];
00731 
00761 void Application::postEvent(Event* event)
00762 {
00763     if(d->homeMenuVisible) {
00764         homeMenuEvent(event);
00765         delete event;
00766         return;
00767     }
00768 
00769     if(wit_Application_distribute_event(event, d->eventFilters)) {
00770         delete event;
00771         return;
00772     }
00773 
00774     if(event->type() == Event::Pointer) {
00775         PointerEvent* p = static_cast<PointerEvent*>(event);
00776         if(p->isValid()) {
00777             Hotspot* hs;
00778             std::auto_ptr<HotspotList> spots = Hotspot::findAtPoint(p->x, p->y);
00779             std::sort(spots->begin(), spots->end());
00780             HotspotList lostFocus;
00781             std::set_difference(lastHotspots[p->controllerNumber].begin(), lastHotspots[p->controllerNumber].end(), spots->begin(), spots->end(), std::back_inserter(lostFocus));
00782             lastHotspots[p->controllerNumber] = *spots;
00783             if(lostFocus.size() > 0) {
00784                 Hotspot** end = &lostFocus.back();
00785                 for(Hotspot** iter = &lostFocus.front(); iter <= end; iter++) {
00786                     hs = *iter;
00787                     PointerLeaveEvent leaveEvent(p->controllerNumber, hs);
00788                     if(!wit_Application_distribute_event(&leaveEvent, d->eventFilters) && hs->eventHandler())
00789                         hs->eventHandler()->event(&leaveEvent);
00790                 }
00791             }
00792             if(spots->size() > 0) {
00793                 Hotspot** end = &spots->back();
00794                 Hotspot* receiver = 0;
00795                 for(Hotspot** iter = &spots->front(); iter <= end; iter++) {
00796                     hs = *iter;
00797                     if(!hs->eventHandler()) continue;
00798                     if(receiver && hs->zIndex() < receiver->zIndex()) continue;
00799                     receiver = hs;
00800                 }
00801                 if(receiver)
00802                     receiver->eventHandler()->event(event);
00803             }
00804         }
00805     } else {
00806         wit_Application_distribute_event(event, d->focus);
00807     }
00808     delete event;
00809 }
00810 
00820 void Application::pushFocus(EventHandler* handler, int controllerID)
00821 {
00822     EventHandlerNode* node = new EventHandlerNode;
00823     node->controllerID = controllerID;
00824     node->handler = handler;
00825     node->next = d->focus;
00826     d->focus = node;
00827 }
00828 
00837 EventHandler* Application::currentFocus(int controllerID) const
00838 {
00839     if(!d->focus) return 0;
00840     EventHandlerNode* node = d->focus;
00841     while(node) {
00842         if(node->controllerID == controllerID || node->controllerID == -1)
00843             return node->handler;
00844         node = node->next;
00845     }
00846     return 0;
00847 }
00848 
00857 EventHandler* Application::popFocus(int controllerID)
00858 {
00859     if(!d->focus) return 0;
00860     EventHandlerNode* node = d->focus;
00861     EventHandlerNode* lastNode = 0;
00862     while(node) {
00863         if(node->controllerID == controllerID) {
00864             if(lastNode) {
00865                 lastNode->next = node->next;
00866             } else {
00867                 d->focus = node->next;
00868             }
00869             EventHandler* h = node->handler;
00870             delete node;
00871             return h;
00872         }
00873         lastNode = node;
00874         node = node->next;
00875     }
00876     return 0;
00877 }
00878 
00886 void Application::removeFromFocusStack(EventHandler* handler, int controllerID)
00887 {
00888     EventHandlerNode* node = d->focus;
00889     EventHandlerNode* lastNode = 0;
00890     while(node) {
00891         if(node->handler == handler && (controllerID == -1 || controllerID == node->controllerID)) {
00892             if(lastNode) {
00893                 lastNode->next = node->next;
00894             } else {
00895                 d->focus = node->next;
00896             }
00897             EventHandlerNode* delNode = node;
00898             node = node->next;
00899             delete delNode;
00900         } else {
00901             lastNode = node;
00902             node = node->next;
00903         }
00904     }
00905 }
00906 
00912 void Application::installEventFilter(EventHandler* handler)
00913 {
00914     EventHandlerNode* node = new EventHandlerNode;
00915     node->controllerID = -1;
00916     node->handler = handler;
00917     node->next = d->eventFilters;
00918     d->eventFilters = node;
00919 }
00920 
00926 void Application::removeEventFilter(EventHandler* handler)
00927 {
00928     EventHandlerNode* node = d->eventFilters;
00929     EventHandlerNode* lastNode = 0;
00930     while(node) {
00931         if(node->handler == handler) {
00932             if(lastNode) {
00933                 lastNode->next = node->next;
00934             } else {
00935                 d->eventFilters = node->next;
00936             }
00937             delete node;
00938             return;
00939         }
00940         lastNode = node;
00941         node = node->next;
00942     }
00943 }
00944 
00953 void Application::scheduleTimer(int frames, EventHandler* handler, void* data)
00954 {
00955     TimerNode* timer = new TimerNode;
00956     timer->handler = handler;
00957     timer->framesRemaining = frames;
00958     timer->data = data;
00959 
00960     // We put the new timer in a secondary queue to avoid runaway callbacks if
00961     // a timer is scheduled during another timer's processing.
00962     timer->next = d->addTimers;
00963     d->addTimers = timer;
00964 }
00965 
00970 bool Application::abortGxOnReset() const
00971 {
00972     return d->abortGxOnReset;
00973 }
00974 
00986 void Application::setAbortGxOnReset(bool on)
00987 {
00988     d->abortGxOnReset = on;
00989 }
00990 
00999 void Application::resetButtonPressed()
01000 {
01001     reboot();
01002 }
01003 
01015 void Application::powerButtonPressed(int controllerID)
01016 {
01017     shutdown();
01018 }
01019 
01020 }

Generated on Sat Sep 3 2011 10:25:00 for wit by  doxygen 1.7.2