reman3/Rayman_X/cpa/tempgrp/ITF/cpawdata.cpp

256 lines
5.4 KiB
C++

#include "stdafx.h"
#include "acp_base.h"
#ifdef ACTIVE_EDITOR
#include "itf/CPAWData.hpp"
#pragma warning(disable:4355)
CPA_WalkDataMgr::CPA_WalkDataMgr():WalkData(this, NULL) {
for (iVoid=0; iVoid<MAX_WALKDATA_ELEMENT; iVoid++) {
aWD [iVoid].ItsData = NULL;
aWD [iVoid].backnext = NO_ID;
aWD [iVoid].backprev = NO_ID;
aWD [iVoid].next = NO_ID;
aWD [iVoid].prev = NO_ID;
}
iVoid = 0;
iCount = 0;
}
CPA_WalkDataMgr::~CPA_WalkDataMgr() {
int i;
for (i=iCurrent; i!=NO_ID; i=aWD[i].backprev) {
delete ((WalkData *)aWD[i].ItsData);
}
}
void CPA_WalkDataMgr::InsertElement (CPA_DLLBase *pDLL, void *ItsData) {
GoElement (pDLL);
WalkData *pWDToInsertTo = (WalkData *)aWD[iCurrent].ItsData;
#ifdef CHECK // check if occurence already exists.
if (!pWDToInsertTo->CheckAndGoElement (ItsData)) {
pWDToInsertTo->InsertVoidElement (ItsData);
UpdateIVoid();
}
#else
pWDToInsertTo->InsertVoidElement (ItsData);
UpdateIVoid();
#endif
}
void CPA_WalkDataMgr::ActiveElement (CPA_DLLBase *pDLL) {
GoElement (pDLL);
ActiveCurrent();
}
/******************** private *******************/
void CPA_WalkDataMgr::UpdateAll () {
int i;
for (i=iCurrent; i!=NO_ID; i=aWD[i].backprev) {
((WalkData *)aWD[i].ItsData)->UpdateList();
}
}
void CPA_WalkDataMgr::UpdateIVoid() {
int i, j;
WalkData *pWD;
if (iCount!=MAX_WALKDATA_ELEMENT-1) {
iVoid = ++iCount;
}
else {// take an element already used
i=iLastUsed;
do {
pWD = (WalkData *)aWD[i].ItsData;
i=aWD[i].next;
}
while (pWD->iCurrent==NO_ID);
j = pWD->iLastUsed;
iVoid = j;
// tell DLL that the data is no longer of use.
pWD->MyDLL->fn_vEraseWalkDataStructure (aWD[j].ItsData);
// update list
if (j == pWD->iCurrent) // this WD had only one element
pWD->iCurrent = NO_ID;
else { // update the element linked to the one we took
pWD->iLastUsed = aWD[j].next;
aWD[pWD->iLastUsed].prev = NO_ID;
aWD[pWD->iLastUsed].backprev = NO_ID;
}
// clean new Void element (for safety)
aWD[j].next = aWD[j].prev = NO_ID;
aWD[j].backnext = aWD[j].backprev = NO_ID;
}
}
int CPA_WalkDataMgr::FindOrCreateWalkData (CPA_DLLBase *pDLL) {
int i, iInsertNode;
for (i=iCurrent; i!=NO_ID; i=aWD[i].backprev) {
if (((WalkData *)aWD[i].ItsData)->MyDLL == pDLL) {
iInsertNode = i;
break;
}
}
if (i==NO_ID) { // New Node
iInsertNode = iVoid;
InsertVoidElement((void *)new WalkData (this, pDLL));
UpdateIVoid();
}
return (iInsertNode);
}
void CPA_WalkDataMgr::GoElement (CPA_DLLBase *pDLL) {
int iNew;
UpdateAll ();
iNew = FindOrCreateWalkData (pDLL);
if (iNew != iCurrent) Go (iNew);
UpdateList ();
}
inline void CPA_WalkDataMgr::ActiveCurrent() {
((WalkData *)aWD[iCurrent].ItsData)->BackActive();
}
void CPA_WalkDataMgr::DBackward() {
if (iCurrent!=NO_ID)
if (((WalkData *)aWD[iCurrent].ItsData)->Backward())
ActiveCurrent();
}
void CPA_WalkDataMgr::DForward() {
if (iCurrent!=NO_ID)
if (((WalkData *)aWD[iCurrent].ItsData)->Forward())
ActiveCurrent();
}
void CPA_WalkDataMgr::EBackward() {
if (Backward ())
ActiveCurrent();
}
void CPA_WalkDataMgr::EForward() {
if (Forward ())
ActiveCurrent();
}
/************************* WalkData ************************/
WalkData::WalkData(CPA_WalkDataMgr *aWDM, CPA_DLLBase *pDLL) {
MyWDM = aWDM;
aWD = aWDM->aWD; // ne changera pas
iCurrent = NO_ID;
iFirst = NO_ID;
iLast = NO_ID;
iLastUsed = NO_ID;
MyDLL = pDLL;
}
inline void WalkData::ABLink (int a, int b) {aWD[a].next = b; aWD[b].prev = a;BLink(a,b);}
inline void WalkData::BLink (int a, int b) {aWD[a].backnext = b; aWD[b].backprev = a;}
void WalkData::UpdateList(){
int i;
if ((iCurrent==NO_ID) || (iLast==iCurrent)) return;
for (i=iLast; i!=NO_ID; i=aWD[i].backnext) { // updatelist
aWD[i].prev = aWD[i].backprev;
aWD[i].next = aWD[i].backnext;
};
iLast = iCurrent;
}
int WalkData::CheckAndGoElement (void *ItsData) {
int i;
for (i=iCurrent; i!=NO_ID; i=aWD[i].prev) {
if ((aWD[i].ItsData == ItsData) && (aWD[i].ItsData == ItsData)) {
if (i!=iCurrent) Go(i);
UpdateList();
return (TRUE);
}
}
return (FALSE);
}
void WalkData::InsertVoidElement (void *ItsData) {
UpdateList();
iLast = iFirst = MyWDM->iVoid;
if (iCurrent!=NO_ID)
ABLink (iCurrent, iFirst);
else {
iLastUsed = iFirst;
aWD[iFirst].prev = NO_ID;
aWD[iFirst].backprev = NO_ID;
}
aWD[iFirst].aWalkData = this;
aWD[iFirst].ItsData = ItsData;
aWD[iFirst].next = NO_ID;
aWD[iFirst].backnext = NO_ID;
iCurrent = iFirst;
}
int WalkData::Backward() {
int iNew;
if (iCurrent==NO_ID) return (FALSE);
iNew = aWD[iCurrent].prev;
if (iNew == NO_ID) return (FALSE);
Go (iNew);
return (TRUE);
}
int WalkData::Forward() {
int iNew;
if (iCurrent==NO_ID) return (FALSE);
iNew = aWD[iCurrent].next;
if (iNew == NO_ID) return (FALSE);
Go (iNew);
return (TRUE);
}
void WalkData::Go(int iNew) { // iNew must not be iCurrent nor NO_ID
int i, j, k;
j = aWD[iNew].backprev;
k = aWD[iNew].backnext;
if (j!=NO_ID)
BLink (j, k);
else {
aWD[k].backprev = NO_ID;
if (iLast==iNew) iLast = k;
else j=k; // to update iLast correctly
}
if (iLastUsed==iNew) iLastUsed = k;
BLink (iCurrent, iNew);
aWD[iNew].backnext = NO_ID;
iCurrent = iNew;
// update iLast if needed
for (i=j; (i!=iLast) && (i!=NO_ID); i=aWD[i].backnext);
if (i==iLast) iLast = j;
}
void WalkData::BackActive () {
if (iCurrent==NO_ID)
MyDLL->fn_vBackActiveMe (NULL);
else
MyDLL->fn_vBackActiveMe (aWD[iCurrent].ItsData);
}
#endif