diff --git a/DynObj.cpp b/DynObj.cpp index a6f95689..9dba3343 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -4633,8 +4633,13 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, */ if( true == pAnimations.empty() ) { // Ra: tworzenie tabeli animacji, jeśli jeszcze nie było - if (!iAnimations) // jeśli nie podano jawnie, ile ma być animacji +/* + // disabled as default animation amounts are no longer supported + if( !iAnimations ) { + // jeśli nie podano jawnie, ile ma być animacji iAnimations = 28; // tyle było kiedyś w każdym pojeździe (2 wiązary wypadły) + } +*/ /* //pojazd może mieć pantograf do innych celów niż napęd if (MoverParameters->EnginePowerSource.SourceType!=CurrentCollector) {//nie będzie pantografów, to się trochę uprości @@ -5463,6 +5468,11 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, } while( ( token != "" ) && ( false == Stop_InternalData ) ); + if( !iAnimations ) { + // if the animations weren't defined the model is likely to be non-functional. warrants a warning. + ErrorLog( "Animations tag is missing from the .mmd file \"" + asFileName + "\"" ); + } + if (mdModel) mdModel->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie // binarnego diff --git a/DynObj.h b/DynObj.h index 56f31d02..bda873a7 100644 --- a/DynObj.h +++ b/DynObj.h @@ -185,7 +185,7 @@ private: private: // zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe public: // tymczasowo udostępnione do wyszukiwania drutu - int iAnimType[ANIM_TYPES]; // 0-osie,1-drzwi,2-obracane,3-zderzaki,4-wózki,5-pantografy,6-tłoki + int iAnimType[ ANIM_TYPES ]; // 0-osie,1-drzwi,2-obracane,3-zderzaki,4-wózki,5-pantografy,6-tłoki private: int iAnimations; // liczba obiektów animujących /* diff --git a/Event.cpp b/Event.cpp index 5ea1ddf5..de274e49 100644 --- a/Event.cpp +++ b/Event.cpp @@ -317,6 +317,7 @@ void TEvent::Load(cParser *parser, vector3 *org) { if (token.find('#') != std::string::npos) token.erase(token.find('#')); // obcięcie unikatowości + win1250_to_ascii( token ); // get rid of non-ascii chars bEnabled = false; // nie do kolejki (dla SetVelocity też, ale jak jest do toru // dowiązany) Params[6].asCommand = cm_PassengerStopPoint; diff --git a/Globals.cpp b/Globals.cpp index 1780eee5..348fa827 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -74,7 +74,9 @@ int Global::iSegmentsRendered = 90; // ilość segmentów do regulacji wydajnoś TCamera *Global::pCamera = NULL; // parametry kamery TDynamicObject *Global::pUserDynamic = NULL; // pojazd użytkownika, renderowany bez trzęsienia bool Global::bSmudge = false; // czy wyświetlać smugę, a pojazd użytkownika na końcu +/* std::string Global::asTranscript[5]; // napisy na ekranie (widoczne) +*/ TTranscripts Global::tranTexts; // obiekt obsługujący stenogramy dźwięków na ekranie // parametry scenerii @@ -1130,6 +1132,7 @@ bool Global::DoEvents() TTranscripts::TTranscripts() { +/* iCount = 0; // brak linijek do wyświetlenia iStart = 0; // wypełniać od linijki 0 for (int i = 0; i < MAX_TRANSCRIPTS; ++i) @@ -1137,19 +1140,35 @@ TTranscripts::TTranscripts() aLines[i].fHide = -1.0; // wolna pozycja (czas symulacji, 360.0 to doba) aLines[i].iNext = -1; // nie ma kolejnej } +*/ fRefreshTime = 360.0; // wartośc zaporowa }; TTranscripts::~TTranscripts(){}; -void TTranscripts::AddLine(char const *txt, float show, float hide, bool it) + +void TTranscripts::AddLine(std::string const &txt, float show, float hide, bool it) { // dodanie linii do tabeli, (show) i (hide) w [s] od aktualnego czasu if (show == hide) return; // komentarz jest ignorowany show = Global::fTimeAngleDeg + show / 240.0; // jeśli doba to 360, to 1s będzie równe 1/240 hide = Global::fTimeAngleDeg + hide / 240.0; + + TTranscript transcript; + transcript.asText = txt; + transcript.fShow = show; + transcript.fHide = hide; + transcript.bItalic = it; + aLines.emplace_back( transcript ); + // set the next refresh time while at it + // TODO, TBD: sort the transcript lines? in theory, they should be coming arranged in the right order anyway + // short of cases with multiple sounds overleaping + fRefreshTime = aLines.front().fHide; +/* int i = iStart, j, k; // od czegoś trzeba zacząć while ((aLines[i].iNext >= 0) ? (aLines[aLines[i].iNext].fShow <= show) : false) // póki nie koniec i wcześniej puszczane i = aLines[i].iNext; // przejście do kolejnej linijki +*/ +/* //(i) wskazuje na linię, po której należy wstawić dany tekst, chyba że while (txt ? *txt : false) for (j = 0; j < MAX_TRANSCRIPTS; ++j) @@ -1176,11 +1195,13 @@ void TTranscripts::AddLine(char const *txt, float show, float hide, bool it) fRefreshTime = show; // to odświeżyć wcześniej break; // więcej już nic } +*/ }; -void TTranscripts::Add(char const *txt, float len, bool backgorund) +void TTranscripts::Add(std::string const &txt, float len, bool backgorund) { // dodanie tekstów, długość dźwięku, czy istotne - if (!txt) + if (true == txt.empty()) return; // pusty tekst +/* int i = 0, j = int(0.5 + 10.0 * len); //[0.1s] if (*txt == '[') { // powinny być dwa nawiasy @@ -1197,14 +1218,44 @@ void TTranscripts::Add(char const *txt, float len, bool backgorund) ++txt; // pominięcie drugiego ] } } - AddLine(txt, 0.1 * i, 0.1 * j, false); +*/ + std::string asciitext{ txt }; win1250_to_ascii( asciitext ); // TODO: launch relevant conversion table based on language + cParser parser( asciitext ); + while( true == parser.getTokens( 3, false, "[]\n" ) ) { + + float begin, end; + std::string transcript; + parser + >> begin + >> end + >> transcript; + AddLine( transcript, 0.10 * begin, 0.12 * end, false ); + } + // try to handle malformed(?) cases with no show/hide times + std::string transcript; parser >> transcript; + while( false == transcript.empty() ) { + + WriteLog( "Transcript text with no display/hide times: \"" + transcript + "\"" ); + AddLine( transcript, 0.0, 0.12 * transcript.size(), false ); + transcript = ""; parser >> transcript; + } }; void TTranscripts::Update() { // usuwanie niepotrzebnych (nie częściej niż 10 razy na sekundę) - if (fRefreshTime > Global::fTimeAngleDeg) + if( Global::fTimeAngleDeg < fRefreshTime ) return; // nie czas jeszcze na zmiany // czas odświeżenia można ustalić wg tabelki, kiedy coś się w niej zmienia - fRefreshTime = Global::fTimeAngleDeg + 360.0; // wartość zaporowa + // fRefreshTime = Global::fTimeAngleDeg + 360.0; // wartość zaporowa + + while( ( false == aLines.empty() ) + && ( Global::fTimeAngleDeg >= aLines.front().fHide ) ) { + // remove expired lines + aLines.pop_front(); + } + // update next refresh time + if( false == aLines.empty() ) { fRefreshTime = aLines.front().fHide; } + else { fRefreshTime = 360.0f; } +/* int i = iStart, j = -1; // od czegoś trzeba zacząć bool change = false; // czy zmieniać napisy? do @@ -1247,6 +1298,7 @@ void TTranscripts::Update() for (++j; j < 5; ++j) Global::asTranscript[j] = ""; // i czyszczenie nieużywanych linijek } +*/ }; // Ra: tymczasowe rozwiązanie kwestii zagranicznych (czeskich) napisów diff --git a/Globals.h b/Globals.h index c50f5d83..2793ed30 100644 --- a/Globals.h +++ b/Globals.h @@ -130,21 +130,31 @@ class TTranscript int iNext; // następna używana linijka, żeby nie przestawiać fizycznie tabeli }; +/* #define MAX_TRANSCRIPTS 30 +*/ class TTranscripts { // klasa obsługująca napisy do dźwięków +/* TTranscript aLines[MAX_TRANSCRIPTS]; // pozycje na napisy do wyświetlenia +*/ +public: + std::deque aLines; +/* int iCount; // liczba zajętych pozycji int iStart; // pierwsza istotna pozycja w tabeli, żeby sortować przestawiając numerki +*/ +private: float fRefreshTime; public: TTranscripts(); ~TTranscripts(); - void AddLine(char const *txt, float show, float hide, bool it); - void Add(char const *txt, float len, - bool backgorund = false); // dodanie tekstów, długość dźwięku, czy istotne - void Update(); // usuwanie niepotrzebnych (ok. 10 razy na sekundę) + void AddLine(std::string const &txt, float show, float hide, bool it); + // dodanie tekstów, długość dźwięku, czy istotne + void Add(std::string const &txt, float len, bool background = false); + // usuwanie niepotrzebnych (ok. 10 razy na sekundę) + void Update(); }; class Global @@ -298,7 +308,9 @@ class Global static double fBrakeStep; // krok zmiany hamulca dla klawiszy [Num3] i [Num9] static bool bJoinEvents; // czy grupować eventy o tych samych nazwach static bool bSmudge; // czy wyświetlać smugę, a pojazd użytkownika na końcu +/* static std::string asTranscript[5]; // napisy na ekranie (widoczne) +*/ static TTranscripts tranTexts; // obiekt obsługujący stenogramy dźwięków na ekranie static std::string asLang; // domyślny język - http://tools.ietf.org/html/bcp47 static int iHiddenEvents; // czy łączyć eventy z torami poprzez nazwę toru diff --git a/McZapkie/mctools.cpp b/McZapkie/mctools.cpp index fe17d484..2c751394 100644 --- a/McZapkie/mctools.cpp +++ b/McZapkie/mctools.cpp @@ -412,6 +412,21 @@ std::string ToUpper(std::string const &text) return uppercase; } +// replaces polish letters with basic ascii +void +win1250_to_ascii( std::string &Input ) { + + std::unordered_map charmap{ + { 165, 'A' }, { 198, 'C' }, { 202, 'E' }, { 163, 'L' }, { 209, 'N' }, { 211, 'O' }, { 140, 'S' }, { 143, 'Z' }, { 175, 'Z' }, + { 185, 'a' }, { 230, 'c' }, { 234, 'e' }, { 179, 'l' }, { 241, 'n' }, { 243, 'o' }, { 156, 's' }, { 159, 'z' }, { 191, 'z' } + }; + std::unordered_map::const_iterator lookup; + for( auto &input : Input ) { + if( ( lookup = charmap.find( input ) ) != charmap.end() ) + input = lookup->second; + } +} + void ComputeArc(double X0, double Y0, double Xn, double Yn, double R, double L, double dL, double &phi, double &Xout, double &Yout) /*wylicza polozenie Xout Yout i orientacje phi punktu na elemencie dL luku*/ diff --git a/McZapkie/mctools.h b/McZapkie/mctools.h index a38abb27..817f34ec 100644 --- a/McZapkie/mctools.h +++ b/McZapkie/mctools.h @@ -107,15 +107,15 @@ bool FuzzyLogicAI(double Test, double Threshold, double Probability); /*operacje na stringach*/ std::string ReadWord( std::ifstream& infile); /*czyta slowo z wiersza pliku tekstowego*/ //std::string Ups(std::string s); -std::string TrimSpace(std::string &s); -char* TrimAndReduceSpaces(const char* s); -std::string ExtractKeyWord(std::string InS, std::string KeyWord); /*wyciaga slowo kluczowe i lancuch do pierwszej spacji*/ +//std::string TrimSpace(std::string &s); +//char* TrimAndReduceSpaces(const char* s); +//std::string ExtractKeyWord(std::string InS, std::string KeyWord); /*wyciaga slowo kluczowe i lancuch do pierwszej spacji*/ std::string DUE(std::string s); /*Delete Until Equal sign*/ std::string DWE(std::string s); /*Delete While Equal sign*/ std::string ExchangeCharInString(std::string const &s, const char &aim, const char &target); // zamienia jeden znak na drugi std::vector &Split(const std::string &s, char delim, std::vector &elems); std::vector Split(const std::string &s, char delim); -std::vector Split(const std::string &s); +//std::vector Split(const std::string &s); std::string to_string(int _Val); std::string to_string(unsigned int _Val); @@ -125,6 +125,7 @@ std::string to_string(double _Val); std::string to_string(double _Val, int precision); std::string to_string(double _Val, int precision, int width); std::string to_hex_str( int const _Val, int const width = 4 ); + inline std::string to_string(bool _Val) { return _Val == true ? "true" : "false"; @@ -135,6 +136,9 @@ int stol_def(const std::string & str, const int & DefaultValue); std::string ToLower(std::string const &text); std::string ToUpper(std::string const &text); +// replaces polish letters with basic ascii +void win1250_to_ascii( std::string &Input ); + /*procedury, zmienne i funkcje graficzne*/ void ComputeArc(double X0, double Y0, double Xn, double Yn, double R, double L, double dL, double & phi, double & Xout, double & Yout); /*wylicza polozenie Xout Yout i orientacje phi punktu na elemencie dL luku*/ diff --git a/RealSound.cpp b/RealSound.cpp index 42aa71a5..17cd51f3 100644 --- a/RealSound.cpp +++ b/RealSound.cpp @@ -271,22 +271,25 @@ void TTextSound::Play(double Volume, int Looping, bool ListenerInside, vector3 N pSound->GetStatus(&stat); if (!(stat & DSBSTATUS_PLAYING)) // jeśli nie jest aktualnie odgrywany { +/* std::string t( asText ); size_t i; do { // na razie zrobione jakkolwiek, docelowo przenieść teksty do tablicy nazw i = t.find('\r'); // znak nowej linii if( i == std::string::npos ) { - Global::tranTexts.Add( t.c_str(), fTime, true ); + Global::tranTexts.Add( t, fTime, true ); } else { - Global::tranTexts.Add(t.substr(0, i).c_str(), fTime, true); + Global::tranTexts.Add(t.substr(0, i), fTime, true); t.erase(0, i + 1); while (t.empty() ? false : (unsigned char)(t[1]) < 33) t.erase(0, 1); } } while (i != std::string::npos); +*/ + Global::tranTexts.Add( asText, fTime, true ); } } TRealSound::Play(Volume, Looping, ListenerInside, NewPosition); diff --git a/Texture.cpp b/Texture.cpp index 9e509d20..fb9a4dd0 100644 --- a/Texture.cpp +++ b/Texture.cpp @@ -175,7 +175,7 @@ opengl_texture::load_DDS() { data_width = ddsd.dwWidth; data_height = ddsd.dwHeight; - data_mapcount = 1;// ddsd.dwMipMapCount; + data_mapcount = ddsd.dwMipMapCount; int blockSize = ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? 8 : 16 ); int offset = 0; @@ -194,11 +194,13 @@ opengl_texture::load_DDS() { data_state = resource_state::failed; return; } + + int datasize = filesize - offset; /* // this approach loads only the first mipmap and relies on graphics card to fill the rest + data_mapcount = 1; int datasize = ( ( data_width + 3 ) / 4 ) * ( ( data_height + 3 ) / 4 ) * blockSize; */ - int datasize = filesize - offset; /* // calculate size of accepted data // NOTE: this is a fallback, as we should be able to just move the file caret by calculated offset and read the rest @@ -331,7 +333,8 @@ opengl_texture::load_TGA() { int const pixelcount = data_width * data_height; for( int i = 0; i < pixelcount; ++i ) { - file.read( (char *)buffer, sizeof( unsigned char ) ); + + file.read( (char *)&buffer[ 0 ], sizeof( unsigned char ) * bytesperpixel ); if( bytesperpixel == 1 ) { // expand greyscale data buffer[ 1 ] = buffer[ 0 ]; @@ -473,8 +476,8 @@ opengl_texture::create() { datasize, (GLubyte *)&data[0] + dataoffset ); dataoffset += datasize; - datawidth = std::max( datawidth / 2, 4 ); - dataheight = std::max( dataheight / 2, 4 ); + datawidth = std::max( datawidth / 2, 1 ); + dataheight = std::max( dataheight / 2, 1 ); } else{ // uncompressed texture data diff --git a/World.cpp b/World.cpp index 56e70d25..c0188625 100644 --- a/World.cpp +++ b/World.cpp @@ -2611,6 +2611,7 @@ TWorld::Render_UI() { } // if ((Global::iTextMode!=VK_F3)) { // stenogramy dźwięków (ukryć, gdy tabelka skanowania lub rozkład?) +/* glColor3f( 1.0f, 1.0f, 0.0f ); //żółte for( int i = 0; i < 5; ++i ) { // kilka linijek if( Global::asTranscript[ i ].empty() ) @@ -2620,6 +2621,23 @@ TWorld::Render_UI() { glPrint( Global::Bezogonkow( Global::asTranscript[ i ] ).c_str() ); } } +*/ + int i = 0; + for( auto const &transcript : Global::tranTexts.aLines ) { + + if( Global::fTimeAngleDeg >= transcript.fShow ) { + + cParser parser( transcript.asText ); + while( true == parser.getTokens(1, false, "|") ) { + + std::string transcriptline; parser >> transcriptline; + ::glColor3f( 1.0f, 1.0f, 0.0f ); //żółte + ::glRasterPos2f( -0.20f, -0.05f - 0.01f * i ); + glPrint( transcriptline.c_str() ); + ++i; + } + } + } } } // if (Global::iViewMode!=Global::iTextMode) diff --git a/mtable.cpp b/mtable.cpp index 680f6cc6..877271b8 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/. #include "stdafx.h" #include "mtable.h" +#include "mczapkie/mctools.h" // using namespace Mtable; std::shared_ptr Mtable::GlobalTime; @@ -278,8 +279,10 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) if (s != "|") break; } // while (!(() || fin.eof())); - if (s != "|") + if( s != "|" ) { Relation1 = s; + win1250_to_ascii( Relation1 ); + } else ConversionError = -5; while (fin >> s || !fin.bad()) @@ -294,6 +297,7 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) break; } // while (!( || (fin.eof()))); fin >> Relation2; + win1250_to_ascii( Relation2 ); while (fin >> s || !fin.bad()) { if (s == "Wymagany") @@ -352,6 +356,8 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) while (s.find("|") == std::string::npos) fin >> s; fin >> record->StationName; + // get rid of non-ascii chars. TODO: run correct version based on locale + win1250_to_ascii( record->StationName ); do { fin >> s;