/** Finds the next clock in list given a tick size and a type * @param[in] _fTickSize Desired tick size * @param[in] _eType Desired type * @param[in] _pstStartClock Clock used as a starting point in the list * @return orxCLOCK / orxNULL */ static orxINLINE orxCLOCK *orxClock_FindClock(orxFLOAT _fTickSize, orxCLOCK_TYPE _eType, const orxCLOCK *_pstStartClock) { orxCLOCK *pstClock; /* Checks */ orxASSERT(sstClock.u32Flags & orxCLOCK_KU32_STATIC_FLAG_READY); orxASSERT(_eType < orxCLOCK_TYPE_NUMBER); /* Finds matching clock */ for(pstClock = (_pstStartClock != orxNULL) ? orxCLOCK(orxStructure_GetNext(_pstStartClock)) : orxCLOCK(orxStructure_GetFirst(orxSTRUCTURE_ID_CLOCK)); pstClock != orxNULL; pstClock = orxCLOCK(orxStructure_GetNext(pstClock))) { /* Match? */ if((pstClock->stClockInfo.eType == _eType) && ((_fTickSize < orxFLOAT_0) || (pstClock->stClockInfo.fTickSize == _fTickSize))) { /* Found */ break; } } /* Done! */ return pstClock; }
/** Gets next existing clock in list (can be used to parse all existing clocks) * @param[in] _pstClock Concerned clock * @return orxCLOCK / orxNULL */ orxCLOCK *orxFASTCALL orxClock_GetNext(const orxCLOCK *_pstClock) { /* Checks */ orxASSERT(sstClock.u32Flags & orxCLOCK_KU32_STATIC_FLAG_READY); /* Returns next stored clock */ return(orxCLOCK(orxStructure_GetNext(_pstClock))); }
/** Event handler * @param[in] _pstEvent Sent event * @return orxSTATUS_SUCCESS if handled / orxSTATUS_FAILURE otherwise */ static orxSTATUS orxFASTCALL orxGraphic_EventHandler(const orxEVENT *_pstEvent) { orxSTATUS eResult = orxSTATUS_SUCCESS; /* Checks */ orxASSERT(_pstEvent->eType == orxEVENT_TYPE_LOCALE); /* Depending on event ID */ switch(_pstEvent->eID) { /* Select language event */ case orxLOCALE_EVENT_SELECT_LANGUAGE: { orxGRAPHIC *pstGraphic; /* For all graphics */ for(pstGraphic = orxGRAPHIC(orxStructure_GetFirst(orxSTRUCTURE_ID_GRAPHIC)); pstGraphic != orxNULL; pstGraphic = orxGRAPHIC(orxStructure_GetNext(pstGraphic))) { /* Is data a text? */ if(orxStructure_TestFlags(pstGraphic, orxGRAPHIC_KU32_FLAG_TEXT)) { /* Updates graphic's size */ orxGraphic_UpdateSize(pstGraphic); } } break; } default: { break; } } /* Done! */ return eResult; }
/** Resyncs all clocks (accumulated DT => 0) * @return orxSTATUS_SUCCESS / orxSTATUS_FAILURE */ orxSTATUS orxFASTCALL orxClock_ResyncAll() { orxCLOCK *pstClock; orxSTATUS eResult = orxSTATUS_SUCCESS; /* Checks */ orxASSERT(sstClock.u32Flags & orxCLOCK_KU32_STATIC_FLAG_READY); /* For all clocks */ for(pstClock = orxCLOCK(orxStructure_GetFirst(orxSTRUCTURE_ID_CLOCK)); pstClock != orxNULL; pstClock = orxCLOCK(orxStructure_GetNext(pstClock))) { /* Not already failed? */ if(eResult != orxSTATUS_FAILURE) { /* Resyncs clock */ eResult = orxClock_Resync(pstClock); } } /* Done! */ return eResult; }
/** Event handler */ static orxSTATUS orxFASTCALL orxTimeLine_EventHandler(const orxEVENT *_pstEvent) { orxSTATUS eResult = orxSTATUS_SUCCESS; /* Add or update? */ if((_pstEvent->eID == orxRESOURCE_EVENT_ADD) || (_pstEvent->eID == orxRESOURCE_EVENT_UPDATE)) { orxRESOURCE_EVENT_PAYLOAD *pstPayload; /* Gets payload */ pstPayload = (orxRESOURCE_EVENT_PAYLOAD *)_pstEvent->pstPayload; /* Is config group? */ if(pstPayload->u32GroupID == orxString_ToCRC(orxCONFIG_KZ_RESOURCE_GROUP)) { orxHANDLE hIterator; orxU64 u64Key; orxTIMELINE_TRACK *pstTrack; /* For all tracks */ for(hIterator = orxHashTable_GetNext(sstTimeLine.pstTrackTable, orxHANDLE_UNDEFINED, &u64Key, (void **)&pstTrack); hIterator != orxHANDLE_UNDEFINED; hIterator = orxHashTable_GetNext(sstTimeLine.pstTrackTable, hIterator, &u64Key, (void **)&pstTrack)) { /* Match origin? */ if(orxConfig_GetOriginID(pstTrack->zReference) == pstPayload->u32NameID) { orxTIMELINE *pstTimeLine; orxTIMELINE_TRACK *pstNewTrack; orxU32 u32Counter, u32ID, u32Flags; const orxSTRING zReference; /* Backups counter, ID, flags & reference */ u32Counter = pstTrack->u32RefCounter; u32ID = pstTrack->u32ID; u32Flags = orxFLAG_GET(pstTrack->u32Flags, orxTIMELINE_TRACK_KU32_MASK_BACKUP); zReference = pstTrack->zReference; /* Deletes it (but keeps it reference in the hashtable to prevent infinite loop upon table changes) */ orxMemory_Free(pstTrack); /* Creates new track */ pstNewTrack = orxTimeLine_CreateTrack(zReference); /* Success? */ if(pstNewTrack != orxNULL) { /* Restores its counter */ pstNewTrack->u32RefCounter = u32Counter; /* Restores its flags */ orxFLAG_SET(pstNewTrack->u32Flags, u32Flags, orxTIMELINE_TRACK_KU32_MASK_BACKUP); } else { /* Removes old reference from the table */ orxHashTable_Remove(sstTimeLine.pstTrackTable, u32ID); } /* For all timelines */ for(pstTimeLine = orxTIMELINE(orxStructure_GetFirst(orxSTRUCTURE_ID_TIMELINE)); pstTimeLine != orxNULL; pstTimeLine = orxTIMELINE(orxStructure_GetNext(pstTimeLine))) { orxU32 u32Index; /* For all its track */ for(u32Index = 0; u32Index < orxTIMELINE_KU32_TRACK_NUMBER; u32Index++) { /* Matches? */ if(pstTimeLine->astTrackList[u32Index].pstTrack == pstTrack) { /* Updates its data */ pstTimeLine->astTrackList[u32Index].pstTrack = pstNewTrack; } } } } } } } /* Done! */ return eResult; }
/** Event handler * @param[in] _pstEvent Sent event * @return orxSTATUS_SUCCESS if handled / orxSTATUS_FAILURE otherwise */ static orxSTATUS orxFASTCALL orxText_EventHandler(const orxEVENT *_pstEvent) { orxSTATUS eResult = orxSTATUS_SUCCESS; /* Locale? */ if(_pstEvent->eType == orxEVENT_TYPE_LOCALE) { /* Select language event? */ if(_pstEvent->eID == orxLOCALE_EVENT_SELECT_LANGUAGE) { orxTEXT *pstText; /* For all texts */ for(pstText = orxTEXT(orxStructure_GetFirst(orxSTRUCTURE_ID_TEXT)); pstText != orxNULL; pstText = orxTEXT(orxStructure_GetNext(pstText))) { const orxSTRING zLocaleKey; /* Gets its corresponding locale string */ zLocaleKey = orxText_GetLocaleKey(pstText, orxTEXT_KZ_CONFIG_STRING); /* Valid? */ if(zLocaleKey != orxNULL) { const orxSTRING zText; /* Gets its localized value */ zText = orxLocale_GetString(zLocaleKey); /* Valid? */ if(*zText != orxCHAR_NULL) { /* Updates text */ orxText_SetString(pstText, zText); } } /* Gets its corresponding locale font */ zLocaleKey = orxText_GetLocaleKey(pstText, orxTEXT_KZ_CONFIG_FONT); /* Valid? */ if(zLocaleKey != orxNULL) { orxFONT *pstFont; /* Creates font */ pstFont = orxFont_CreateFromConfig(orxLocale_GetString(zLocaleKey)); /* Valid? */ if(pstFont != orxNULL) { /* Updates text */ if(orxText_SetFont(pstText, pstFont) != orxSTATUS_FAILURE) { /* Sets its owner */ orxStructure_SetOwner(pstFont, pstText); /* Updates flags */ orxStructure_SetFlags(pstText, orxTEXT_KU32_FLAG_INTERNAL, orxTEXT_KU32_FLAG_NONE); } else { /* Sets default font */ orxText_SetFont(pstText, orxFONT(orxFont_GetDefaultFont())); } } } } } } /* Resource */ else { /* Checks */ orxASSERT(_pstEvent->eType == orxEVENT_TYPE_RESOURCE); /* Add or update? */ if((_pstEvent->eID == orxRESOURCE_EVENT_ADD) || (_pstEvent->eID == orxRESOURCE_EVENT_UPDATE)) { orxRESOURCE_EVENT_PAYLOAD *pstPayload; /* Gets payload */ pstPayload = (orxRESOURCE_EVENT_PAYLOAD *)_pstEvent->pstPayload; /* Is config group? */ if(pstPayload->u32GroupID == orxString_ToCRC(orxCONFIG_KZ_RESOURCE_GROUP)) { orxTEXT *pstText; /* For all texts */ for(pstText = orxTEXT(orxStructure_GetFirst(orxSTRUCTURE_ID_TEXT)); pstText != orxNULL; pstText = orxTEXT(orxStructure_GetNext(pstText))) { /* Match origin? */ if(orxConfig_GetOriginID(pstText->zReference) == pstPayload->u32NameID) { /* Re-processes its config data */ orxText_ProcessConfigData(pstText); } } } } } /* Done! */ return eResult; }
/** Updates the clock system * @return orxSTATUS_SUCCESS / orxSTATUS_FAILURE */ orxSTATUS orxFASTCALL orxClock_Update() { orxDOUBLE dNewTime; orxFLOAT fDT, fDelay; orxCLOCK *pstClock; orxSTATUS eResult = orxSTATUS_SUCCESS; /* Checks */ orxASSERT(sstClock.u32Flags & orxCLOCK_KU32_STATIC_FLAG_READY); /* Not already locked? */ if(!(sstClock.u32Flags & orxCLOCK_KU32_STATIC_FLAG_UPDATE_LOCK)) { /* Lock clocks */ sstClock.u32Flags |= orxCLOCK_KU32_STATIC_FLAG_UPDATE_LOCK; /* Gets new time */ dNewTime = orxSystem_GetTime(); /* Computes natural DT */ fDT = (orxFLOAT)(dNewTime - sstClock.dTime); /* Gets modified DT */ fDT = orxClock_ComputeDT(fDT, orxNULL); /* Updates time */ sstClock.dTime = dNewTime; /* Inits delay */ fDelay = sstClock.fMainClockTickSize; /* For all clocks */ for(pstClock = orxCLOCK(orxStructure_GetFirst(orxSTRUCTURE_ID_CLOCK)); pstClock != orxNULL; pstClock = orxCLOCK(orxStructure_GetNext(pstClock))) { /* Locks it */ orxStructure_SetFlags(pstClock, orxCLOCK_KU32_FLAG_UPDATE_LOCK, orxCLOCK_KU32_FLAG_NONE); /* Is clock not paused? */ if(orxClock_IsPaused(pstClock) == orxFALSE) { orxFLOAT fClockDelay; /* Updates clock real time & partial DT */ pstClock->fPartialDT += fDT; /* New tick happens? */ if(pstClock->fPartialDT >= pstClock->stClockInfo.fTickSize) { orxFLOAT fClockDT; orxCLOCK_TIMER_STORAGE *pstTimerStorage; orxCLOCK_FUNCTION_STORAGE *pstFunctionStorage; /* Gets clock modified DT */ fClockDT = orxClock_ComputeDT(pstClock->fPartialDT, &(pstClock->stClockInfo)); /* Updates clock DT */ pstClock->stClockInfo.fDT = fClockDT; /* Updates clock time */ pstClock->stClockInfo.fTime += fClockDT; /* For all timers */ for(pstTimerStorage = (orxCLOCK_TIMER_STORAGE *)orxLinkList_GetFirst(&(pstClock->stTimerList)); pstTimerStorage != orxNULL;) { /* Should call it? */ if((pstTimerStorage->fTimeStamp <= pstClock->stClockInfo.fTime) && (pstTimerStorage->s32Repetition != 0)) { /* Calls it */ pstTimerStorage->pfnCallback(&(pstClock->stClockInfo), pstTimerStorage->pContext); /* Updates its time stamp */ pstTimerStorage->fTimeStamp = pstClock->stClockInfo.fTime + pstTimerStorage->fDelay; /* Should update counter */ if(pstTimerStorage->s32Repetition > 0) { /* Updates it */ pstTimerStorage->s32Repetition--; } } /* Should delete it */ if(pstTimerStorage->s32Repetition == 0) { orxCLOCK_TIMER_STORAGE *pstDelete; /* Gets timer to delete */ pstDelete = pstTimerStorage; /* Gets the next timer */ pstTimerStorage = (orxCLOCK_TIMER_STORAGE *)orxLinkList_GetNext(&(pstTimerStorage->stNode)); /* Removes current timer */ orxLinkList_Remove(&(pstDelete->stNode)); /* Deletes it */ orxBank_Free(sstClock.pstTimerBank, pstDelete); } else { /* Gets the next timer */ pstTimerStorage = (orxCLOCK_TIMER_STORAGE *)orxLinkList_GetNext(&(pstTimerStorage->stNode)); } } /* For all registered callbacks */ for(pstFunctionStorage = (orxCLOCK_FUNCTION_STORAGE *)orxLinkList_GetFirst(&(pstClock->stFunctionList)); pstFunctionStorage != orxNULL; pstFunctionStorage = (orxCLOCK_FUNCTION_STORAGE *)orxLinkList_GetNext(&(pstFunctionStorage->stNode))) { /* Calls it */ pstFunctionStorage->pfnCallback(&(pstClock->stClockInfo), pstFunctionStorage->pContext); } /* Updates partial DT */ pstClock->fPartialDT = orxFLOAT_0; } /* Gets clock's delay */ fClockDelay = pstClock->stClockInfo.fTickSize - pstClock->fPartialDT; /* Smaller than previous clocks' delay? */ if(fClockDelay < fDelay) { /* Stores it */ fDelay = fClockDelay; } } /* Unlocks it */ orxStructure_SetFlags(pstClock, orxCLOCK_KU32_FLAG_NONE, orxCLOCK_KU32_FLAG_UPDATE_LOCK); } /* Unlocks clocks */ sstClock.u32Flags &= ~orxCLOCK_KU32_STATIC_FLAG_UPDATE_LOCK; /* Gets real remaining delay */ fDelay = fDelay + orxCLOCK_KF_DELAY_ADJUSTMENT - orx2F(orxSystem_GetTime() - sstClock.dTime); /* Should delay? */ if(fDelay > orxFLOAT_0) { /* Waits for next time slice */ orxSystem_Delay(fDelay); } } /* Done! */ return eResult; }