Exemple #1
0
/**
 *  Main loop code.
 */
void CDemo::perform()
{
	char buf[100];

	time_value tmv = CSystemTimer::getInstance().getTime();
	double t = tmv.tosec();
	float dt = CSystemTimer::getInstance().getDeltaTimeS();
	gTimeParam = float(t);

	CDynamicVBManager::getInstance().discard();

	CD3DDevice& dx = CD3DDevice::getInstance();
	gScreenFixUVs.set( 0.5f/dx.getBackBufferWidth(), 0.5f/dx.getBackBufferHeight(), 0.0f, 0.0f );

	CGameInfo& gi = CGameInfo::getInstance();
	const CGameDesc& desc = gi.getGameDesc();
	CGameState& state = gi.getState();
	const CGameMap& gmap = desc.getMap();

	//
	// should we still perform some initialization steps?

	if( !gInitGuiDone ) {
		// perform multi-step initialization...
		const char* initStepName = NULL;
		if( !gInitMainStarted ) {

			BEGIN_T();
			
			initStepName = gi.initBegin();
			gInitMainStarted = true;
		} else if( !gInitMainDone ) {
			initStepName = gi.initStep();
			if( !initStepName ) {
				initStepName = "Initializing GUI...";
				gInitMainDone = true;
			}
		} else {
			gInitiallyPlaceViewer();
			gSetupGUI();
			gInitGuiDone = true;

			END_T( "initialization" );
			
			return;
		}
		// check for init errors...
		if( !gErrorMsg.empty() ) {
			CONS << "Fatal error: " << gErrorMsg << endl;
			gFinished = true;
			return;
		}
		if( initStepName ) {
			CONS << "Init step: " << initStepName << endl;
		}
		// render progress
		assert( initStepName );
		dx.clearTargets( true, true, true, 0xFF000000, 1.0f, 0L );
		dx.sceneBegin();
		G_RENDERCTX->applyGlobalEffect();
		gUIDlg->renderBegin();
		gUIDrawLogo();
		gUIDrawProgress( initStepName );
		gUIDlg->renderEnd();
		dx.sceneEnd();
		return;
	}

	//
	// fatal error

	if( gCheckFatalError() )
		return;

	//
	// check if settings dialog just was closed

	if( gSettingsDlgWasActive && gUISettingsDlg->getState() != CDemoSettingsDialog::STATE_ACTIVE ) {
		gSettingsDlgWasActive = false;
		gUIDlg->getCheckBox( GID_CHK_OPTIONS )->setChecked( false );
		if( gUISettingsDlg->getState() == CDemoSettingsDialog::STATE_OK ) {
			// apply settings, return
			if( gAppSettings.gfxDetail != gUISettingsDlg->getAppSettings().gfxDetail ) {
				gi.getLevelMesh().updateDetailLevel( gUISettingsDlg->getAppSettings().gfxDetail );
			}
			gAppSettings = gUISettingsDlg->getAppSettings();
			CD3DSettings d3dset;
			gUISettingsDlg->getFinalSettings( d3dset );
			// don't apply d3d settings if they didn't change
			if( d3dset != gAppContext->getD3DSettings() )
				gAppContext->applyD3DSettings( d3dset );
			return;
		}
	} else if( gSettingsDlgWasActive ) {
		// if the dialog is active, but the d3d settings just changed (eg. alt-tab),
		// hide it and re-show it
		if( gSettingsAtDlgStart != gAppContext->getD3DSettings() ) {
			gUISettingsDlg->hideDialog();
			gSettingsAtDlgStart = gAppContext->getD3DSettings();
			gUISettingsDlg->showDialog( gSettingsAtDlgStart );
		}
	}

	//
	// check if help dialog just was closed

	if( gHelpDlgWasActive && !gUIHelpDlg->isActive() ) {
		gHelpDlgWasActive = false;
		gUIDlg->getCheckBox( GID_CHK_HELP )->setChecked( false );
	}


	bool gameSetupActive = (gUIGameSetupDlg->getState() == CGameSetupDialog::STATE_ACTIVE);
	bool insideView = gAppSettings.followMode && !gameSetupActive;

	//
	// perform input

	G_INPUTCTX->perform();

	//
	// update game if it's started

	if( gameSetupActive ) {
		gUILabelTime->setVisible( false );
	} else {
		// if server state is starting, update it
		if( state.getServerState().state == GST_STARTING ) {
			gUILabelTime->setVisible( false );
			state.updateServerState( false, false );
		} else {
			gUILabelTime->setVisible( true );
			// update game state
			if( tmv - gLastGameUpdateTime >= time_value::fromsec(desc.getTurnDT()*0.5f) ) {
				// TBD: commands to dll
				net::updateGame( 0, 0, 0, state );
				gLastGameUpdateTime = tmv;
			}
		}
	}


	//
	// control time

	// TBD
	/*
	float gameTime = gi.getTime();
	float oldGameTime = gameTime;
	if( gUIBtnTimeRew->isPressed() )
		gameTime -= TURNS_PER_SEC * TIME_SPD_FAST * dt;
	if( gUIBtnTimeFfwd->isPressed() )
		gameTime += TURNS_PER_SEC * TIME_SPD_FAST * dt;
	if( gameTime != oldGameTime )
		gSetPlayMode( false );
	if( gPlayMode )
		gameTime += TURNS_PER_SEC * TIME_SPD_NORMAL * dt;
	if( gameTime < 0 )
		gameTime = 0;
	if( gameTime > replay.getGameTurnCount()-1 ) {
		gameTime = replay.getGameTurnCount()-1;
		gSetPlayMode( false );
	}
	gUIDlg->enableNonUserEvents( false );
	gUISliderTime->setValue( gameTime );
	gUIDlg->enableNonUserEvents( true );
	gi.setTime( gameTime );
	*/

	//
	// camera

	int selEntityID = gi.getEntities().getSelectedEntityID();
	const CActorEntity* selEntity = gi.getEntities().getActorEntityByID( selEntityID );
	bool hasSelected = (selEntity != NULL);
	if( hasSelected ) {
		SVector3 selPos = selEntity->mWorldMat.getOrigin();
		if( !gAppSettings.followMode ) {
			selPos.y = VIEWER_Y;
			SVector3 newPos = smoothCD( gViewer.getOrigin(), selPos, gViewerVel, 0.25f, dt );
			gTryPositionViewer( newPos, selPos );
		} else {
			//SVector3 selPrevPos = selEntity.samplePos( gi.getTime() - 10.0f );
			// TBD
			SVector3 selPrevPos = selPos;
			selPrevPos.y = (selPrevPos.y + VIEWER_Y)*0.5f;
			selPos.y = selPrevPos.y;
			SVector3 dirZ = selPos - selPrevPos;
			dirZ.y = 0.0f;
			const float MIN_DIST = 2.0f;
			if( dirZ.lengthSq() < MIN_DIST*MIN_DIST ) {
				dirZ = gViewer.getAxisZ();
				selPrevPos = selPrevPos - dirZ * MIN_DIST;
			}
			const float PREF_DIST = 5.0f;
			if( dirZ.lengthSq() < PREF_DIST*PREF_DIST ) {
				dirZ.normalize();
				selPrevPos = selPos - dirZ * PREF_DIST;
			} else {
				dirZ.normalize();
			}
			const float SMOOTHT = 0.5f;
			SVector3 newPos = smoothCD( gViewer.getOrigin(), selPrevPos, gViewerVel, SMOOTHT, dt );
			gTryPositionViewer( newPos, selPrevPos );
			dirZ = smoothCD( gViewer.getAxisZ(), dirZ, gViewerZVel, SMOOTHT, dt );
			if( dirZ.lengthSq() < 0.5f ) {
				dirZ = gViewer.getAxisZ();
			} else {
				gViewer.getAxisZ() = dirZ.getNormalized();
			}
			gViewer.getAxisY().set(0,1,0);
			gViewer.getAxisX() = gViewer.getAxisY().cross( gViewer.getAxisZ() );
		}
	} else {
		gViewerVel.set(0,0,0);
		gViewerZVel.set(0,0,0);
	}

	//
	// check if current viewer's position is valid

	{
		SVector3 testViewerPos = gViewer.getOrigin();
		int cx = testViewerPos.x;
		int cy = -testViewerPos.z;
		if( cx >= 0 && cy >= 0 && cx < gmap.getCellsX() && cy < gmap.getCellsY() && gmap.isBlood( gmap.getCell(cx,cy).type ) ) {
			gi.getLevelMesh().fitSphere( testViewerPos, VIEWER_R*2.0f );
			const float SMALL_FIT = 0.2f;
			if( SVector3(testViewerPos - gViewer.getOrigin()).lengthSq() < SMALL_FIT * SMALL_FIT ) {
				gLastViewerValidPos = testViewerPos;
			}
		}
	}

	SMatrix4x4& mm = gCamera.mWorldMat;
	mm = gViewer;
	float camnear, camfar, camfov, fognear, fogfar;
	if( !insideView ) {
		float tilt = gAppSettings.megaTilt;
		float zoom = gAppSettings.megaZoom;
		if( gameSetupActive ) {
			gUIGameSetupDlg->updateViewer( gViewer, tilt, zoom );
		}

		SMatrix4x4 mr;
		D3DXMatrixRotationX( &mr, D3DXToRadian( tilt ) );
		mm = mr * mm;
		mm.getOrigin() -= mm.getAxisZ() * zoom;

		camnear = (zoom - 15.0f) * 0.25f;
		camfar = (zoom + 10.0f) * 2.5f;
		camfov = D3DX_PI/3;
		fognear = (zoom + 10.0f) * 2.0f;
		fogfar = (zoom + 10.0f) * 2.3f;
		gFogColorParam.set( 0, 0, 0, 1 );
	} else {
		camnear = 0.3f;
		camfar = 60.0f;
		camfov = D3DX_PI/4;
		fognear = 20.0f;
		fogfar = camfar-1;
		gFogColorParam.set( 0.25f, 0, 0, 1 );
	}

	if( camnear < 0.1f )
		camnear = 0.1f;
	gCamera.setProjectionParams( camfov, dx.getBackBufferAspect(), camnear, camfar );
	gCamera.setOntoRenderContext();


	//
	// update entities and stats UI

	gMouseRay = gCamera.getWorldRay( gMouseX, gMouseY );
	const SVector3& eyePos = gCamera.mWorldMat.getOrigin();
	SLine3 mouseRay;
	mouseRay.pos = eyePos;
	mouseRay.vec = gMouseRay;

	float timeAlpha = (tmv - gi.getState().getTurnReceivedTime()).tosec() / desc.getTurnDT();
	if( timeAlpha >= 1.0f )
		timeAlpha = 1.0f;
	gi.getEntities().update( mouseRay, timeAlpha );
	
	// stats UI
	int nplayers = desc.getPlayerCount();
	for( int p = 0; p < nplayers; ++p ) {
		const CGameState::SPlayer& pl = state.getPlayer(p);
		SUIPlayerStats& plui = gUIPlayerStats[p];
		if( plui.score ) {
			itoa( pl.score, buf, 10 );
			plui.score->setText( buf );
		}
		if( plui.botCount ) {
			itoa( pl.botCount, buf, 10 );
			plui.botCount->setText( buf );
		}
	}

	// entity stats UI
	gUpdateSelEntityStats();
	gUpdateMissionStats();
	
	// time UI
	sprintf( buf, "%i", state.getTurn() );
	gUILabelTime->setText( buf );
	sprintf( buf, "fps: %.1f", dx.getStats().getFPS() );
	gUILabelFPS->setText( buf );

	gFogParam.set( fognear, fogfar, 1.0f/(fogfar-fognear), 0 );


	dx.clearTargets( true, true, true, insideView ? 0xFF400000 : 0xFF000000, 1.0f, insideView ? 1L : 0L );
	dx.sceneBegin();
	G_RENDERCTX->applyGlobalEffect();
	gi.getLevelMesh().render( RM_NORMAL, insideView ? (CLevelMesh::FULL) : (CLevelMesh::NOTOP) );
	gi.getPointsMesh().render( RM_NORMAL );
	gi.getEntities().render( RM_NORMAL, !insideView, insideView, timeAlpha );
	G_RENDERCTX->perform();

	// render GUI
	if( !gameSetupActive ) {
		gUIDlg->onRender( dt );
	}

	// render minimap
	if( gAppSettings.showMinimap && !gameSetupActive )
		gRenderMinimap();

	// render GUI #2
	if( gUISettingsDlg->getState() == CDemoSettingsDialog::STATE_ACTIVE ) {
		gUISettingsDlg->getDialog().onRender( dt );
	}
	if( gUIHelpDlg->isActive() ) {
		gUIHelpDlg->getDialog().onRender( dt );
	}
	if( gUIGameSetupDlg->getState() == CGameSetupDialog::STATE_ACTIVE ) {
		gUIGameSetupDlg->getDialog().onRender( dt );
	}

	dx.sceneEnd();
}