mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
168 lines
5.5 KiB
C++
168 lines
5.5 KiB
C++
//---------------------------------------------------------------------------
|
|
|
|
#include <vcl.h>
|
|
#pragma hdrstop
|
|
|
|
#include "Names.h"
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
#pragma package(smart_init)
|
|
/*
|
|
Moduł zarządzający plikami oraz wyszukiwaniem obiektów wg nazw.
|
|
1. Ma przydzielony z góry (EU07.INI) obszar pamięci (rzędu 16MB).
|
|
2. W przypadku przepełnienia dostępnej pamięci wystąpi błąd wczytywania.
|
|
3. Obszar ten będzie zużywany na rekordy obiektów oraz ciągi tekstowe z nazwami.
|
|
4. Rekordy będą sortowane w ramach typu (tekstury, dźwięki, modele, node, eventy).
|
|
5. Pierwszy etap wyszukiwania to 5 bitów z pierwszego bajtu i 3 z drugiego (256).
|
|
6. Dla plików istnieje możliwość wczytania ich w innym terminie.
|
|
7. Możliwość wczytania plików w oddzielnym watku (np. tekstur).
|
|
|
|
Obsługiwane pliki:
|
|
1. Tekstury, można wczytywać później, rekord przechowuje numer podany przez kartę graficzną.
|
|
2. Dźwięki, można wczytać później.
|
|
3. Modele, można wczytać później o ile nie mają animacji eventami i nie dotyczą pojazdów.
|
|
|
|
Obiekty sortowane wg nazw, można dodawać i usuwać komórki scenerii:
|
|
4. Tory, drogi, rzeki - wyszukiwanie w celu sprawdzenia zajetości.
|
|
5. Eventy - wyszukiwane przy zewnętrznym wywołaniu oraz podczas wczytywania.
|
|
6. Pojazdy - wyszukiwane w celu wysyłania komend.
|
|
7. Egzemplarze modeli animowanych - wyszukiwanie w celu połączenia z animacjami.
|
|
|
|
*/
|
|
|
|
void __fastcall ItemRecord::TreeAdd(ItemRecord *r,int c)
|
|
{//dodanie rekordu do drzewa - ustalenie w której gałęzi
|
|
//zapisać w (iFlags) ile znaków jest zgodnych z nadrzędnym, żeby nie sprawdzać wszystkich od zera
|
|
if ((cName[c]&&r->cName[c])?cName[c]==r->cName[c]:false)
|
|
TreeAdd(r,c+1); //ustawić wg kolejnego znaku, chyba że zero
|
|
else
|
|
if ((unsigned char)(cName[c])<(unsigned char)(r->cName[c]))
|
|
{//zero jest najmniejsze - doczepiamy jako (rNext)
|
|
if (!rNext) rNext=r;
|
|
else rNext->TreeAdd(r,0); //doczepić do tej gałęzi
|
|
}
|
|
else
|
|
{
|
|
if (!rPrev) rPrev=r;
|
|
else rPrev->TreeAdd(r,0); //doczepić do tej gałęzi
|
|
}
|
|
};
|
|
|
|
void __fastcall ItemRecord::ListGet(ItemRecord *r,int*&n)
|
|
{//rekurencyjne wypełnianie posortowanej listy na podstawie drzewa
|
|
if (rPrev) rPrev->ListGet(r,n); //dodanie wszystkich wcześniejszych
|
|
*n++=this-r; //dodanie swojego indeksu do tabeli
|
|
if (rNext) rNext->ListGet(r,n); //dodanie wszystkich późniejszych
|
|
};
|
|
|
|
void* __fastcall ItemRecord::TreeFind(const char *n)
|
|
{//wyszukanie ciągu (n)
|
|
ItemRecord *r=TreeFindRecord(n);
|
|
return r?r->pData:NULL;
|
|
};
|
|
|
|
ItemRecord* __fastcall ItemRecord::TreeFindRecord(const char *n)
|
|
{//wyszukanie ciągu (n)
|
|
ItemRecord *r=this; //żeby nie robić rekurencji
|
|
int i=0;
|
|
do
|
|
{
|
|
if (!n[i]) if (!r->cName[i]) return r; //znaleziony
|
|
if (n[i]==r->cName[i])
|
|
++i; //porównać kolejny znak
|
|
else
|
|
if ((unsigned char)(n[i])<(unsigned char)(r->cName[i]))
|
|
{
|
|
i=0; //porównywać od nowa
|
|
r=r->rPrev; //wcześniejsza gałąź drzewa
|
|
}
|
|
else
|
|
{
|
|
i=0; //porównywać od nowa
|
|
r=r->rNext; //późniejsza gałąź drzewa
|
|
}
|
|
} while (r);
|
|
return NULL;
|
|
};
|
|
|
|
__fastcall TNames::TNames()
|
|
{//tworzenie bufora
|
|
iSize=16*1024*1024; //rozmiar bufora w bajtach
|
|
cBuffer=new char[iSize];
|
|
ZeroMemory(cBuffer,iSize); //nie trzymać jakiś starych śmieci
|
|
rRecords=(ItemRecord*)cBuffer;
|
|
cLast=cBuffer+iSize; //bajt za buforem
|
|
iLast=-1;
|
|
ZeroMemory(rTypes,20*sizeof(ItemRecord*));
|
|
};
|
|
|
|
int __fastcall TNames::Add(int t,const char *n)
|
|
{//dodanie obiektu typu (t) o nazwie (n)
|
|
int len=strlen(n)+1; //ze znacznikiem końca
|
|
cLast-=len; //rezerwacja miejsca
|
|
memcpy(cLast,n,len); //przekopiowanie tekstu do bufora
|
|
//cLast[len-1]='\0';
|
|
rRecords[++iLast].cName=cLast; //połączenie nazwy z rekordem
|
|
rRecords[iLast].iFlags=t;
|
|
if (!rTypes[t])
|
|
rTypes[t]=rRecords+iLast; //korzeń drzewa, bo nie było wcześniej
|
|
else
|
|
rTypes[t]->TreeAdd(rRecords+iLast,0); //doczepienie jako gałąź
|
|
//rTypes[t]=Sort(t); //sortowanie uruchamiać ręcznie
|
|
if ((iLast&0x3F)==0) //nie za często, bo sortowania zajmą więcej czasu niż wyszukiwania
|
|
Sort(t); //optymalizacja drzewa co jakiś czas
|
|
return iLast;
|
|
}
|
|
int __fastcall TNames::Add(int t,const char *n,void *d)
|
|
{
|
|
int i=Add(t,n);
|
|
rRecords[iLast].pData=d;
|
|
return i;
|
|
};
|
|
|
|
bool __fastcall TNames::Update(int t,const char *n,void *d)
|
|
{//dodanie jeśli nie ma, wymiana (d), gdy jest
|
|
ItemRecord *r=FindRecord(t,n); //najpierw sprawdzić, czy już jest
|
|
if (r)
|
|
{//przy zdublowaniu nazwy podmieniać w drzewku na późniejszy
|
|
r->pData=d;
|
|
return true; //duplikat
|
|
}
|
|
//Add(t,n,d); //nazwa unikalna
|
|
return false; //został dodany nowy
|
|
};
|
|
|
|
ItemRecord* __fastcall TNames::TreeSet(int *n,int d,int u)
|
|
{//rekurencyjne wypełnianie drzewa pozycjami od (d) do (u)
|
|
if (d==u)
|
|
{
|
|
rRecords[n[d]].rPrev=rRecords[n[d]].rNext=NULL;
|
|
return rRecords+n[d]; //tej gałęzi nie ma
|
|
}
|
|
else if (d>u) return NULL;
|
|
int p=(u+d)>>1; //połowa
|
|
rRecords[n[p]].rPrev=TreeSet(n,d,p-1); //zapisanie wcześniejszych gałęzi
|
|
rRecords[n[p]].rNext=TreeSet(n,p+1,u); //zapisanie późniejszych gałęzi
|
|
return rRecords+n[p];
|
|
};
|
|
|
|
void __fastcall TNames::Sort(int t)
|
|
{//przebudowa drzewa typu (t), zwraca wierzchołek drzewa
|
|
if (iLast<3) return; //jak jest mało, to nie ma sensu sortować
|
|
if (rTypes[t]) //jeśli jest jakiś rekord danego typu
|
|
{int *r=new int[iLast+1]; //robocza tablica indeksów - numery posortowanych rekordów
|
|
int *q=r; //wskaźnik roboczy, przekazywany przez referencję
|
|
rTypes[t]->ListGet(rRecords,q); //drzewo jest już posortowane - zamienić je na listę
|
|
rTypes[t]=TreeSet(r,0,(q-r)-1);
|
|
delete[] r;
|
|
}
|
|
return;
|
|
};
|
|
|
|
ItemRecord* __fastcall TNames::FindRecord(const int t,const char *n)
|
|
{//poszukiwanie rekordu w celu np. zmiany wskaźnika
|
|
return rTypes[t]?rTypes[t]->TreeFindRecord(n):NULL;
|
|
};
|
|
|