/** Creates a plugin info * @return orxPLUGIN_INFO / orxNULL */ static orxPLUGIN_INFO *orxFASTCALL orxPlugin_CreatePluginInfo() { orxPLUGIN_INFO *pstPluginInfo; /* Creates a plugin info */ pstPluginInfo = (orxPLUGIN_INFO *)orxBank_Allocate(sstPlugin.pstPluginBank); /* Valid? */ if(pstPluginInfo != orxNULL) { /* Inits it */ orxMemory_Zero(pstPluginInfo, sizeof(orxPLUGIN_INFO)); /* Undefines plugin handle */ pstPluginInfo->hPluginHandle = orxHANDLE_UNDEFINED; /* Creates function bank */ pstPluginInfo->pstFunctionBank = orxBank_Create(orxPLUGIN_KU32_FUNCTION_BANK_SIZE, sizeof(orxPLUGIN_FUNCTION_INFO), orxBANK_KU32_FLAG_NONE, orxMEMORY_TYPE_MAIN); /* Valid? */ if(pstPluginInfo->pstFunctionBank != orxNULL) { /* Creates function hash table */ pstPluginInfo->pstFunctionTable = orxHashTable_Create(orxPLUGIN_KU32_FUNCTION_BANK_SIZE, orxHASHTABLE_KU32_FLAG_NONE, orxMEMORY_TYPE_MAIN); /* Invalid? */ if(pstPluginInfo->pstFunctionTable == orxNULL) { /* Logs message */ orxDEBUG_PRINT(orxDEBUG_LEVEL_PLUGIN, "Invalid function hash table."); /* Frees previously allocated data */ orxBank_Delete(pstPluginInfo->pstFunctionBank); orxBank_Free(sstPlugin.pstPluginBank, pstPluginInfo); /* Not successful */ pstPluginInfo = orxNULL; } } else { /* Logs message */ orxDEBUG_PRINT(orxDEBUG_LEVEL_PLUGIN, "Invalid function bank."); /* Frees previously allocated data */ orxBank_Free(sstPlugin.pstPluginBank, pstPluginInfo); /* Not successful */ pstPluginInfo = orxNULL; } } /* Done! */ return pstPluginInfo; }
/** Unregisters a callback function from a clock * @param[in] _pstClock Concerned clock * @param[in] _fnCallback Callback to remove * @return orxSTATUS_SUCCESS / orxSTATUS_FAILURE */ orxSTATUS orxFASTCALL orxClock_Unregister(orxCLOCK *_pstClock, const orxCLOCK_FUNCTION _pfnCallback) { orxCLOCK_FUNCTION_STORAGE *pstFunctionStorage; orxSTATUS eResult = orxSTATUS_SUCCESS; /* Checks */ orxASSERT(sstClock.u32Flags & orxCLOCK_KU32_STATIC_FLAG_READY); orxSTRUCTURE_ASSERT(_pstClock); orxASSERT(_pfnCallback != orxNULL); /* Finds clock function storage */ pstFunctionStorage = orxClock_FindFunctionStorage(_pstClock, _pfnCallback); /* Found? */ if(pstFunctionStorage != orxNULL) { /* Removes it from list */ orxLinkList_Remove(&(pstFunctionStorage->stNode)); /* Removes it from bank */ orxBank_Free(_pstClock->pstFunctionBank, pstFunctionStorage); } else { /* Logs message */ orxDEBUG_PRINT(orxDEBUG_LEVEL_CLOCK, "Couldn't find clock function storage."); /* Not found */ eResult = orxSTATUS_FAILURE; } /* Done! */ return eResult; }
/** Removes an event handler which matches given context * @param[in] _eEventType Concerned type of event * @param[in] _pfnEventHandler Event handler to remove * @param[in] _pContext Context of the handler to remove, orxNULL for removing all occurrences regardless of their context * return orxSTATUS_SUCCESS / orxSTATUS_FAILURE */ orxSTATUS orxFASTCALL orxEvent_RemoveHandlerWithContext(orxEVENT_TYPE _eEventType, orxEVENT_HANDLER _pfnEventHandler, void *_pContext) { orxEVENT_HANDLER_STORAGE *pstStorage; orxSTATUS eResult = orxSTATUS_FAILURE; /* Checks */ orxASSERT(orxFLAG_TEST(sstEvent.u32Flags, orxEVENT_KU32_STATIC_FLAG_READY)); orxASSERT(_pfnEventHandler != orxNULL); /* Gets corresponding storage */ pstStorage = (_eEventType < orxEVENT_TYPE_CORE_NUMBER) ? sstEvent.astCoreHandlerStorageList[_eEventType] : (orxEVENT_HANDLER_STORAGE *)orxHashTable_Get(sstEvent.pstHandlerStorageTable, _eEventType); /* Valid? */ if(pstStorage != orxNULL) { orxEVENT_HANDLER_INFO *pstInfo; /* For all handlers */ for(pstInfo = (orxEVENT_HANDLER_INFO *)orxLinkList_GetFirst(&(pstStorage->stList)); pstInfo != orxNULL; pstInfo = (orxEVENT_HANDLER_INFO *)orxLinkList_GetNext(&(pstInfo->stNode))) { /* Found? */ if((pstInfo->pfnHandler == _pfnEventHandler) && ((_pContext == orxNULL) || (_pContext == _pfnEventHandler) || (_pContext == pstInfo->pContext))) { /* Removes it from list */ orxLinkList_Remove(&(pstInfo->stNode)); /* Frees it */ orxBank_Free(pstStorage->pstBank, pstInfo); /* Updates result */ eResult = orxSTATUS_SUCCESS; /* Should only remove one? */ if(_pContext == _pfnEventHandler) { /* Stops */ break; } } } } else { /* Defaults to success */ eResult = orxSTATUS_SUCCESS; } /* Done! */ return eResult; }
/** Deletes a function info * @param[in] _pstPluginInfo Concerned plugin info * @param[in] _pstFunctionInfo Concerned function info */ static void orxFASTCALL orxPlugin_DeleteFunctionInfo(orxPLUGIN_INFO *_pstPluginInfo, orxPLUGIN_FUNCTION_INFO *_pstFunctionInfo) { /* Checks */ orxASSERT(_pstPluginInfo != orxNULL); orxASSERT(_pstFunctionInfo != orxNULL); /* Deletes it */ orxBank_Free(_pstPluginInfo->pstFunctionBank, _pstFunctionInfo); /* Done */ return; }
/** Deletes a plugin info * @param[in] _pstPluginInfo Concerned plugin info */ static void orxFASTCALL orxPlugin_DeletePluginInfo(orxPLUGIN_INFO *_pstPluginInfo) { orxPLUGIN_FUNCTION_INFO *pstFunctionInfo; /* Checks */ orxASSERT(_pstPluginInfo != orxNULL); /* Deletes all function info */ for(pstFunctionInfo = (orxPLUGIN_FUNCTION_INFO *)orxBank_GetNext(_pstPluginInfo->pstFunctionBank, orxNULL); pstFunctionInfo != orxNULL; pstFunctionInfo = (orxPLUGIN_FUNCTION_INFO *)orxBank_GetNext(_pstPluginInfo->pstFunctionBank, orxNULL)) { /* Is it a core function? */ if(pstFunctionInfo->eFunctionID & orxPLUGIN_KU32_FLAG_CORE_ID) { /* Registers core function */ orxPlugin_UnregisterCoreFunction(pstFunctionInfo); } /* Deletes it */ orxPlugin_DeleteFunctionInfo(_pstPluginInfo, pstFunctionInfo); } /* Updates all modules */ orxPlugin_UpdateAllModule(); /* Deletes function hash table */ orxHashTable_Delete(_pstPluginInfo->pstFunctionTable); /* Deletes function bank */ orxBank_Delete(_pstPluginInfo->pstFunctionBank); /* Deletes plugin info */ orxBank_Free(sstPlugin.pstPluginBank, _pstPluginInfo); #ifdef __orxPLUGIN_DYNAMIC__ /* Linked to system plugin? */ if(_pstPluginInfo->pstSysPlugin != orxNULL) { /* Closes it */ orxPLUGIN_CLOSE(_pstPluginInfo->pstSysPlugin); _pstPluginInfo->pstSysPlugin = orxNULL; } #endif /* __orxPLUGIN_DYNAMIC__ */ /* Done */ return; }
/** Adds an event handler with user-defined context * @param[in] _eEventType Concerned type of event * @param[in] _pfnHandler Event handler to add * @param[in] _pContext Context that will be stored in events sent to this handler * return orxSTATUS_SUCCESS / orxSTATUS_FAILURE */ orxSTATUS orxFASTCALL orxEvent_AddHandlerWithContext(orxEVENT_TYPE _eEventType, orxEVENT_HANDLER _pfnEventHandler, void *_pContext) { orxEVENT_HANDLER_STORAGE *pstStorage; orxSTATUS eResult = orxSTATUS_FAILURE; /* Checks */ orxASSERT(orxFLAG_TEST(sstEvent.u32Flags, orxEVENT_KU32_STATIC_FLAG_READY)); orxASSERT(_pfnEventHandler != orxNULL); /* Gets corresponding storage */ pstStorage = (_eEventType < orxEVENT_TYPE_CORE_NUMBER) ? sstEvent.astCoreHandlerStorageList[_eEventType] : (orxEVENT_HANDLER_STORAGE *)orxHashTable_Get(sstEvent.pstHandlerStorageTable, _eEventType); /* No storage yet? */ if(pstStorage == orxNULL) { /* Allocates it */ pstStorage = (orxEVENT_HANDLER_STORAGE *)orxBank_Allocate(sstEvent.pstHandlerStorageBank); /* Success? */ if(pstStorage != orxNULL) { /* Creates its bank */ pstStorage->pstBank = orxBank_Create(orxEVENT_KU32_HANDLER_BANK_SIZE, sizeof(orxEVENT_HANDLER_INFO), orxBANK_KU32_FLAG_NONE, orxMEMORY_TYPE_MAIN); /* Success? */ if(pstStorage->pstBank != orxNULL) { /* Clears its list */ orxMemory_Zero(&(pstStorage->stList), sizeof(orxLINKLIST)); /* Is a core event handler? */ if(_eEventType < orxEVENT_TYPE_CORE_NUMBER) { /* Stores it */ sstEvent.astCoreHandlerStorageList[_eEventType] = pstStorage; } else { /* Tries to add it to the table */ if(orxHashTable_Add(sstEvent.pstHandlerStorageTable, _eEventType, pstStorage) == orxSTATUS_FAILURE) { /* Deletes its bank */ orxBank_Delete(pstStorage->pstBank); /* Frees storage */ orxBank_Free(sstEvent.pstHandlerStorageBank, pstStorage); pstStorage = orxNULL; } } } else { /* Frees storage */ orxBank_Free(sstEvent.pstHandlerStorageBank, pstStorage); pstStorage = orxNULL; } } } /* Valid? */ if(pstStorage != orxNULL) { orxEVENT_HANDLER_INFO *pstInfo; /* Allocates a new handler info */ pstInfo = (orxEVENT_HANDLER_INFO *)orxBank_Allocate(pstStorage->pstBank); /* Valid? */ if(pstInfo != orxNULL) { /* Clears its node */ orxMemory_Zero(&(pstInfo->stNode), sizeof(orxLINKLIST_NODE)); /* Stores its handler */ pstInfo->pfnHandler = _pfnEventHandler; /* Stores context */ pstInfo->pContext = _pContext; /* Adds it to the list */ eResult = orxLinkList_AddEnd(&(pstStorage->stList), &(pstInfo->stNode)); } } /* Done! */ return eResult; }
/** Remove an item. * @param[in] _pstHashTable The hash table where remove. * @param[in] _u64Key Key to remove. * @return Returns the status of the operation. */ orxSTATUS orxFASTCALL orxHashTable_Remove(orxHASHTABLE *_pstHashTable, orxU64 _u64Key) { orxU32 u32Index; /* Hash table index */ orxHASHTABLE_CELL *pstCell; /* Cell used to traverse */ orxSTATUS eStatus = orxSTATUS_FAILURE; /* Status to return */ /* Profiles */ orxPROFILER_PUSH_MARKER("orxHashTable_Remove"); /* Checks */ orxASSERT(_pstHashTable != orxNULL); /* Get the index from the key */ u32Index = orxHashTable_FindIndex(_pstHashTable, _u64Key); pstCell = _pstHashTable->apstCell[u32Index]; /* Is the first key is the key to remove ? */ if(pstCell != orxNULL) { if(pstCell->u64Key == _u64Key) { /* The first cell has to be removed */ _pstHashTable->apstCell[u32Index] = pstCell->pstNext; orxBank_Free(_pstHashTable->pstBank, pstCell); /* Operation succeed */ eStatus = orxSTATUS_SUCCESS; } else { /* Traverse to find the key */ while(pstCell->pstNext != orxNULL && pstCell->pstNext->u64Key != _u64Key) { /* Try with next cell */ pstCell = pstCell->pstNext; } /* Cell found ? (key should be on the next cell) */ if(pstCell->pstNext != orxNULL) { orxHASHTABLE_CELL *pstRemoveCell; /* We found it, remove this cell */ pstRemoveCell = pstCell->pstNext; pstCell->pstNext = pstRemoveCell->pstNext; /* Free cell from bank */ orxBank_Free(_pstHashTable->pstBank, pstRemoveCell); /* Operation succeed */ eStatus = orxSTATUS_SUCCESS; } } } /* Successful? */ if(eStatus != orxSTATUS_FAILURE) { /* Updates counter */ _pstHashTable->u32Counter--; } /* Profiles */ orxPROFILER_POP_MARKER(); /* Done! */ return eStatus; }
/** Deletes a clock * @param[in] _pstClock Concerned clock * @return orxSTATUS_SUCCESS / orxSTATUS_FAILURE */ orxSTATUS orxFASTCALL orxClock_Delete(orxCLOCK *_pstClock) { orxSTATUS eResult = orxSTATUS_SUCCESS; /* Checks */ orxASSERT(sstClock.u32Flags & orxCLOCK_KU32_STATIC_FLAG_READY); orxSTRUCTURE_ASSERT(_pstClock); /* Decreases counter */ orxStructure_DecreaseCounter(_pstClock); /* Not referenced? */ if(orxStructure_GetRefCounter(_pstClock) == 0) { /* Not locked? */ if(!orxStructure_TestFlags(_pstClock, orxCLOCK_KU32_FLAG_UPDATE_LOCK)) { orxCLOCK_TIMER_STORAGE *pstTimerStorage; /* For all stored timers */ for(pstTimerStorage = (orxCLOCK_TIMER_STORAGE *)orxLinkList_GetFirst(&(_pstClock->stTimerList)); pstTimerStorage != orxNULL; pstTimerStorage = (orxCLOCK_TIMER_STORAGE *)orxLinkList_GetFirst(&(_pstClock->stTimerList))) { /* Removes it */ orxLinkList_Remove(&(pstTimerStorage->stNode)); /* Deletes it */ orxBank_Free(sstClock.pstTimerBank, pstTimerStorage); } /* Deletes function bank */ orxBank_Delete(_pstClock->pstFunctionBank); /* Is referenced? */ if(orxStructure_TestFlags(_pstClock, orxCLOCK_KU32_FLAG_REFERENCED)) { /* Removes it from reference table */ orxHashTable_Remove(sstClock.pstReferenceTable, orxString_ToCRC(_pstClock->zReference)); } /* Has reference? */ if(_pstClock->zReference != orxNULL) { /* Unprotects it */ orxConfig_ProtectSection(_pstClock->zReference, orxFALSE); } /* Deletes clock */ orxStructure_Delete(_pstClock); } else { /* Increases counter */ orxStructure_IncreaseCounter(_pstClock); /* Logs message */ orxDEBUG_PRINT(orxDEBUG_LEVEL_CLOCK, "Can't delete clock <%s> as it's currently locked for processing!", orxStructure_TestFlags(_pstClock, orxCLOCK_KU32_FLAG_REFERENCED) ? _pstClock->zReference : orxSTRING_EMPTY); /* Updates result */ eResult = orxSTATUS_FAILURE; } } else { /* Referenced by others */ eResult = orxSTATUS_FAILURE; } /* 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; }