void CGame::ComputerMouseMove(PIX pixX, PIX pixY) { _vpixMouse(1) += pixX-_vpixExternMouse(1); _vpixMouse(2) += pixY-_vpixExternMouse(2); _vpixExternMouse(1) = pixX; _vpixExternMouse(2) = pixY; // if dragging if (_pixSliderDragJ>=0) { PIX pixDelta = _vpixMouse(2)-_pixSliderDragJ; if (_bSliderDragText) { if (_iActiveMessage<_acmMessages.Count()) { INDEX ctTextLines = _acmMessages[_iActiveMessage].cm_ctFormattedLines; INDEX iWantedLine = _iSliderDragLine+ SliderPixToIndex(pixDelta, _ctTextLinesOnScreen, ctTextLines, GetTextSliderSpace()); MessageTextUpDn(iWantedLine-_iTextLineOnScreen); } } else { INDEX ctLines = _acmMessages.Count(); INDEX iWantedLine = _iSliderDragLine+ SliderPixToIndex(pixDelta, _ctMessagesOnScreen, ctLines, GetMsgSliderSpace()); MessagesUpDn(iWantedLine-_iFirstMessageOnScreen); } } }
// Get empty texcoords array for modifying GFXTexCoord *shaGetNewTexCoordArray(void) { ASSERT(_ctVertices!=0); _uvUVMapForModify.PopAll(); _uvUVMapForModify.Push(_ctVertices); return &_uvUVMapForModify[0]; }
// make array of entity offsets in a block void MakeInfos(CStaticStackArray<EntityBlockInfo> &aebi, UBYTE *pubBlock, SLONG slSize, UBYTE *pubFirst, UBYTE *&pubEnd) { // clear all offsets aebi.PopAll(); // until end of block UBYTE *pub = pubFirst; while (pub<pubBlock+slSize) { // if no more entities if (*(ULONG*)pub != ENT4) { pubEnd = pub; // stop return; } // remember it EntityBlockInfo &ebi = aebi.Push(); ebi.ebi_slOffset = pub-pubBlock; pub+=sizeof(ULONG); // get id and size ULONG ulID = *(ULONG*)pub; ebi.ebi_ulID = ulID; pub+=sizeof(ULONG); SLONG slSizeChunk = *(SLONG*)pub; pub+=sizeof(ULONG); ebi.ebi_slSize = slSizeChunk+sizeof(SLONG)*3; pub+=slSizeChunk; } }
// update scroll position for message list static void UpdateFirstOnScreen(void) { if (_iFirstMessageOnScreen==_iWantedFirstMessageOnScreen) { return; } _iFirstMessageOnScreen=_iWantedFirstMessageOnScreen; ASSERT( _iFirstMessageOnScreen>=0&& _iFirstMessageOnScreen<=_acmMessages.Count()); _iFirstMessageOnScreen = Clamp(_iFirstMessageOnScreen, INDEX(0), _acmMessages.Count()); // for each message for(INDEX i=0; i<_acmMessages.Count(); i++) { CCompMessage &cm = _acmMessages[i]; // if on screen if (i>=_iWantedFirstMessageOnScreen &&i<_iWantedFirstMessageOnScreen+_ctMessagesOnScreen) { // load cm.PrepareMessage(_ctTextCharsPerRow); // if not on screen } else { // unload cm.UnprepareMessage(); } } }
// update current active message category static void UpdateType(BOOL bForce=FALSE) { if (_cmtCurrentType==_cmtWantedType && !bForce) { return; } // cleare message cache _acmMessages.Clear(); // for each player's message CDynamicStackArray<CCompMessageID> &acmiMsgs = _ppenPlayer->m_acmiMessages; for(INDEX i=0; i<acmiMsgs.Count(); i++) { CCompMessageID &cmi = acmiMsgs[i]; // if it is of given type if (cmi.cmi_cmtType == _cmtWantedType) { // add it to cache CCompMessage &cm = _acmMessages.Push(); cm.SetMessage(&cmi); } } if (!bForce) { _cmtCurrentType=_cmtWantedType; _iFirstMessageOnScreen = -1; _iWantedFirstMessageOnScreen = 0; _iActiveMessage = 0; _iLastActiveMessage = -2; _iTextLineOnScreen = 0; LastUnreadMessage(); UpdateFirstOnScreen(); } }
// Get empty vertex array for modifying GFXVertex *shaGetNewVertexArray(void) { ASSERT(_ctVertices!=0); _vModifyVertices.PopAll(); _vModifyVertices.Push(_ctVertices); return &_vModifyVertices[0]; }
static void EndTris(void) { _avtx.Clear(); _atex.Clear(); _acol.Clear(); _aiElements.Clear(); }
static void BatchTile(INDEX itt) { CTerrainTile &tt = _ptrTerrain->tr_attTiles[itt]; ASSERT(tt.GetVertices().Count()==9); ASSERT(tt.GetIndices().Count()==24); INDEX ctDelayedVertices = _avDelayedVertices.Count(); GFXVertex4 *pavVertices = &tt.GetVertices()[0]; GFXTexCoord *pauvTexCoords = &tt.GetTexCoords()[0]; GFXTexCoord *pauvShadowMapTC = &tt.GetShadowMapTC()[0]; INDEX *paiIndices = &tt.GetIndices()[0]; GFXVertex4 *pavDelVertices = _avDelayedVertices.Push(9); GFXTexCoord *pauvDelTexCoords = _auvDelayedTexCoords.Push(9); GFXTexCoord *pauvDelShadowMapTC = _auvDelayedShadowMapTC.Push(9); INDEX *paiDelIndices = _aiDelayedIndices.Push(24); // for each vertex in tile for(INDEX ivx=0;ivx<9;ivx++) { // copy vertex, texcoord & shadow map texcoord to delayed array pavDelVertices[ivx] = pavVertices[ivx]; pauvDelTexCoords[ivx] = pauvTexCoords[ivx]; pauvDelShadowMapTC[ivx] = pauvShadowMapTC[ivx]; } // for each index in tile for(INDEX iind=0;iind<24;iind++) { // reindex indice for new arrays paiDelIndices[iind] = paiIndices[iind] + ctDelayedVertices; } _ctDelayedNodes++; }
// Get empty color array for modifying GFXColor *shaGetNewColorArray(void) { ASSERT(_ctVertices!=0); _acolVtxModifyColors.PopAll(); _acolVtxModifyColors.Push(_ctVertices); return &_acolVtxModifyColors[0]; }
static void InitTris(void) { INDEX iR, iC; INDEX ctVx = _ctR*_ctC; _avtx.Push(ctVx); _atex.Push(ctVx); _acol.Push(ctVx); for( iR=0; iR<_ctR; iR++) { for( iC=0; iC<_ctC; iC++) { INDEX ivx = iR*_ctC+iC; _avtx[ivx].x = FLOAT(iC) / _ctC*4 -2.0f; _avtx[ivx].y = -FLOAT(iR) / _ctR*4 +2.0f; _avtx[ivx].z = -1.0f; _atex[ivx].st.s = (iC+iR) % 2; _atex[ivx].st.t = (iR) % 2; _acol[ivx].ul.abgr = 0xFFFFFFFF; } } INDEX ctTri = (_ctR-1)*(_ctC-1)*2; _aiElements.Push(ctTri*3); for( iR=0; iR<_ctR-1; iR++) { for( iC=0; iC<_ctC-1; iC++) { INDEX iq = iR*(_ctC-1)+iC; _aiElements[iq*6+0] = (iR+1) * _ctC + (iC+0); _aiElements[iq*6+1] = (iR+1) * _ctC + (iC+1); _aiElements[iq*6+2] = (iR+0) * _ctC + (iC+0); _aiElements[iq*6+3] = (iR+0) * _ctC + (iC+0); _aiElements[iq*6+4] = (iR+1) * _ctC + (iC+1); _aiElements[iq*6+5] = (iR+0) * _ctC + (iC+1); } } }
void CCastRay::ClearSectorList(void) { // for each active sector for(INDEX ias=0; ias<_aas.Count(); ias++) { // mark it as inactive _aas[ias].as_pbsc->bsc_ulFlags&=~BSCF_RAYTESTED; } _aas.PopAll(); }
static void FillConstColorArray(INDEX ctVertices) { INDEX ctColors=_acolVtxConstColors.Count(); _acolVtxConstColors.PopAll(); _acolVtxConstColors.Push(ctVertices); // if requested array is larger then existing one if(ctVertices>ctColors) { memset(&_acolVtxConstColors[ctColors],255,(ctVertices-ctColors)*sizeof(GFXColor)); } }
void NextMessage(void) { if (_iActiveMessage<_acmMessages.Count()==0) { return; } _iActiveMessage++; if (_iActiveMessage>=_acmMessages.Count()) { _iActiveMessage = _acmMessages.Count()-1; } SyncScrollWithActive(); }
// select last unread message, or last message if all read void LastUnreadMessage(void) { BOOL bFound = FALSE; for(_iActiveMessage=_acmMessages.Count()-1; _iActiveMessage>=0; _iActiveMessage--) { if (!_acmMessages[_iActiveMessage].cm_bRead) { bFound = TRUE; break; } } if (!bFound) { _iActiveMessage = ClampDn(_acmMessages.Count()-1, 0); } SyncScrollWithActive(); }
void SelectMessage(INDEX i) { if (_acmMessages.Count()==0) { return; } _iActiveMessage = i; if (_iActiveMessage<0) { _iActiveMessage = 0; } if (_iActiveMessage>=_acmMessages.Count()) { _iActiveMessage = _acmMessages.Count()-1; } SyncScrollWithActive(); }
// check all delayed depth points extern void CheckDelayedDepthPoints( const CDrawPort *pdp, INDEX iMirrorLevel/*=0*/) { // skip if not delayed or mirror level is to high gap_iOptimizeDepthReads = Clamp( gap_iOptimizeDepthReads, 0L, 2L); if( gap_iOptimizeDepthReads==0 || iMirrorLevel>7) return; ASSERT( pdp!=NULL && iMirrorLevel>=0); // check only if time lapse allows const CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); const TIME tmDelta = (tvNow-_tvLast[iMirrorLevel]).GetSeconds(); ASSERT( tmDelta>=0); if( gap_iOptimizeDepthReads==2 && tmDelta<0.1f) return; // prepare _tvLast[iMirrorLevel] = tvNow; INDEX ctPoints = _adiDelayed.Count(); if( ctPoints==0) return; // done if no points in queue // for each point INDEX iPoint = 0; while( iPoint<ctPoints) { DepthInfo &di = _adiDelayed[iPoint]; // if the point is not active any more if( iMirrorLevel==di.di_iMirrorLevel && di.di_iSwapLastRequest<_iCheckIteration-KEEP_BEHIND) { // delete it by moving the last one on its place di = _adiDelayed[ctPoints-1]; ctPoints--; // if the point is still active } else { // go to next point iPoint++; } } // remove unused points at the end if( ctPoints==0) _adiDelayed.PopAll(); else _adiDelayed.PopUntil(ctPoints-1); // ignore stalls if( tmDelta>1.0f) return; // check and update visibility of what has left ASSERT( ctPoints == _adiDelayed.Count()); if( ctPoints>0) UpdateDepthPointsVisibility( pdp, iMirrorLevel, &_adiDelayed[0], ctPoints); // mark checking _iCheckIteration++; }
// turn credits on void Credits_On(INDEX iType) { if (_bCreditsOn) { Credits_Off(); } _astrCredits.PopAll(); if (iType==1) { _fSpeed = 1.0f; LoadOneFile(CTFILENAME("Data\\Intro.txt")); } else if (iType==2) { _fSpeed = 2.0f; LoadOneFile(CTFILENAME("Data\\Credits.txt")); LoadOneFile(CTFILENAME("Data\\Credits_End.txt")); } else { _fSpeed = 2.0f; #if _SE_DEMO || TECHTESTONLY LoadOneFile(CTFILENAME("Data\\Credits_Demo.txt")); #else LoadOneFile(CTFILENAME("Data\\Credits.txt")); #endif } // if some file was loaded if (_bCreditsOn) { // remember start time if (iType==1 || iType==2) { _bUseRealTime = FALSE; _tmStart = _pTimer->GetLerpedCurrentTick(); } else { _bUseRealTime = TRUE; _tvStart = _pTimer->GetHighPrecisionTimer(); } } }
static void LoadOneFile(const CTFileName &fnm) { try { // open the file CTFileStream strm; strm.Open_t(fnm); // count number of lines INDEX ctLines = 0; while(!strm.AtEOF()) { CTString strLine; strm.GetLine_t(strLine); ctLines++; } strm.SetPos_t(0); // allocate that much CTString *astr = _astrCredits.Push(ctLines); // load all lines for(INDEX iLine = 0; iLine<ctLines && !strm.AtEOF(); iLine++) { strm.GetLine_t(astr[iLine]); } strm.Close(); _bCreditsOn = TRUE; } catch (char *strError) { CPrintF("%s\n", strError); } }
// draw image of current message void RenderMessageImage(CDrawPort *pdp) { if (!GetSP()->sp_bCooperative) { return; } // if no message if (_acmMessages.Count()==0 || fComputerFadeValue<0.99f) { // render empty LCDRenderClouds2(); LCDScreenBox(_colBoxes); return; } CCompMessage &cm = _acmMessages[_iActiveMessage]; if (cm.cm_itImage == CCompMessage::IT_STATISTICS) { _pGame->LCDRenderCompGrid(); } LCDRenderClouds2(); LCDScreenBox(_colBoxes); // if no image if (cm.cm_itImage == CCompMessage::IT_NONE) { // do nothing return; } else if (cm.cm_itImage == CCompMessage::IT_PICTURE) { RenderMessagePicture(pdp); } else if (cm.cm_itImage == CCompMessage::IT_STATISTICS) { RenderMessageStats(pdp); } else if (cm.cm_itImage == CCompMessage::IT_MODEL) { RenderMessageModel(pdp, cm.cm_strModel); } else { ASSERT(FALSE); } }
static void ComputerOn(void) { // init button names _astrButtonTexts[CMT_INFORMATION ] = TRANS("tactical data"); _astrButtonTexts[CMT_BACKGROUND ] = TRANS("strategic data"); _astrButtonTexts[CMT_WEAPONS ] = TRANS("weapons"); _astrButtonTexts[CMT_ENEMIES ] = TRANS("enemies"); _astrButtonTexts[CMT_STATISTICS ] = TRANS("statistics"); _iFirstMessageOnScreen = -1; _iWantedFirstMessageOnScreen = 0; _iActiveMessage = 0; _cmtCurrentType = (enum CompMsgType)-1; _cmtWantedType = CMT_INFORMATION; _acmMessages.Clear(); ASSERT(_ppenPlayer!=NULL); if (_ppenPlayer==NULL) { return; } // fill in player statistics _ppenPlayer->GetStats(_strStatsDetails, CST_DETAIL, _ctTextCharsPerRow); // if end of level if (_ppenPlayer!=NULL && _ppenPlayer->m_bEndOfLevel || _pNetwork->IsGameFinished()) { // select statistics _cmtWantedType = CMT_STATISTICS; // if not end of level } else { // find group with some unread messages FindGroupWithUnread(); } }
// Calculate lightning for given model void shaCalculateLightForSpecular(void) { ASSERT(_paNormals!=NULL); _acolVtxColors.PopAll(); _acolVtxColors.Push(_ctVertices); GFXColor colModel = (GFXColor)_colModel; // Model color GFXColor &colAmbient = (GFXColor)_colAmbient; // Ambient color GFXColor &colLight = (GFXColor)_colLight; // Light color GFXColor &colSurface = (GFXColor)_colConstant; // shader color // colModel = MulColors(colModel.r,colSurface.abgr); colModel.MultiplyRGBA(colModel,colSurface); UBYTE ubColShift = 8; SLONG slar = colAmbient.r; SLONG slag = colAmbient.g; SLONG slab = colAmbient.b; if(shaOverBrightningEnabled()) { slar = ClampUp(slar,127L); slag = ClampUp(slag,127L); slab = ClampUp(slab,127L); ubColShift = 8; } else { slar*=2; slag*=2; slab*=2; ubColShift = 7; } // for each vertex color for(INDEX ivx=0;ivx<_ctVertices;ivx++) { // calculate vertex light FLOAT3D &vNorm = FLOAT3D(_paNormals[ivx].nx,_paNormals[ivx].ny,_paNormals[ivx].nz); FLOAT fDot = vNorm % _vLightDir; fDot = Clamp(fDot,0.0f,1.0f); SLONG slDot = NormFloatToByte(fDot); _acolVtxColors[ivx].r = ClampUp(colModel.r * (slar + ((colLight.r * slDot)>>ubColShift))>>8,255L); _acolVtxColors[ivx].g = ClampUp(colModel.g * (slag + ((colLight.g * slDot)>>ubColShift))>>8,255L); _acolVtxColors[ivx].b = ClampUp(colModel.b * (slab + ((colLight.b * slDot)>>ubColShift))>>8,255L); _acolVtxColors[ivx].a = slDot;//colModel.a;//slDot; } // Set current wertex array _pcolVtxColors = &_acolVtxColors[0]; }
// check point against depth buffer extern BOOL CheckDepthPoint( const CDrawPort *pdp, PIX pixI, PIX pixJ, FLOAT f**K, INDEX iID, INDEX iMirrorLevel/*=0*/) { // no raster? const CRaster *pra = pdp->dp_Raster; if( pra==NULL) return FALSE; // almoust out of raster? pixI += pdp->dp_MinI; pixJ += pdp->dp_MinJ; if( pixI<1 || pixJ<1 || pixI>pra->ra_Width-2 || pixJ>pra->ra_Height-2) return FALSE; // if shouldn't delay if( gap_iOptimizeDepthReads==0) { // just check immediately DepthInfo di = { iID, pixI, pixJ, f**K, _iCheckIteration, iMirrorLevel, FALSE }; UpdateDepthPointsVisibility( pdp, iMirrorLevel, &di, 1); return di.di_bVisible; } // for each stored point for( INDEX idi=0; idi<_adiDelayed.Count(); idi++) { DepthInfo &di = _adiDelayed[idi]; // if same id if( di.di_iID == iID) { // remember parameters di.di_pixI = pixI; di.di_pixJ = pixJ; di.di_fOoK = f**K; di.di_iSwapLastRequest = _iCheckIteration; // return visibility return di.di_bVisible; } } // if not found... // create new one DepthInfo &di = _adiDelayed.Push(); // remember parameters di.di_iID = iID; di.di_pixI = pixI; di.di_pixJ = pixJ; di.di_fOoK = f**K; di.di_iSwapLastRequest = _iCheckIteration; di.di_iMirrorLevel = iMirrorLevel; di.di_bVisible = FALSE; // not visible by default return FALSE; }
static PIXaabbox2D GetMsgSliderBox(void) { INDEX ctLines = _acmMessages.Count(); PIX pixSizeI = _boxMsgList.Size()(1); PIX pixSizeJ = _boxMsgList.Size()(2); return GetSliderBox( _iFirstMessageOnScreen, _ctMessagesOnScreen, ctLines, GetMsgSliderSpace()); }
// turn credits off void Credits_Off(void) { if (!_bCreditsOn) { return; } _bCreditsOn = FALSE; _astrCredits.Clear(); }
void MessagesUpDn(INDEX ctLines) { INDEX ctMessages = _acmMessages.Count(); _iWantedFirstMessageOnScreen += ctLines; INDEX iMaxFirst = ClampDn(0L, ctMessages-_ctMessagesOnScreen); _iWantedFirstMessageOnScreen = Clamp(_iWantedFirstMessageOnScreen, 0L, iMaxFirst); _iActiveMessage = Clamp(_iActiveMessage, _iWantedFirstMessageOnScreen, _iWantedFirstMessageOnScreen+_ctMessagesOnScreen-1L); }
static PIXaabbox2D GetTextSliderBox(void) { if (_iActiveMessage>=_acmMessages.Count()) { return PIXaabbox2D(); } INDEX ctTextLines = _acmMessages[_iActiveMessage].cm_ctFormattedLines; PIX pixSizeI = _boxMsgText.Size()(1); PIX pixSizeJ = _boxMsgText.Size()(2); return GetSliderBox( _iTextLineOnScreen, _ctTextLinesOnScreen, ctTextLines, GetTextSliderSpace()); }
// go to next/previous message void PrevMessage(void) { if (_iActiveMessage<_acmMessages.Count()==0) { return; } _iActiveMessage--; if (_iActiveMessage<0) { _iActiveMessage = 0; } SyncScrollWithActive(); }
static FLOATaabbox3D AddAllVerticesToBBox(CModelInstance &mi) { FLOATmatrix3D mat; FLOAT3D vPos = FLOAT3D(0,0,0); mat.Diagonal(1); CStaticStackArray<FLOAT3D> avVertices; mi.GetModelVertices(avVertices,mat,vPos,0,0); INDEX ctvtx = avVertices.Count(); // if at least one vertex exists FLOATaabbox3D bbox; if(ctvtx>0) { bbox = FLOATaabbox3D(avVertices[0]); // for each vertex after first one for(INDEX ivx=1;ivx<ctvtx;ivx++) { // add this vertex position to all frames bbox bbox |= FLOATaabbox3D(avVertices[ivx]); } } return bbox; }
// render credits to given drawport FLOAT Credits_Render(CDrawPort *pdp) { if (!_bCreditsOn) { return 0; } CDrawPort dpWide; pdp->MakeWideScreen(&dpWide); pdp->Unlock(); dpWide.Lock(); FLOAT fTime = GetTime(); pixW = dpWide.GetWidth(); pixH = dpWide.GetHeight(); fResolutionScaling = (FLOAT)pixW / 640.0f; dpWide.SetFont( _pfdDisplayFont); pixLineHeight = floor(20*fResolutionScaling); const FLOAT fLinesPerSecond = _fSpeed; FLOAT fOffset = fTime*fLinesPerSecond; INDEX ctLinesOnScreen = pixH/pixLineHeight; INDEX iLine1 = fOffset; pixJ = iLine1*pixLineHeight-fOffset*pixLineHeight; iLine1-=ctLinesOnScreen; INDEX ctLines = _astrCredits.Count(); BOOL bOver = TRUE; for (INDEX i = iLine1; i<iLine1+ctLinesOnScreen+1; i++) { CTString *pstr = &strEmpty; INDEX iLine = i; if (iLine>=0 && iLine<ctLines) { pstr = &_astrCredits[iLine]; bOver = FALSE; } PrintOneLine(&dpWide, *pstr); } dpWide.Unlock(); pdp->Lock(); if (bOver) { return 0; } else if (ctLines-iLine1<ctLinesOnScreen) { return FLOAT(ctLines-iLine1)/ctLinesOnScreen; } else { return 1; } }
// Clean all values void shaClean(void) { _ctVertices = -1; _ctIndices = -1; _ctColors = -1; _ctTextures = -1; _ctUVMaps = -1; _ctLights = -1; _colConstant = 0; _ulFlags = 0; _pShader = NULL; _paVertices = NULL; _paNormals = NULL; _paIndices = NULL; _paUVMaps = NULL; _paTextures = NULL; _paColors = NULL; _paFloats = NULL; _pCurrentUVMap = NULL; _pcolVtxColors = NULL; _paFogUVMap = NULL; _paHazeUVMap = NULL; _pacolVtxHaze = NULL; _pmObjToView = NULL; _pmObjToAbs = NULL; _paprProjection = NULL; _acolVtxColors.PopAll(); _acolVtxModifyColors.PopAll(); _vModifyVertices.PopAll(); _uvUVMapForModify.PopAll(); shaCullFace(GFX_BACK); }