/* Copyright (c) 2002-2012 Croteam Ltd. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 240 %{ #include "StdH.h" #include "EntitiesMP/WorldSettingsController.h" #include "EntitiesMP/BackgroundViewer.h" %} %{ #define CTA_LEFT 1 #define CTA_RIGHT 2 #define CTA_CENTER 3 class CCreditEntry { public: CTString strTitle; CTString strName; CTString strQuote; INDEX iAlign; INDEX iX, iY; FLOAT fRelSize; FLOAT fWait; }; static CStaticStackArray _acceEntries; #define BLANK_TIME 1.0f %} class CCreditsHolder: CRationalEntity { name "CreditsHolder"; thumbnail "Thumbnails\\ScrollHolder.tbn"; features "IsTargetable", "HasName", "IsImportant"; properties: 1 CTString m_strName "Name" 'N' = "Credits holder", 2 CTString m_strDescription = "", 3 CTFileName m_fnmMessage "Scroll Text" 'T' = CTString(""), 4 FLOAT m_fMyTimer = 0.0f, // time when started 6 FLOAT m_fMyTimerLast = 0.0f, 5 FLOAT m_iTotalEntries = 0, 10 BOOL m_bEnd = FALSE, // set to TRUE to end 15 CEntityPointer m_penEndCreditsTrigger "EndCredits trigger", 20 BOOL m_bDataError = FALSE, { BOOL bDataLoaded; CFontData _fdMedium; } components: 1 model MODEL_HOLDER "Models\\Editor\\MessageHolder.mdl", 2 texture TEXTURE_HOLDER "Models\\Editor\\MessageHolder.tex" functions: const CTString &GetDescription(void) const { ((CTString&)m_strDescription).PrintF("%s", m_fnmMessage.FileName()); return m_strDescription; } void CCreditsHolder(void) { bDataLoaded = FALSE; } BOOL ReloadData(void) { m_bDataError = FALSE; if (!Credits_On(m_fnmMessage)) { Credits_Off(); return FALSE; } if(!LoadFont()) { Credits_Off(); return FALSE; } return TRUE; } BOOL LoadOneFile(const CTFileName &fnm) { if(fnm=="") { return FALSE; } try { // open the file CTFileStream strm; strm.Open_t(fnm); CTString strCheck; strm.GetLine_t(strCheck); strCheck.TrimSpacesRight(); if (strCheck!="CREDITS") { return FALSE; }; m_iTotalEntries = 0; while(!strm.AtEOF()) { CTString strLine; CTString strArgs; CTString strTmp; CCreditEntry cceEntry; strm.GetLine_t(strLine); strm.GetLine_t(strLine); strLine.TrimSpacesRight(); if (strLine=="END") { strm.Close(); return TRUE; } else if (strLine!="ENTRY") { _acceEntries.PopAll(); return FALSE; } strm.GetLine_t(strArgs); strArgs.ScanF("%d,%d", &cceEntry.iX, &cceEntry.iY); strm.GetLine_t(strArgs); strArgs.ScanF("%f", &cceEntry.fRelSize); strm.GetLine_t(strArgs); strArgs.TrimSpacesRight(); if (strArgs=="CENTER") { cceEntry.iAlign = CTA_CENTER; } else if (strArgs=="RIGHT") { cceEntry.iAlign = CTA_RIGHT; } else if (TRUE) { cceEntry.iAlign = CTA_LEFT; } strm.GetLine_t(cceEntry.strTitle); strm.GetLine_t(cceEntry.strName); strm.GetLine_t(cceEntry.strQuote); strm.GetLine_t(strArgs); strArgs.ScanF("%f", &cceEntry.fWait); _acceEntries.Push() = cceEntry; m_iTotalEntries ++; } strm.Close(); return TRUE; } catch (char *strError) { CPrintF("%s\n", strError); return FALSE; } } BOOL LoadFont() { try { _fdMedium.Load_t( CTFILENAME( "Fonts\\Display3-normal.fnt")); } catch (char *strError) { CPrintF("%s\n", strError); return FALSE; } return TRUE; } // turn credits on BOOL Credits_On(CTFileName fnCreditsText) { _acceEntries.PopAll(); return LoadOneFile(fnCreditsText); } // turn credits off void Credits_Off(void) { _acceEntries.Clear(); } // render credits to given drawport FLOAT Credits_Render(CCreditsHolder *penThis, CDrawPort *pdp) { if (m_bDataError) { return 0; } if (!bDataLoaded) { if (!ReloadData()) { m_bDataError = TRUE; return 0; } bDataLoaded = TRUE; return 1; } PIX pixW = 0; PIX pixH = 0; //FLOAT fResolutionScaling; CTString strEmpty; FLOAT fTime = Lerp(m_fMyTimerLast, m_fMyTimer, _pTimer->GetLerpFactor()); CDrawPort *pdpCurr=pdp; pdp->Unlock(); pdpCurr->Lock(); pixW = pdpCurr->GetWidth(); pixH = pdpCurr->GetHeight(); FLOAT fResFactor = pixH/480.0f; //fResolutionScaling = (FLOAT)pixH / 360.0f; pdpCurr->SetFont( _pfdDisplayFont); //PIX pixLineHeight = floor(20*fResolutionScaling); BOOL bOver = FALSE; FLOAT fPassed = 0.0f; FLOAT fStart = 0.0f; INDEX iNextItem = 0; // go to active items for (INDEX i = 0; i<_acceEntries.Count(); i++) { if (_acceEntries[i].fWait!=0.0f) { fPassed += _acceEntries[i].fWait; if (fPassed>fTime) { break; } else { iNextItem = i+1; fStart = fPassed; if (iNextItem>=_acceEntries.Count()) { bOver = TRUE; } } } } //CPrintF("start:%f, passed:%f, time:%f\n", fStart, fPassed, fTime); if (!bOver) { while (TRUE) { BOOL bLast = FALSE; if (_acceEntries[iNextItem].fWait!=0.0f) { bLast = TRUE; }; FLOAT fFade = CalculateRatio(fTime, fStart, fPassed-BLANK_TIME, 0.2f, 0.2f); pdp->SetFont( _pfdDisplayFont); pdp->SetTextAspect( 1.0f); FLOAT fTextSize01 = 1.2f*_acceEntries[iNextItem].fRelSize; FLOAT fTextSize02 = 2.0f*_acceEntries[iNextItem].fRelSize; FLOAT fTextSize03 = 0.75f*_acceEntries[iNextItem].fRelSize; FLOAT fTextHeight = 15.0f; FLOAT fSpacing01 = 1.2f; FLOAT fSpacing02 = 1.1f; if (_acceEntries[iNextItem].iAlign == CTA_CENTER) { FLOAT fYY = _acceEntries[iNextItem].iY*fResFactor; pdp->SetTextScaling(fTextSize01*fResFactor); pdp->PutTextC( _acceEntries[iNextItem].strTitle, _acceEntries[iNextItem].iX*fResFactor, fYY, C_WHITE|(INDEX)(fFade*255)); fYY += fTextSize01*fResFactor*fTextHeight*fSpacing01; pdp->SetFont( &_fdMedium); pdp->SetTextScaling(fTextSize02*fResFactor); pdp->PutTextC( _acceEntries[iNextItem].strName, _acceEntries[iNextItem].iX*fResFactor, fYY, C_WHITE|(INDEX)(fFade*255)); fYY += fTextSize02*fResFactor*fTextHeight*fSpacing02; pdp->SetTextScaling(fTextSize03*fResFactor); pdp->PutTextC( _acceEntries[iNextItem].strQuote, _acceEntries[iNextItem].iX*fResFactor, fYY, C_WHITE|(INDEX)(fFade*255)); } else if (_acceEntries[iNextItem].iAlign == CTA_RIGHT) { FLOAT fYY = _acceEntries[iNextItem].iY*fResFactor; pdp->SetTextScaling(fTextSize01*fResFactor); pdp->PutTextR( _acceEntries[iNextItem].strTitle, _acceEntries[iNextItem].iX*fResFactor, fYY, C_WHITE|(INDEX)(fFade*255)); fYY += fTextSize01*fResFactor*fTextHeight*fSpacing01; pdp->SetTextScaling(fTextSize02*fResFactor); pdp->PutTextR( _acceEntries[iNextItem].strName, _acceEntries[iNextItem].iX*fResFactor, fYY, C_WHITE|(INDEX)(fFade*255)); fYY += fTextSize02*fResFactor*fTextHeight*fSpacing02; pdp->SetTextScaling(fTextSize03*fResFactor); pdp->PutTextR( _acceEntries[iNextItem].strQuote, _acceEntries[iNextItem].iX*fResFactor, fYY, C_WHITE|(INDEX)(fFade*255)); } else if (TRUE) { FLOAT fYY = _acceEntries[iNextItem].iY*fResFactor; pdp->SetTextScaling(fTextSize01*fResFactor); pdp->PutText( _acceEntries[iNextItem].strTitle, _acceEntries[iNextItem].iX*fResFactor, fYY, C_WHITE|(INDEX)(fFade*255)); fYY += fTextSize01*fResFactor*fTextHeight*fSpacing01; pdp->SetTextScaling(fTextSize02*fResFactor); pdp->PutText( _acceEntries[iNextItem].strName, _acceEntries[iNextItem].iX*fResFactor, fYY, C_WHITE|(INDEX)(fFade*255)); fYY += fTextSize02*fResFactor*fTextHeight*fSpacing02; pdp->SetTextScaling(fTextSize03*fResFactor); pdp->PutText( _acceEntries[iNextItem].strQuote, _acceEntries[iNextItem].iX*fResFactor, fYY, C_WHITE|(INDEX)(fFade*255)); } iNextItem++; if (iNextItem>=_acceEntries.Count() || bLast) { bOver = TRUE; break; } } } pdpCurr->Unlock(); pdp->Lock(); if (bOver) { return 0; } else { return 1; } } procedures: WaitScrollingToEnd() { while (!m_bEnd) { autowait(_pTimer->TickQuantum); m_fMyTimerLast = m_fMyTimer; m_fMyTimer+=_pTimer->TickQuantum/_pNetwork->GetRealTimeFactor(); } return EStop(); } Main() { InitAsEditorModel(); SetPhysicsFlags(EPF_MODEL_IMMATERIAL); SetCollisionFlags(ECF_IMMATERIAL); // set appearance SetModel(MODEL_HOLDER); SetModelMainTexture(TEXTURE_HOLDER); autowait(0.05f); if( !Credits_On(m_fnmMessage)) { CPrintF("Error loading credits file '%s'!\n", m_fnmMessage); Credits_Off(); return; } m_bDataError = FALSE; wait() { on (EStart eStart): { CWorldSettingsController *pwsc = GetWSC(this); if( pwsc!=NULL) { m_fMyTimer = 0; m_fMyTimerLast = 0; ECredits ecr; ecr.bStart=TRUE; ecr.penSender=this; pwsc->SendEvent(ecr); } call WaitScrollingToEnd(); } on (EStop eStop): { CWorldSettingsController *pwsc = GetWSC(this); if( pwsc!=NULL) { ECredits ecr; ecr.bStart=FALSE; ecr.penSender=this; pwsc->SendEvent(ecr); } stop; } } Credits_Off(); if (m_penEndCreditsTrigger) { SendToTarget(m_penEndCreditsTrigger, EET_TRIGGER, FixupCausedToPlayer(this, NULL, FALSE)); } return; } };