void CHLSL_Image::CreateScreenshot( CNodeView *n, const char *filepath )
{
	Vector4D graphBounds;
	n->GetGraphBoundaries( graphBounds );

	int vsize_x, vsize_y;
	n->GetSize( vsize_x, vsize_y );
	const float zoomFactor = 1.0f / clamp( sedit_screenshot_zoom.GetFloat(), 0.01f, 100.0f );

	float nodespace_width = graphBounds.z - graphBounds.x;
	float nodespace_height = graphBounds.w - graphBounds.y;
	float nodespace_width_pershot = vsize_x * zoomFactor;
	float nodespace_height_pershot = vsize_y * zoomFactor;

	int numshots_x = ceil( nodespace_width / nodespace_width_pershot );
	int numshots_y = ceil( nodespace_height / nodespace_height_pershot );

	Vector2D extraSpace;
	extraSpace.x = (nodespace_width_pershot*numshots_x) - nodespace_width;
	extraSpace.y = (nodespace_height_pershot*numshots_y) - nodespace_height;
	extraSpace *= 0.5f;

	n->vecScreenshotBounds.Init( graphBounds.x - extraSpace.x,
								graphBounds.y - extraSpace.y,
								graphBounds.z + extraSpace.x,
								graphBounds.w + extraSpace.y );

	int tgapixels_x = numshots_x * vsize_x - numshots_x;
	int tgapixels_y = numshots_y * vsize_y - numshots_y;

	unsigned int targetSize = tgapixels_x * 3 * tgapixels_y;
	unsigned char *pTGA = ( unsigned char * )malloc( targetSize );
	if ( !pTGA )
	{
		Warning( "Not enough memory available (failed to malloc %u bytes).\n", targetSize );
	}

	Vector2D pos_old = n->AccessViewPos();
	float zoom_old = n->AccessViewZoom();
	n->bRenderingScreenShot = true;

	n->AccessViewZoom() = zoomFactor;

	int vp_x, vp_y;
	vp_x = vp_y = 0;
	n->LocalToScreen( vp_x, vp_y );
	int screen_sx, screen_sy;
	engine->GetScreenSize( screen_sx, screen_sy );

	vp_x++;
	vp_y++;
	vsize_x--;
	vsize_y--;

	n->AccessViewPos().Init();

	CViewSetup view2D;
	view2D.x = 0;
	view2D.y = 0;
	view2D.width = screen_sx;
	view2D.height = screen_sy;
	view2D.m_bRenderToSubrectOfLargerScreen = false;
	Frustum _fplanes;

	CMatRenderContextPtr pRenderContext( materials );

#ifdef SHADER_EDITOR_DLL_2006
	render->Push2DView( view2D, 0, false, NULL, _fplanes );
#else
	render->Push2DView( view2D, 0, NULL, _fplanes );
#endif
	pRenderContext->PushRenderTargetAndViewport( NULL, view2D.x, view2D.y, view2D.width, view2D.height );

//	bool bSuccess = TGAWriter::WriteDummyFileNoAlloc( filepath, tgapixels_x, tgapixels_y, IMAGE_FORMAT_RGBA8888 );
//	Assert( bSuccess );

	if ( pTGA )
	{
		for ( int sX = 0; sX < numshots_x; sX ++ )
		{
			for ( int sY = 0; sY < numshots_y; sY ++ )
			{
				Vector2D basepos( graphBounds.x + nodespace_width_pershot * 0.5f, graphBounds.w - nodespace_height_pershot * 0.5f );
				basepos.x += sX * nodespace_width_pershot;
				basepos.y -= sY * nodespace_height_pershot;
				basepos.x *= -1.0f;
				basepos += extraSpace;
				n->AccessViewPos() = basepos;

				pRenderContext->ClearColor4ub( 0, 0, 0, 0 );
				pRenderContext->ClearBuffers( true, true );
				vgui::ipanel()->PaintTraverse( n->GetVPanel(), true );

				unsigned int sizeimg = vsize_x * 3 * vsize_y;
				unsigned char *pImage = ( unsigned char * )malloc( sizeimg );
				if ( pImage )
				{
					pRenderContext->ReadPixels( vp_x, vp_y, vsize_x, vsize_y, pImage, IMAGE_FORMAT_RGB888 );

					for ( int pX = 0; pX < vsize_x; pX ++ )
					{
						for ( int pY = 0; pY < vsize_y; pY ++ )
						{
							int targetpixel = (sX * vsize_x + pX) * 3 +
								( sY * vsize_y + pY ) * tgapixels_x * 3;
							int srcpixel = pX * 3 + pY * vsize_x * 3;

							Q_memcpy( &pTGA[targetpixel], &pImage[srcpixel], 3 );
						}
					}
#if 0
#if DEBUG
					bool bSuccess =
#endif
					TGAWriter::WriteRectNoAlloc( pImage, filepath, sX * vsize_x, sY * vsize_y, vsize_x, vsize_y, 0, IMAGE_FORMAT_RGB888 );
#if DEBUG
					Assert( bSuccess );
#endif
#endif

					free( pImage );
				}
				else
					Warning( "Tiling error (failed to malloc %u bytes).\n", sizeimg );

			}
		}
	}


	if ( pTGA )
	{
		//unsigned int iMaxTGASize = 1024 + (tgapixels_x * tgapixels_y * 3);
		//void *pTGA_BUFFER = malloc( iMaxTGASize );
		//if ( pTGA_BUFFER )
		//{
		//	CUtlBuffer buffer( pTGA_BUFFER, iMaxTGASize );

		//	TGAWriter::WriteToBuffer( pTGA, buffer, tgapixels_x, tgapixels_y, IMAGE_FORMAT_RGB888, IMAGE_FORMAT_RGB888 );
		//	filesystem->AsyncWrite( filepath, buffer.Base(), buffer.TellPut(), true );
		//}
		//else
		//{
		//	Warning( "Not enough memory available (failed to malloc %u bytes).\n", iMaxTGASize );
		//}

		jpeg_compress_struct jInfo;
		ValveJpegErrorHandler_t jErr;
		jpeg_destination_mgr jDest;

		jInfo.err = jpeg_std_error( &jErr.m_Base );
		jInfo.err->error_exit = &ValveJpegErrorHandler;

		jpeg_create_compress( &jInfo );

		jInfo.dest = &jDest;
		jInfo.dest->init_destination = &jInit_destination;
		jInfo.dest->empty_output_buffer = &jEmpty_output_buffer;
		jInfo.dest->term_destination = &jTerm_destination;

		jInfo.image_width = tgapixels_x;
		jInfo.image_height = tgapixels_y;
		jInfo.input_components = 3;
		jInfo.in_color_space = JCS_RGB;
		jpeg_set_defaults( &jInfo );
		jpeg_set_quality( &jInfo, clamp( sedit_screenshot_quali.GetInt(), 1, 100 ), FALSE );

		jpeg_start_compress(&jInfo, TRUE);

		JSAMPROW row_pointer[1];
		int row_stride;
		row_stride = jInfo.image_width * 3;
		while (jInfo.next_scanline < jInfo.image_height)
		{
			row_pointer[0] = &pTGA[jInfo.next_scanline * row_stride];
			jpeg_write_scanlines(&jInfo, row_pointer, 1);
		}

		jpeg_finish_compress(&jInfo);

		jpeg_destroy_compress(&jInfo);

		void *pBUFFER = malloc( jOut.Count() );
		Q_memcpy( pBUFFER, jOut.Base(), jOut.Count() );
		filesystem->AsyncWrite( filepath, pBUFFER, jOut.Count(), true );

		jOut.Purge();
		free( pTGA );
	}

	pRenderContext->PopRenderTargetAndViewport();
	render->PopView( _fplanes );

	n->bRenderingScreenShot = false;
	n->AccessViewPos() = pos_old;
	n->AccessViewZoom() = zoom_old;
}
void CBuildModeDialogMgr::Remove( BuildModeDialog *pDlg )
{
	m_vecBuildDialogs.FindAndRemove( pDlg );
}
//-----------------------------------------------------------------------------
// Purpose: Creates the build mode editing controls
//-----------------------------------------------------------------------------
void BuildModeDialog::CreateControls()
{
	int i;
	m_pPanelList = new PanelList;
	m_pPanelList->m_pResourceData = new KeyValues( "BuildDialog" );
	m_pPanelList->m_pControls = new PanelListPanel(this, "BuildModeControls");

	// file to edit combo box is first
	m_pFileSelectionCombo = new ComboBox(this, "FileSelectionCombo", 10, false);
	for ( i = 0; i < m_pBuildGroup->GetRegisteredControlSettingsFileCount(); i++)
	{
		m_pFileSelectionCombo->AddItem(m_pBuildGroup->GetRegisteredControlSettingsFileByIndex(i), NULL);
	}
	if (m_pFileSelectionCombo->GetItemCount() < 2)
	{
		m_pFileSelectionCombo->SetEnabled(false);
	}

	int buttonH = 18;

	// status info at top of dialog
	m_pStatusLabel = new Label(this, "StatusLabel", "[nothing currently selected]");
	m_pStatusLabel->SetTextColorState(Label::CS_DULL);
	m_pStatusLabel->SetTall( buttonH );
	m_pDivider = new Divider(this, "Divider");
	// drop-down combo box for adding new controls
	m_pAddNewControlCombo = new ComboBox(this, NULL, 30, false);
	m_pAddNewControlCombo->SetSize(116, buttonH);
	m_pAddNewControlCombo->SetOpenDirection(Menu::DOWN);

	m_pEditableParents = new CBuildModeNavCombo( this, NULL, 15, false, true, m_pBuildGroup->GetContextPanel() );
	m_pEditableParents->SetSize(116, buttonH);
	m_pEditableParents->SetOpenDirection(Menu::DOWN);

	m_pEditableChildren = new CBuildModeNavCombo( this, NULL, 15, false, false, m_pBuildGroup->GetContextPanel() );
	m_pEditableChildren->SetSize(116, buttonH);
	m_pEditableChildren->SetOpenDirection(Menu::DOWN);

	m_pNextChild = new Button( this, "NextChild", "Next", this );
	m_pNextChild->SetCommand( new KeyValues( "OnChangeChild", "direction", 1 ) );

	m_pPrevChild = new Button( this, "PrevChild", "Prev", this );
	m_pPrevChild->SetCommand( new KeyValues( "OnChangeChild", "direction", -1 ) );

	// controls that can be added
	// this list comes from controls EditablePanel can create by name.
	int defaultItem = m_pAddNewControlCombo->AddItem("None", NULL);

	CUtlVector< char const * >	names;
	CBuildFactoryHelper::GetFactoryNames( names );
	// Sort the names
	CUtlRBTree< char const *, int > sorted( 0, 0, StringLessThan );

	for ( i = 0; i < names.Count(); ++i )
	{
		sorted.Insert( names[ i ] );
	}

	for ( i = sorted.FirstInorder(); i != sorted.InvalidIndex(); i = sorted.NextInorder( i ) )
	{
		m_pAddNewControlCombo->AddItem( sorted[ i ], NULL );
	}

	m_pAddNewControlCombo->ActivateItem(defaultItem);

	m_pExitButton = new Button(this, "ExitButton", "&Exit");
	m_pExitButton->SetSize(64, buttonH);

	m_pSaveButton = new Button(this, "SaveButton", "&Save");
	m_pSaveButton->SetSize(64, buttonH);
	
	m_pApplyButton = new Button(this, "ApplyButton", "&Apply");
	m_pApplyButton->SetSize(64, buttonH);

	m_pReloadLocalization = new Button( this, "Localization", "&Reload Localization" );
	m_pReloadLocalization->SetSize( 100, buttonH );

	m_pExitButton->SetCommand("Exit");
	m_pSaveButton->SetCommand("Save");
	m_pApplyButton->SetCommand("Apply");
	m_pReloadLocalization->SetCommand( new KeyValues( "ReloadLocalization" ) );

	m_pDeleteButton = new Button(this, "DeletePanelButton", "Delete");
	m_pDeleteButton->SetSize(64, buttonH);
	m_pDeleteButton->SetCommand("DeletePanel");

	m_pVarsButton = new MenuButton(this, "VarsButton", "Variables");
	m_pVarsButton->SetSize(72, buttonH);
	m_pVarsButton->SetOpenDirection(Menu::UP);
	
	// iterate the vars
	KeyValues *vars = m_pBuildGroup->GetDialogVariables();
	if (vars && vars->GetFirstSubKey())
	{
		// create the menu
		m_pVarsButton->SetEnabled(true);
		Menu *menu = new Menu(m_pVarsButton, "VarsMenu");

		// set all the variables to be copied to the clipboard when selected
		for (KeyValues *kv = vars->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey())
		{
			char buf[32];
			_snprintf(buf, sizeof(buf), "%%%s%%", kv->GetName());
			menu->AddMenuItem(kv->GetName(), new KeyValues("SetClipboardText", "text", buf), this);
		}

		m_pVarsButton->SetMenu(menu);
	}
	else
	{
		// no variables
		m_pVarsButton->SetEnabled(false);
	}

	m_pApplyButton->SetTabPosition(1);
	m_pPanelList->m_pControls->SetTabPosition(2);
	m_pVarsButton->SetTabPosition(3);
	m_pDeleteButton->SetTabPosition(4);
	m_pAddNewControlCombo->SetTabPosition(5);
	m_pSaveButton->SetTabPosition(6);
	m_pExitButton->SetTabPosition(7);

	m_pEditableParents->SetTabPosition( 8 );
	m_pEditableChildren->SetTabPosition( 9 );

	m_pPrevChild->SetTabPosition( 10 );
	m_pNextChild->SetTabPosition( 11 );

	m_pReloadLocalization->SetTabPosition( 12 );
}
int CGlobalEntityList::ResetDeleteList( void )
{
	int result = g_DeleteList.Count();
	g_DeleteList.RemoveAll();
	return result;
}
	void EndGroupingSounds()
	{
		g_GroupedSounds.Purge();
		SetImpactSoundRoute( NULL );
	}
Beispiel #6
0
// Add a leaf to my list of interesting leaves
void CPlaneList::ReferenceLeaf( int leafIndex )
{
	m_leafList.AddToTail( leafIndex );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CEnvMicrophone::~CEnvMicrophone( void )
{
	s_Microphones.FindAndRemove( this );
}
void FoundryHelpers_AddEntityHighlightEffect( int iEntity )
{
	EHANDLE hEnt = cl_entitylist->GetBaseEntity( iEntity );
	if ( hEnt.IsValid() )
		g_EntityHighlightEffects.AddToTail( hEnt );
}
// add the sample to the list.  If we exceed the maximum number of samples, the worst sample will
// be discarded.  This has the effect of converging on the best samples when enough are added.
void AddSampleToList( CUtlVector<ambientsample_t> &list, const Vector &samplePosition, Vector *pCube )
{
	const int MAX_SAMPLES = 16;

	int index = list.AddToTail();
	list[index].pos = samplePosition;
	for ( int i = 0; i < 6; i++ )
	{
		list[index].cube[i] = pCube[i];
	}

	if ( list.Count() <= MAX_SAMPLES )
		return;

	int nearestNeighborIndex = 0;
	float nearestNeighborDist = FLT_MAX;
	float nearestNeighborTotal = 0;
	for ( int i = 0; i < list.Count(); i++ )
	{
		int closestIndex = 0;
		float closestDist = FLT_MAX;
		float totalDC = 0;
		for ( int j = 0; j < list.Count(); j++ )
		{
			if ( j == i )
				continue;
			float dist = (list[i].pos - list[j].pos).Length();
			float maxDC = 0;
			for ( int k = 0; k < 6; k++ )
			{
				// color delta is computed per-component, per cube side
				for (int s = 0; s < 3; s++ )
				{
					float dc = fabs(list[i].cube[k][s] - list[j].cube[k][s]);
					maxDC = max(maxDC,dc);
				}
				totalDC += maxDC;
			}
			// need a measurable difference in color or we'll just rely on position
			if ( maxDC < 1e-4f )
			{
				maxDC = 0;
			}
			else if ( maxDC > 1.0f )
			{
				maxDC = 1.0f;
			}
			// selection criteria is 10% distance, 90% color difference
			// choose samples that fill the space (large distance from each other)
			// and have largest color variation
			float distanceFactor = 0.1f + (maxDC * 0.9f);
			dist *= distanceFactor;

			// find the "closest" sample to this one
			if ( dist < closestDist )
			{
				closestDist = dist;
				closestIndex = j;
			}
		}
		// the sample with the "closest" neighbor is rejected
		if ( closestDist < nearestNeighborDist || (closestDist == nearestNeighborDist && totalDC < nearestNeighborTotal) )
		{
			nearestNeighborDist = closestDist;
			nearestNeighborIndex = i;
		}
	}
	list.FastRemove( nearestNeighborIndex );
}
//-----------------------------------------------------------------------------
// Purpose: Applies dialog data to the list of selected faces.
// Input  : *pOnlyFace - 
//			bAll - 
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::Apply( CMapFace *pOnlyFace, int flags )
{
	int			i;
	CString		str;
	float		fshiftX = NOT_INIT;
	float		fshiftY = NOT_INIT;
	float		fscaleX = NOT_INIT;
	float		fscaleY = NOT_INIT;
	float		frotate = NOT_INIT;
	int			material = NOT_INIT;
	int			nLightmapScale = NOT_INIT;
	IEditorTexture	*pTex = m_TexturePic.GetTexture();

	//
	// Get numeric data.
	//
	if (flags & FACE_APPLY_MAPPING)
	{
		TransferToFloat( &m_shiftX, fshiftX );
		TransferToFloat( &m_shiftY, fshiftY );
		TransferToFloat( &m_scaleX, fscaleX );
		TransferToFloat( &m_scaleY, fscaleY );
		TransferToFloat( &m_rotate, frotate );
	}

	if (flags & FACE_APPLY_LIGHTMAP_SCALE)
	{
		TransferToInteger( &m_cLightmapScale, nLightmapScale );
	}

	if ( !pOnlyFace )
	{
		GetHistory()->MarkUndoPosition( NULL, "Apply Face Attributes" );

		// make sure we apply everything in this case.
		flags |= FACE_APPLY_ALL;

		// Keep the solids that we are about to change.
		// In the pOnlyFace case we do the Keep before calling ClickFace. Why?
		CUtlVector<CMapSolid *> kept;
		CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
		for( i = 0; i < pSheet->GetFaceListCount(); i++ )
		{
			CMapSolid *pSolid = pSheet->GetFaceListDataSolid( i );
			if ( kept.Find( pSolid ) == -1 )
			{
				GetHistory()->Keep( pSolid );
				kept.AddToTail( pSolid );
			}
		}
	}
		
	//
	// Run thru stored faces & apply.
	//
	CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
	int faceCount = pSheet->GetFaceListCount();
	for( i = 0; i < faceCount || pOnlyFace; i++ )
	{
		CMapFace *pFace;
		if( pOnlyFace )
		{
			pFace = pOnlyFace;
		}
		else
		{
			pFace = pSheet->GetFaceListDataFace( i );
		}

		//
		// Get values for texture shift, scale, rotate, and material.
		//
		if ((flags & FACE_APPLY_MAPPING) && (!(flags & FACE_APPLY_ALIGN_EDGE)))
		{
			if ( fshiftX != NOT_INIT )
			{
				pFace->texture.UAxis[3] = fshiftX;
			}

			if ( fshiftY != NOT_INIT )
			{
				pFace->texture.VAxis[3] = fshiftY;
			}

			if ( fscaleX != NOT_INIT )
			{
				pFace->texture.scale[0] = fscaleX;
			}
			
			if ( fscaleY != NOT_INIT )
			{
				pFace->texture.scale[1] = fscaleY;
			}

			if ( frotate != NOT_INIT )
			{
				pFace->RotateTextureAxes( frotate - pFace->texture.rotate );
				pFace->texture.rotate = frotate;
			}
		}

		if (flags & FACE_APPLY_CONTENTS_DATA)
		{
			if ( material != NOT_INIT )
			{
				pFace->texture.material = material;
			}
		}

		if (flags & FACE_APPLY_LIGHTMAP_SCALE)
		{
			if (nLightmapScale != NOT_INIT)
			{
				pFace->texture.nLightmapScale = max( nLightmapScale, 1 );
			}
		}

		//
		// Update the texture and recalculate texture coordinates.
		//
		if ((flags & FACE_APPLY_MATERIAL) && (pTex != NULL))
		{
			char szCurrentTexName[MAX_PATH];
			char szNewTexName[MAX_PATH];

			pFace->GetTextureName( szCurrentTexName );
			pTex->GetShortName( szNewTexName );

			if( stricmp( szCurrentTexName, szNewTexName ) != 0 )
			{
				pFace->SetTexture( szNewTexName );
			}
		}

		//
		// Copy texture coordinate system.
		//
		if ((flags & FACE_APPLY_ALIGN_EDGE) && (faceCount >= 1))
		{
			CopyTCoordSystem( pSheet->GetFaceListDataFace( faceCount - 1 ), pFace );
		}

		//
		// Recalculate texture coordinates.
		//
		pFace->CalcTextureCoords();

		//
		// Update the face flags.
		//
		if (flags & FACE_APPLY_CONTENTS_DATA)
		{
			//
			// Copy the bits from this face into our variables.
			//
			m_FaceContents = pFace->texture.q2contents;
			m_FaceSurface = pFace->texture.q2surface;

			//
			// Update our variables based on the state of the checkboxes.
			//
			for( int nItem = 0; nItem < sizeof( FaceAttributes ) / sizeof( FaceAttributes[0] ); nItem++ )
			{
				CButton *pButton = ( CButton* )GetDlgItem( FaceAttributes[nItem].uControlID );
				if( pButton != NULL )
				{
					int nSet = pButton->GetCheck();

					if (nSet == 0)
					{
						*FaceAttributes[nItem].puAttribute &= ~FaceAttributes[nItem].uFlag;
					}
					else if (nSet == 1)
					{
						*FaceAttributes[nItem].puAttribute |= FaceAttributes[nItem].uFlag;
					}
				}	
			}

			//
			// Copy our variables back into this face.
			//
			pFace->texture.q2contents = m_FaceContents;
			pFace->texture.q2surface = m_FaceSurface;
		}

		if( pOnlyFace )
		{
			break;
		}
	}

	CMapDoc::GetActiveMapDoc()->SetModifiedFlag();
}
void FoundryHelpers_ClearEntityHighlightEffects()
{
	g_EntityHighlightEffects.Purge();
}
void CMoveHelperClient::ResetTouchList( void )
{
	m_TouchList.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose: Compute the overall color & alpha of the fades
//-----------------------------------------------------------------------------
void CViewEffects::FadeCalculate( void )
{
	// Cycle through all fades and remove any that have finished (work backwards)
	int i;
	int iSize = m_FadeList.Size();
	for (i = iSize-1; i >= 0; i-- )
	{
		screenfade_t *pFade = m_FadeList[i];

		// Keep pushing reset time out indefinitely
		if ( pFade->Flags & FFADE_STAYOUT )
		{
			pFade->Reset = gpGlobals->curtime + 0.1;
		}

		// All done?
		if ( ( gpGlobals->curtime > pFade->Reset ) && ( gpGlobals->curtime > pFade->End ) )
		{
			// User passed in a callback function, call it now
			if ( s_pfnFadeDoneCallback )
			{
				s_pfnFadeDoneCallback( s_nCallbackParameter );
				s_pfnFadeDoneCallback = NULL;
				s_nCallbackParameter = 0;
			}

			// Remove this Fade from the list
			m_FadeList.FindAndRemove( pFade );
			delete pFade;
		}
	}

	m_bModulate = false;
	m_FadeColorRGBA[0] = m_FadeColorRGBA[1] = m_FadeColorRGBA[2] = m_FadeColorRGBA[3] = 0;

	// Cycle through all fades in the list and calculate the overall color/alpha
	for ( i = 0; i < m_FadeList.Size(); i++ )
	{
		screenfade_t *pFade = m_FadeList[i];

		// Color
		m_FadeColorRGBA[0] += pFade->r;
		m_FadeColorRGBA[1] += pFade->g;
		m_FadeColorRGBA[2] += pFade->b;

		// Fading...
		int iFadeAlpha;
		if ( pFade->Flags & (FFADE_OUT|FFADE_IN) )
		{
			iFadeAlpha = pFade->Speed * ( pFade->End - gpGlobals->curtime );
			if ( pFade->Flags & FFADE_OUT )
			{
				iFadeAlpha += pFade->alpha;
			}
			iFadeAlpha = MIN( iFadeAlpha, pFade->alpha );
			iFadeAlpha = MAX( 0, iFadeAlpha );
		}
		else
		{
			iFadeAlpha = pFade->alpha;
		}

		// Use highest alpha
		if ( iFadeAlpha > m_FadeColorRGBA[3] )
		{
			m_FadeColorRGBA[3] = iFadeAlpha;
		}

		// Modulate?
		if ( pFade->Flags & FFADE_MODULATE )
		{
			m_bModulate = true;
		}
	}

	// Divide colors
	if ( m_FadeList.Size() )
	{
		m_FadeColorRGBA[0] /= m_FadeList.Size();
		m_FadeColorRGBA[1] /= m_FadeList.Size();
		m_FadeColorRGBA[2] /= m_FadeList.Size();
	}
}
//-----------------------------------------------------------------------------
// Purpose: Apply noise to the eye position.
// UNDONE: Feedback a bit of this into the view model position.  It shakes too much
//-----------------------------------------------------------------------------
void CViewEffects::CalcShake( void )
{
	float	fraction, freq;

	// We'll accumulate the aggregate shake for this frame into these data members.
	m_vecShakeAppliedOffset.Init(0, 0, 0);
	m_flShakeAppliedAngle = 0;
	float flRumbleAngle = 0;

	// NVNT - haptic shake effect amplitude
	float hapticShakeAmp = 0;

	bool bShow = shake_show.GetBool();

	int nShakeCount = m_ShakeList.Count();

	for ( int nShake = nShakeCount - 1; nShake >= 0; nShake-- )
	{
		screenshake_t *pShake = m_ShakeList.Element( nShake );

		if ( pShake->endtime == 0 )
		{
			// Shouldn't be any such shakes in the list.
			Assert( false );
			continue;
		}

		if ( ( gpGlobals->curtime > pShake->endtime ) || 
			pShake->duration <= 0 || 
			pShake->amplitude <= 0 || 
			pShake->frequency <= 0 )
		{
			// Retire this shake.
			delete m_ShakeList.Element( nShake );
			m_ShakeList.FastRemove( nShake );
			continue;
		}

		if ( bShow )
		{
			con_nprint_t np;
			np.time_to_live = 2.0f;
			np.fixed_width_font = true;
			np.color[0] = 1.0;
			np.color[1] = 0.8;
			np.color[2] = 0.1;
			np.index = nShake + 2;

			engine->Con_NXPrintf( &np, "%02d: dur(%8.2f) amp(%8.2f) freq(%8.2f)", nShake + 1, (double)pShake->duration, (double)pShake->amplitude, (double)pShake->frequency );
		}

		if ( gpGlobals->curtime > pShake->nextShake )
		{
			// Higher frequency means we recalc the extents more often and perturb the display again
			pShake->nextShake = gpGlobals->curtime + (1.0f / pShake->frequency);

			// Compute random shake extents (the shake will settle down from this)
			for (int i = 0; i < 3; i++ )
			{
				pShake->offset[i] = random->RandomFloat( -pShake->amplitude, pShake->amplitude );
			}

			pShake->angle = random->RandomFloat( -pShake->amplitude*0.25, pShake->amplitude*0.25 );
		}

		// Ramp down amplitude over duration (fraction goes from 1 to 0 linearly with slope 1/duration)
		fraction = ( pShake->endtime - gpGlobals->curtime ) / pShake->duration;

		// Ramp up frequency over duration
		if ( fraction )
		{
			freq = (pShake->frequency / fraction);
		}
		else
		{
			freq = 0;
		}

		// square fraction to approach zero more quickly
		fraction *= fraction;

		// Sine wave that slowly settles to zero
		float angle = gpGlobals->curtime * freq;
		if ( angle > 1e8 )
		{
			angle = 1e8;
		}
		fraction = fraction * sin( angle );
		
		if( pShake->command != SHAKE_START_NORUMBLE )
		{
			// As long as this isn't a NO RUMBLE effect, then accumulate rumble
			flRumbleAngle += pShake->angle * fraction;
		}

		if( pShake->command != SHAKE_START_RUMBLEONLY )
		{
			// As long as this isn't a RUMBLE ONLY effect, then accumulate screen shake
			
			// Add to view origin
			m_vecShakeAppliedOffset += pShake->offset * fraction;

			// Add to roll
			m_flShakeAppliedAngle += pShake->angle * fraction;
		}

		// Drop amplitude a bit, less for higher frequency shakes
		pShake->amplitude -= pShake->amplitude * ( gpGlobals->frametime / (pShake->duration * pShake->frequency) );
		// NVNT - update our amplitude.
		hapticShakeAmp += pShake->amplitude*fraction;
	}
	// NVNT - apply our screen shake update
	if ( haptics )
		haptics->SetShake(hapticShakeAmp,1);

	// Feed this to the rumble system!
	UpdateScreenShakeRumble( flRumbleAngle );
}
Beispiel #15
0
// adds a collision entry for this brush model
static void ConvertModelToPhysCollide( CUtlVector<CPhysCollisionEntry *> &collisionList, int modelIndex, int contents, float shrinkSize, float mergeTolerance )
{
	int i;
	CPlaneList planes( shrinkSize, mergeTolerance );

	planes.m_contentsMask = contents;

	dmodel_t *pModel = dmodels + modelIndex;
	VisitLeaves_r( planes, pModel->headnode );
	planes.AddBrushes();
	int count = planes.m_convex.Count();
	convertconvexparams_t params;
	params.Defaults();
	params.buildOuterConvexHull = count > 1 ? true : false;
	params.buildDragAxisAreas = true;
	Vector size = pModel->maxs - pModel->mins;

	float minSurfaceArea = -1.0f;
	for ( i = 0; i < 3; i++ )
	{
		int other = (i+1)%3;
		int cross = (i+2)%3;
		float surfaceArea = size[other] * size[cross];
		if ( minSurfaceArea < 0 || surfaceArea < minSurfaceArea )
		{
			minSurfaceArea = surfaceArea;
		}
	}
	// this can be really slow with super-large models and a low error tolerance
	// Basically you get a ray cast through each square of epsilon surface area on each OBB side
	// So compute it for 1% error (on the smallest side, less on larger sides)
	params.dragAreaEpsilon = clamp( minSurfaceArea * 1e-2f, 1.0f, 1024.0f );
	CPhysCollide *pCollide = physcollision->ConvertConvexToCollideParams( planes.m_convex.Base(), count, params );
	
	if ( !pCollide )
		return;

	struct 
	{
		int prop;
		float area;
	} proplist[256];
	int numprops = 1;

	proplist[0].prop = -1;
	proplist[0].area = 1;
	// compute the array of props on the surface of this model

	// NODRAW brushes no longer have any faces
	if ( !dmodels[modelIndex].numfaces )
	{
		int sideIndex = planes.GetFirstBrushSide();
		int texdata = texinfo[dbrushsides[sideIndex].texinfo].texdata;
		int prop = g_SurfaceProperties[texdata];
		proplist[numprops].prop = prop;
		proplist[numprops].area = 2;
		numprops++;
	}

	for ( i = 0; i < dmodels[modelIndex].numfaces; i++ )
	{
		dface_t *face = dfaces + i + dmodels[modelIndex].firstface;
		int texdata = texinfo[face->texinfo].texdata;
		int prop = g_SurfaceProperties[texdata];
		int j;
		for ( j = 0; j < numprops; j++ )
		{
			if ( proplist[j].prop == prop )
			{
				proplist[j].area += face->area;
				break;
			}
		}

		if ( (!numprops || j >= numprops) && numprops < ARRAYSIZE(proplist) )
		{
			proplist[numprops].prop = prop;
			proplist[numprops].area = face->area;
			numprops++;
		}
	}


	// choose the prop with the most surface area
	int maxIndex = -1;
	float maxArea = 0;
	float totalArea = 0;

	for ( i = 0; i < numprops; i++ )
	{
		if ( proplist[i].area > maxArea )
		{
			maxIndex = i;
			maxArea = proplist[i].area;
		}
		// add up the total surface area
		totalArea += proplist[i].area;
	}
	
	float mass = 1.0f;
	const char *pMaterial = "default";
	if ( maxIndex >= 0 )
	{
		int prop = proplist[maxIndex].prop;
		
		// use default if this material has no prop
		if ( prop < 0 )
			prop = 0;

		pMaterial = physprops->GetPropName( prop );
		float density, thickness;
		physprops->GetPhysicsProperties( prop, &density, &thickness, NULL, NULL );

		// if this is a "shell" material (it is hollow and encloses some empty space)
		// compute the mass with a constant surface thickness
		if ( thickness != 0 )
		{
			mass = totalArea * thickness * density * CUBIC_METERS_PER_CUBIC_INCH;
		}
		else
		{
			// material is completely solid, compute total mass as if constant density throughout.
			mass = planes.m_totalVolume * density * CUBIC_METERS_PER_CUBIC_INCH;
		}
	}

	// Clamp mass to 100,000 kg
	if ( mass > VPHYSICS_MAX_MASS )
	{
		mass = VPHYSICS_MAX_MASS;
	}

	collisionList.AddToTail( new CPhysCollisionEntrySolid( pCollide, pMaterial, mass ) );
}
void ComputePerLeafAmbientLighting()
{
	// Figure out which lights should go in the per-leaf ambient cubes.
	int nInAmbientCube = 0;
	int nSurfaceLights = 0;
	for ( int i=0; i < *pNumworldlights; i++ )
	{
		dworldlight_t *wl = &dworldlights[i];
		
		if ( IsLeafAmbientSurfaceLight( wl ) )
			wl->flags |= DWL_FLAGS_INAMBIENTCUBE;
		else
			wl->flags &= ~DWL_FLAGS_INAMBIENTCUBE;
	
		if ( wl->type == emit_surface )
			++nSurfaceLights;

		if ( wl->flags & DWL_FLAGS_INAMBIENTCUBE )
			++nInAmbientCube;
	}

	Msg( "%d of %d (%d%% of) surface lights went in leaf ambient cubes.\n", nInAmbientCube, nSurfaceLights, nSurfaceLights ? ((nInAmbientCube*100) / nSurfaceLights) : 0 );

	g_LeafAmbientSamples.SetCount(numleafs);

	if ( g_bUseMPI )
	{
		// Distribute the work among the workers.
		VMPI_SetCurrentStage( "ComputeLeafAmbientLighting" );
		DistributeWork( numleafs, VMPI_DISTRIBUTEWORK_PACKETID, VMPI_ProcessLeafAmbient, VMPI_ReceiveLeafAmbientResults );
	}
	else
	{
		RunThreadsOn(numleafs, true, ThreadComputeLeafAmbient);
	}

	// now write out the data
	Msg("Writing leaf ambient...");
	g_pLeafAmbientIndex->RemoveAll();
	g_pLeafAmbientLighting->RemoveAll();
	g_pLeafAmbientIndex->SetCount( numleafs );
	g_pLeafAmbientLighting->EnsureCapacity( numleafs*4 );
	for ( int leafID = 0; leafID < numleafs; leafID++ )
	{
		const CUtlVector<ambientsample_t> &list = g_LeafAmbientSamples[leafID];
		g_pLeafAmbientIndex->Element(leafID).ambientSampleCount = list.Count();
		if ( !list.Count() )
		{
			g_pLeafAmbientIndex->Element(leafID).firstAmbientSample = 0;
		}
		else
		{
			g_pLeafAmbientIndex->Element(leafID).firstAmbientSample = g_pLeafAmbientLighting->Count();
			// compute the samples in disk format.  Encode the positions in 8-bits using leaf bounds fractions
			for ( int i = 0; i < list.Count(); i++ )
			{
				int outIndex = g_pLeafAmbientLighting->AddToTail();
				dleafambientlighting_t &light = g_pLeafAmbientLighting->Element(outIndex);

				light.x = Fixed8Fraction( list[i].pos.x, dleafs[leafID].mins[0], dleafs[leafID].maxs[0] );
				light.y = Fixed8Fraction( list[i].pos.y, dleafs[leafID].mins[1], dleafs[leafID].maxs[1] );
				light.z = Fixed8Fraction( list[i].pos.z, dleafs[leafID].mins[2], dleafs[leafID].maxs[2] );
				light.pad = 0;
				for ( int side = 0; side < 6; side++ )
				{
					VectorToColorRGBExp32( list[i].cube[side], light.cube.m_Color[side] );
				}
			}
		}
	}
	for ( int i = 0; i < numleafs; i++ )
	{
		// UNDONE: Do this dynamically in the engine instead.  This will allow us to sample across leaf
		// boundaries always which should improve the quality of lighting in general
		if ( g_pLeafAmbientIndex->Element(i).ambientSampleCount == 0 )
		{
			if ( !(dleafs[i].contents & CONTENTS_SOLID) )
			{
				Msg("Bad leaf ambient for leaf %d\n", i );
			}

			int refLeaf = NearestNeighborWithLight(i);
			g_pLeafAmbientIndex->Element(i).ambientSampleCount = 0;
			g_pLeafAmbientIndex->Element(i).firstAmbientSample = refLeaf;
		}
	}
	Msg("done\n");
}
Beispiel #17
0
// This is the only public entry to this file.
// The global data touched in the file is:
// from bsplib.h:
//		g_pPhysCollide		: This is an output from this file.
//		g_PhysCollideSize	: This is set in this file.
//		g_numdispinfo		: This is an input to this file.
//		g_dispinfo			: This is an input to this file.
//		numnodewaterdata	: This is an output from this file.
//		dleafwaterdata		: This is an output from this file.
// from vbsp.h:
//		g_SurfaceProperties : This is an input to this file.
void EmitPhysCollision()
{
	ClearLeafWaterData();
	
	CreateInterfaceFn physicsFactory = GetPhysicsFactory();
	if ( physicsFactory )
	{
		physcollision = (IPhysicsCollision *)physicsFactory( VPHYSICS_COLLISION_INTERFACE_VERSION, NULL );
	}

	if ( !physcollision )
	{
		Warning("!!! WARNING: Can't build collision data!\n" );
		return;
	}

	CUtlVector<CPhysCollisionEntry *> collisionList[MAX_MAP_MODELS];
	CTextBuffer *pTextBuffer[MAX_MAP_MODELS];

	int physModelCount = 0, totalSize = 0;

	int start = Plat_FloatTime();

	Msg("Building Physics collision data...\n" );

	int i, j;
	for ( i = 0; i < nummodels; i++ )
	{
		// Build a list of collision models for this brush model section
		if ( i == 0 )
		{
			// world is the only model that processes water separately.
			// other brushes are assumed to be completely solid or completely liquid
			BuildWorldPhysModel( collisionList[i], NO_SHRINK, VPHYSICS_MERGE);
		}
		else
		{
			ConvertModelToPhysCollide( collisionList[i], i, MASK_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|MASK_WATER, VPHYSICS_SHRINK, VPHYSICS_MERGE );
		}
		
		pTextBuffer[i] = NULL;
		if ( !collisionList[i].Count() )
			continue;

		// if we've got collision models, write their script for processing in the game
		pTextBuffer[i] = new CTextBuffer;
		for ( j = 0; j < collisionList[i].Count(); j++ )
		{
			// dump a text file for visualization
			if ( dumpcollide )
			{
				collisionList[i][j]->DumpCollide( pTextBuffer[i], i, j );
			}
			// each model knows how to write its script
			collisionList[i][j]->WriteToTextBuffer( pTextBuffer[i], i, j );
			// total up the binary section's size
			totalSize += collisionList[i][j]->GetCollisionBinarySize() + sizeof(int);
		}

		// These sections only appear in the world's collision text
		if ( i == 0 )
		{
			if ( !g_bNoVirtualMesh && physcollision->SupportsVirtualMesh() )
			{
				pTextBuffer[i]->WriteText("virtualterrain {}\n");
			}
			if ( s_WorldPropList.Count() )
			{
				pTextBuffer[i]->WriteText( "materialtable {\n" );
				for ( j = 0; j < s_WorldPropList.Count(); j++ )
				{
					int propIndex = s_WorldPropList[j];
					if ( propIndex < 0 )
					{
						pTextBuffer[i]->WriteIntKey( "default", j+1 );
					}
					else
					{
						pTextBuffer[i]->WriteIntKey( physprops->GetPropName( propIndex ), j+1 );
					}
				}
				pTextBuffer[i]->WriteText( "}\n" );
			}
		}

		pTextBuffer[i]->Terminate();

		// total lump size includes the text buffers (scripts)
		totalSize += pTextBuffer[i]->GetSize();

		physModelCount++;
	}

	//  add one for tail of list marker
	physModelCount++;	

	// DWORD align the lump because AddLump assumes that it is DWORD aligned.
	byte *ptr ;
	g_PhysCollideSize = totalSize + (physModelCount * sizeof(dphysmodel_t));
	g_pPhysCollide = (byte *)malloc(( g_PhysCollideSize + 3 ) & ~3 );
	memset( g_pPhysCollide, 0, g_PhysCollideSize );
	ptr = g_pPhysCollide;

	for ( i = 0; i < nummodels; i++ )
	{
		if ( pTextBuffer[i] )
		{
			int j;

			dphysmodel_t model;

			model.modelIndex = i;
			model.solidCount = collisionList[i].Count();
			model.dataSize = sizeof(int) * model.solidCount;

			for ( j = 0; j < model.solidCount; j++ )
			{
				model.dataSize += collisionList[i][j]->GetCollisionBinarySize();
			}
			model.keydataSize = pTextBuffer[i]->GetSize();

			// store the header
			memcpy( ptr, &model, sizeof(model) );
			ptr += sizeof(model);

			for ( j = 0; j < model.solidCount; j++ )
			{
				int collideSize = collisionList[i][j]->GetCollisionBinarySize();

				// write size
				memcpy( ptr, &collideSize, sizeof(int) );
				ptr += sizeof(int);

				// now write the collision model
				collisionList[i][j]->WriteCollisionBinary( reinterpret_cast<char *>(ptr) );
				ptr += collideSize;
			}

			memcpy( ptr, pTextBuffer[i]->GetData(), pTextBuffer[i]->GetSize() );
			ptr += pTextBuffer[i]->GetSize();
		}

		delete pTextBuffer[i];
	}

	dphysmodel_t model;

	// Mark end of list
	model.modelIndex = -1;
	model.dataSize = -1;
	model.keydataSize = 0;
	model.solidCount = 0;
	memcpy( ptr, &model, sizeof(model) );
	ptr += sizeof(model);
	Assert( (ptr-g_pPhysCollide) == g_PhysCollideSize);
	Msg("done (%d) (%d bytes)\n", (int)(Plat_FloatTime() - start), g_PhysCollideSize );

	// UNDONE: Collision models (collisionList) memory leak!
}
void PhonemeEditor::CloseCaption_MergeSelected( void )
{
	CountSelected();
	if ( m_nSelectedPhraseCount < 2 )
	{
		Con_Printf( "CloseCaption_MergeSelected:  requires 2 or more selected phrases\n" );
		return;
	}

	if ( !CloseCaption_AreSelectedPhrasesContiguous() )
	{
		Con_Printf( "CloseCaption_MergeSelected:  selected phrases must be contiguous\n" );
		return;
	}

	SetDirty( true );

	PushUndo();

	CUtlVector< CCloseCaptionPhrase * > selected;

	float beststart = 100000.0f;
	float bestend = -100000.0f;

	int c = m_Tags.GetCloseCaptionPhraseCount( CC_ENGLISH );
	int i;
	int insertslot = c -1;

	// Walk backwards and remove
	for ( i = c - 1; i >= 0; i-- )
	{
		CCloseCaptionPhrase *phrase = m_Tags.GetCloseCaptionPhrase( CC_ENGLISH, i );
		if ( !phrase || !phrase->GetSelected() )
			continue;

		if ( phrase->GetStartTime() < beststart )
		{
			beststart = phrase->GetStartTime();
		}
		if ( phrase->GetEndTime() > bestend )
		{
			bestend = phrase->GetEndTime();
		}

		selected.AddToHead( new CCloseCaptionPhrase( *phrase ) );

		// Remember the earliest slot
		if ( i < insertslot )
		{
			insertslot = i;
		}

		m_Tags.RemoveCloseCaptionPhrase( CC_ENGLISH, i );
	}

	if ( selected.Count() <= 0 )
		return;

	CCloseCaptionPhrase *newphrase = new CCloseCaptionPhrase( selected[ 0 ]->GetStream() );
	Assert( newphrase );
	wchar_t sz[ 4096 ];
	delete selected[ 0 ];
	for ( i = 1; i < selected.Count(); i++ )
	{
		_snwprintf( sz, sizeof( sz ), newphrase->GetStream() );
		// Phrases don't have leading/trailing spaces so it should be safe to just append a space here
		wcscat( sz, L" " );
		wcscat( sz, selected[ i ]->GetStream() );
		newphrase->SetStream( sz );
		delete selected[ i ];
	}
	selected.RemoveAll();

	m_Tags.InsertCloseCaptionPhraseAtIndex( CC_ENGLISH, newphrase, insertslot );
	newphrase->SetSelected( true );
	newphrase->SetStartTime( beststart );
	newphrase->SetEndTime( bestend );

	PushRedo();

	redraw();
}
//-----------------------------------------------------------------------------
// Purpose: Hook for the sound system to tell us when a sound's been played
//-----------------------------------------------------------------------------
MicrophoneResult_t CEnvMicrophone::SoundPlayed( int entindex, const char *soundname, soundlevel_t soundlevel, float flVolume, int iFlags, int iPitch, const Vector *pOrigin, float soundtime, CUtlVector< Vector >& soundorigins )
{
	if ( m_bAvoidFeedback )
		return MicrophoneResult_Ok;

	// Don't hear sounds that have already been heard by a microphone to avoid feedback!
	if ( iFlags & SND_SPEAKER )
		return MicrophoneResult_Ok;

#ifdef DEBUG_MICROPHONE
	Msg("%s heard %s: ", STRING(GetEntityName()), soundname );
#endif

	if ( !CanHearSound( entindex, soundlevel, flVolume, pOrigin ) )
		return MicrophoneResult_Ok;

	// We've heard it. Play it out our speaker. If our speaker's gone away, we're done.
	if ( !m_hSpeaker )
	{
		// First time, find our speaker. Done here, because finding it in Activate() wouldn't
		// find players, and we need to be able to specify !player for a speaker.
		if ( m_iszSpeakerName != NULL_STRING )
		{
			m_hSpeaker = gEntList.FindEntityByName(NULL, STRING(m_iszSpeakerName) );

			if ( !m_hSpeaker )
			{
				Warning( "EnvMicrophone %s specifies a non-existent speaker name: %s\n", STRING(GetEntityName()), STRING(m_iszSpeakerName) );
				m_iszSpeakerName = NULL_STRING;
			}
		}

		if ( !m_hSpeaker )
		{
			return MicrophoneResult_Remove;
		}
	}

	m_bAvoidFeedback = true;

	// Add the speaker flag. Detected at playback and applies the speaker filter.
	iFlags |= SND_SPEAKER;
	CPASAttenuationFilter filter( m_hSpeaker );

	EmitSound_t ep;
	ep.m_nChannel = CHAN_STATIC;
	ep.m_pSoundName = soundname;
	ep.m_flVolume = flVolume;
	ep.m_SoundLevel = soundlevel;
	ep.m_nFlags = iFlags;
	ep.m_nPitch = iPitch;
	ep.m_pOrigin = &m_hSpeaker->GetAbsOrigin();
	ep.m_flSoundTime = soundtime;
	ep.m_nSpeakerEntity = entindex;

	CBaseEntity::EmitSound( filter, m_hSpeaker->entindex(), ep );

	Q_strncpy( m_szLastSound, soundname, sizeof(m_szLastSound) );
	m_OnRoutedSound.FireOutput( this, this, 0 );

	m_bAvoidFeedback = false;

	// Copy emitted origin to soundorigins array
	for ( int i = 0; i < ep.m_UtlVecSoundOrigin.Count(); ++i )
	{
		soundorigins.AddToTail( ep.m_UtlVecSoundOrigin[ i ] );
	}

	// Do we want to allow the original sound to play?
	if ( m_spawnflags & SF_MICROPHONE_SWALLOW_ROUTED_SOUNDS )
	{
		return MicrophoneResult_Swallow;
	}

	return MicrophoneResult_Ok;
}
Beispiel #20
0
int	CVGuiScreenEnumerator::GetScreenCount()
{
    return m_VguiScreens.Count();
}
void CNotifyList::LevelShutdownPreEntity( void )
{
	gEntList.RemoveListenerEntity( this );
	m_notifyList.Purge();
}
Beispiel #22
0
void CASWMissionChooserNPCs::PushEncountersApart( CMapLayout *pLayout )
{
	// get a list of valid rooms
	int iRooms = pLayout->m_PlacedRooms.Count();
	CUtlVector<CRoom*> candidates;
	float flTotalWeight = 0;
	for ( int i = 0; i < iRooms; i++ )
	{
		CRoom *pRoom = pLayout->m_PlacedRooms[i];
		if ( pRoom->GetSpawnWeight() > 0
			&& !pRoom->m_pRoomTemplate->IsEscapeRoom() 
			&& !pRoom->m_pRoomTemplate->IsStartRoom() 
			&& !pRoom->m_pRoomTemplate->IsBorderRoom() )
		{
			// skip 1x1 rooms
			if ( pRoom->m_pRoomTemplate->GetTilesX() * pRoom->m_pRoomTemplate->GetTilesY() <= 1 )
				continue;

			flTotalWeight += pRoom->GetSpawnWeight();
			candidates.AddToTail( pRoom );
		}
	}

	// push the encounters apart 
	int iSteps = 6;
	for ( int i = 0; i < iSteps; i++ )
	{
		int iEncounters = pLayout->m_Encounters.Count();
		for ( int e = 0; e < iEncounters; e++ )
		{
			Vector vecPush = vec3_origin;
			CASW_Encounter *pEncounter = pLayout->m_Encounters[ e ];
			// accumulate a force from all other nearby encounters
			for ( int k = 0; k < iEncounters; k++ )
			{
				if ( e == k )
					continue;
				CASW_Encounter *pOther = pLayout->m_Encounters[ k ];
				Vector dir = pEncounter->GetEncounterPosition() - pOther->GetEncounterPosition();	// direction from other to us
				float dist = dir.NormalizeInPlace();
				float flMinDistance = asw_encounters_distance_min.GetFloat() + pEncounter->GetEncounterRadius() + pOther->GetEncounterRadius();
				if ( dist < flMinDistance )
				{
					float flPush = flMinDistance - dist;		// push us exactly out of the min
					vecPush += dir * flPush;
				}
			}
			pEncounter->SetEncounterPosition( pEncounter->GetEncounterPosition() + vecPush );

			// clamp encounters to room bounds
			CRoom *pClosestRoom = NULL;
			float flClosestDist = 65535.0f;
			bool bWithinARoom = false;
			Vector pos = pEncounter->GetEncounterPosition();
			for ( int k = 0; k < candidates.Count(); k++ )
			{
				CRoom *pRoom = candidates[k];
				Vector vecMins, vecMaxs;
				pRoom->GetWorldBounds( &vecMins, &vecMaxs );
				if ( pos.x >= vecMins.x && pos.x <= vecMaxs.x
								&& pos.y >= vecMins.y && pos.y <= vecMaxs.y )
				{
					bWithinARoom = true;
					break;
				}
				Vector vecMiddle = ( vecMins + vecMaxs ) * 0.5f;
				float flDist = vecMiddle.DistTo( pos );
				if ( flDist < flClosestDist )
				{
					flClosestDist = flDist;
					pClosestRoom = pRoom;
				}
			}
			// if encounter wasn't in any room, then clamp to the closest
			if ( !bWithinARoom && pClosestRoom )
			{
				Vector vecMins, vecMaxs;
				pClosestRoom->GetWorldBounds( &vecMins, &vecMaxs );
				pos.x = clamp( pos.x, vecMins.x, vecMaxs.x );
				pos.y = clamp( pos.y, vecMins.y, vecMaxs.y );
				pEncounter->SetEncounterPosition( pos );
			}

			/*
			// put encounter in the center of its room
			for ( int k = 0; k < candidates.Count(); k++ )
			{
				CRoom *pRoom = candidates[k];
				Vector vecMins, vecMaxs;
				pRoom->GetWorldBounds( &vecMins, &vecMaxs );
				if ( pos.x >= vecMins.x && pos.x <= vecMaxs.x
					&& pos.y >= vecMins.y && pos.y <= vecMaxs.y )
				{
					Vector mid = ( vecMins + vecMaxs ) * 0.5f;
					mid.z = 0;
					pEncounter->SetEncounterPosition ( mid );
					break;
				}
			}
			*/
		}
	}
}
	void StartGroupingSounds()
	{
		Assert( g_GroupedSounds.Count() == 0 );
		SetImpactSoundRoute( ShotgunImpactSoundGroup );
	}
Beispiel #24
0
void CASWMissionChooserNPCs::InitFixedSpawns( CLayoutSystem *pLayoutSystem, CMapLayout *pLayout )
{
	// init the spawn set for this mission
	KeyValues *pGenerationOptions = pLayout->GetGenerationOptions();
	if ( !pGenerationOptions )
	{
		Warning( "Error placed fixed alien spawns, no generation options in this layout." );
		return;
	}

	bool bChosenSpawnSet = false;
	const char *szNamedSpawnSet = pGenerationOptions->GetString( "AlienSpawnSet" );
	if ( szNamedSpawnSet && szNamedSpawnSet[0] )
	{
		bChosenSpawnSet = SpawnSelection()->SetCurrentSpawnSet( szNamedSpawnSet );
	}

	if ( !bChosenSpawnSet )
	{
		SpawnSelection()->SetCurrentSpawnSet( pGenerationOptions->GetInt( "Difficulty", 5 ) );
	}

	// if we have any rooms with the alien encounter tag, then just use those for fixed spawn locations
	bool bAlienEncounterTag = false;
	int iRooms = pLayout->m_PlacedRooms.Count();
	for ( int i = 0; i < iRooms; i++ )
	{
		CRoom *pRoom = pLayout->m_PlacedRooms[i];
		if ( pRoom && pRoom->m_pRoomTemplate && pRoom->m_pRoomTemplate->HasTag( "AlienEncounter" ) )
		{
			bAlienEncounterTag = true;

			CASW_Encounter *pEncounter = new CASW_Encounter();

			// pick a random spot in this room
			Vector vecWorldMins, vecWorldMaxs;
			pRoom->GetWorldBounds( &vecWorldMins, &vecWorldMaxs );
			Vector vecPos = vecWorldMins + pLayoutSystem->GetRandomFloat( 0, 1 ) * ( vecWorldMaxs - vecWorldMins );
			vecPos.z = 0;
			pEncounter->SetEncounterPosition( vecPos );
			pEncounter->SetEncounterRadius( pLayoutSystem->GetRandomFloat( asw_encounter_radius_min.GetFloat(), asw_encounter_radius_max.GetFloat() ) );

			// add spawn defs
			// TODO: more spawns in bigger rooms? or rooms with higher weights?
			int iSpawnsPerEncounter = pLayoutSystem->GetRandomInt( CurrentSpawnSet()->GetMinSpawnsPerEncounter(), CurrentSpawnSet()->GetMaxSpawnsPerEncounter() );
			for ( int i = 0; i < iSpawnsPerEncounter; i++ )
			{
				CASW_Spawn_Definition* pSpawnDef = CurrentSpawnSet()->GetSpawnDef( ASW_NPC_SPAWN_TYPE_FIXED );
				if ( !pSpawnDef )
					continue;
				pEncounter->AddSpawnDef( pSpawnDef );
			}

			pLayout->m_Encounters.AddToTail( pEncounter );
		}
	}

	if ( bAlienEncounterTag )
	{
		pLayout->MarkEncounterRooms();
		return;
	}

	// find area of the mission
	int iTotalArea = 0;
	for ( int i = 0; i < iRooms; i++ )
	{
		CRoom *pRoom = pLayout->m_PlacedRooms[i];
		iTotalArea += ( pRoom->m_pRoomTemplate->GetTilesX() * ASW_TILE_SIZE ) * ( pRoom->m_pRoomTemplate->GetTilesY() * ASW_TILE_SIZE );
	}

	// decide how many encounters we want
	int iEncounters = pLayoutSystem->GetRandomInt( CurrentSpawnSet()->GetMinEncounters(), CurrentSpawnSet()->GetMaxEncounters() );

	// distance between encounters
	//float flMinDistance = asw_encounters_distance_min.GetFloat();

	// randomly pick rooms for the encounters to be in, using the room weights
	CUtlVector<CRoom*> candidates;
	float flTotalWeight = 0;
	for ( int i = 0; i < iRooms; i++ )
	{
		CRoom *pRoom = pLayout->m_PlacedRooms[i];
		if ( pRoom->GetSpawnWeight() > 0
				&& !pRoom->m_pRoomTemplate->IsEscapeRoom() 
				&& !pRoom->m_pRoomTemplate->IsStartRoom() 
				&& !pRoom->m_pRoomTemplate->IsBorderRoom() )
		{
			flTotalWeight += pRoom->GetSpawnWeight();
			candidates.AddToTail( pRoom );
		}
	}

	for ( int e = 0; e < iEncounters; e++ )
	{
		float flChosen = pLayoutSystem->GetRandomFloat( 0, flTotalWeight );
		CRoom *pChosenRoom = NULL;
		for ( int i = 0; i < candidates.Count(); i++ )
		{
			CRoom *pRoom = candidates[i];
			flChosen -= pRoom->GetSpawnWeight();
			if ( flChosen <= 0 )
			{
				pChosenRoom = pRoom;
				break;
			}
		}

		if ( !pChosenRoom )
			continue;

		CASW_Encounter *pEncounter = new CASW_Encounter();

		// pick a random spot in this room
		Vector vecWorldMins, vecWorldMaxs;
		pChosenRoom->GetWorldBounds( &vecWorldMins, &vecWorldMaxs );
		//Vector vecPos = vecWorldMins + pLayoutSystem->GetRandomFloat( 0, 1 ) * ( vecWorldMaxs - vecWorldMins );
		Vector vecPos = ( vecWorldMins + vecWorldMaxs ) * 0.5f; // center of the room
		vecPos.z = 0;
		pEncounter->SetEncounterPosition( vecPos );
		pEncounter->SetEncounterRadius( pLayoutSystem->GetRandomFloat( asw_encounter_radius_min.GetFloat(), asw_encounter_radius_max.GetFloat() ) );

		// add spawn defs
		// TODO: more spawns in bigger rooms? or rooms with higher weights?
		int iSpawnsPerEncounter = pLayoutSystem->GetRandomInt( CurrentSpawnSet()->GetMinSpawnsPerEncounter(), CurrentSpawnSet()->GetMaxSpawnsPerEncounter() );
		for ( int i = 0; i < iSpawnsPerEncounter; i++ )
		{
			CASW_Spawn_Definition* pSpawnDef = CurrentSpawnSet()->GetSpawnDef( ASW_NPC_SPAWN_TYPE_FIXED );
			if ( !pSpawnDef )
				continue;
			pEncounter->AddSpawnDef( pSpawnDef );
		}

		pLayout->m_Encounters.AddToTail( pEncounter );
	}

	PushEncountersApart( pLayout );
	pLayout->MarkEncounterRooms();
}
void CMoveHelperServer::ResetTouchList( void )
{
	m_TouchList.RemoveAll();
}
Beispiel #26
0
// Creates a list of watermodel_t for later processing by EmitPhysCollision
void EmitWaterVolumesForBSP( dmodel_t *pModel, node_t *node )
{
	CUtlVector<node_t *> leafListAnyWater;
	// build the list of all leaves containing water
	EnumLeaves_r( leafListAnyWater, node, MASK_WATER );

	// make a sorted list to flood fill
	CUtlVector<waterleaf_t>	list;
	
	int i;
	for ( i = 0; i < leafListAnyWater.Count(); i++ )
	{
		waterleaf_t waterLeaf;
		BuildWaterLeaf( leafListAnyWater[i], waterLeaf );
		InsertSortWaterLeaf( list, waterLeaf );
	}

	leafbitarray_t visited;
	CUtlVector<node_t *> waterAreaList;
	for ( i = 0; i < list.Count(); i++ )
	{
		Flood_FindConnectedWaterVolumes_r( waterAreaList, list[i].pNode, list[i], visited );

		// did we find a list of leaves connected to this one?
		// remember the list is sorted, so this one may have been attached to a previous
		// leaf.  So it could have nothing hanging off of it.
		if ( waterAreaList.Count() )
		{
			// yes, emit a watermodel
			watermodel_t tmp;
			tmp.modelIndex = nummodels;
			tmp.contents = list[i].pNode->contents;
			tmp.waterLeafData = list[i];
			tmp.firstWaterLeafIndex = g_WaterLeafList.Count();
			tmp.waterLeafCount = waterAreaList.Count();
			
			float waterDepth = tmp.waterLeafData.surfaceDist - tmp.waterLeafData.minZ;
			if ( tmp.waterLeafData.surfaceTexInfo < 0 )
			{
				// the map has probably leaked in this case, but output something anyway.
				Assert(list[i].pNode->planenum == PLANENUM_LEAF);
				tmp.waterLeafData.surfaceTexInfo = FirstWaterTexinfo( list[i].pNode->brushlist, tmp.contents );
			}
			tmp.depthTexinfo = FindOrCreateWaterTexInfo( &texinfo[ tmp.waterLeafData.surfaceTexInfo ], waterDepth );
			tmp.fogVolumeIndex = FindOrCreateLeafWaterData( tmp.waterLeafData.surfaceDist, tmp.waterLeafData.minZ, tmp.waterLeafData.surfaceTexInfo );

			for ( int j = 0; j < waterAreaList.Count(); j++ )
			{
				g_WaterLeafList.AddToTail( waterAreaList[j]->diskId );
			}
			waterAreaList.RemoveAll();
			g_WaterModels.AddToTail( tmp );
		}
	}

	WriteFogVolumeIDs( pModel );
}
int CBuildModeDialogMgr::Count() const
{
	return m_vecBuildDialogs.Count();
}
Beispiel #28
0
static void ConvertWaterModelToPhysCollide( CUtlVector<CPhysCollisionEntry *> &collisionList, int modelIndex, 
										    float shrinkSize, float mergeTolerance )
{
	dmodel_t *pModel = dmodels + modelIndex;

	for ( int i = 0; i < g_WaterModels.Count(); i++ )
	{
		watermodel_t &waterModel = g_WaterModels[i];
		if ( waterModel.modelIndex != modelIndex )
			continue;

		CPlaneList planes( shrinkSize, mergeTolerance );
		int firstLeaf = waterModel.firstWaterLeafIndex;
		planes.m_contentsMask = waterModel.contents;
		
		// push all of the leaves into the collision list
		for ( int j = 0; j < waterModel.waterLeafCount; j++ )
		{
			int leafIndex = g_WaterLeafList[firstLeaf + j];

			dleaf_t *pLeaf = dleafs + leafIndex;
			// fixup waterdata
			pLeaf->leafWaterDataID = waterModel.fogVolumeIndex;
			planes.ReferenceLeaf( leafIndex );
		}
	
		// visit the referenced leaves that belong to this model
		VisitLeaves_r( planes, pModel->headnode );

		// Now add the brushes from those leaves as convex

		// BUGBUG: NOTE: If your map has a brush that crosses the surface, it will be added to two water
		// volumes.  This only happens with connected water volumes with multiple surface heights
		// UNDONE: Right now map makers must cut such brushes.  It could be automatically cut by adding the
		// surface plane to the list for each brush before calling ConvexFromPlanes()
		planes.AddBrushes();

		int count = planes.m_convex.Count();
		if ( !count )
			continue;

		// Save off the plane of the surface for this group as well as the collision model
		// for all convex objects in the group.
		CPhysCollide *pCollide = physcollision->ConvertConvexToCollide( planes.m_convex.Base(), count );
		if ( pCollide )
		{
			int waterSurfaceTexInfoID = -1;
			// use defaults
			const char *pSurfaceProp = "water";
			float damping = 0.01;
			if ( waterSurfaceTexInfoID >= 0 )
			{
				// material override
				int texdata = texinfo[waterSurfaceTexInfoID].texdata;
				int prop = g_SurfaceProperties[texdata];
				pSurfaceProp = physprops->GetPropName( prop );
			}

			if ( !waterModel.waterLeafData.hasSurface )
			{
				waterModel.waterLeafData.surfaceNormal.Init( 0,0,1 );
				Vector top = physcollision->CollideGetExtent( pCollide, vec3_origin, vec3_angle, waterModel.waterLeafData.surfaceNormal );
				waterModel.waterLeafData.surfaceDist = top.z;
			}
			CPhysCollisionEntryFluid *pCollisionEntryFuild = new CPhysCollisionEntryFluid( pCollide, 
				pSurfaceProp, damping, waterModel.waterLeafData.surfaceNormal, waterModel.waterLeafData.surfaceDist, waterModel.contents );
			collisionList.AddToTail( pCollisionEntryFuild );
		}
	}
}
int main(int argc, char* argv[])
{
	SpewOutputFunc( MySpewFunc );

	// Figure out a random port to use.
	CCycleCount cnt;
	cnt.Sample();
	CUniformRandomStream randomStream;
	randomStream.SetSeed( cnt.GetMicroseconds() );
	int iPort = randomStream.RandomInt( 20000, 30000 );


	g_ClientPacketEvent.Init( false, false );

	
	// Setup the "server".
	CHandlerCreator_Server serverHandler;
	CIPAddr addr( 127, 0, 0, 1, iPort );

	ITCPConnectSocket *pListener = ThreadedTCP_CreateListener( 
		&serverHandler,
		(unsigned short)iPort );

	
	// Setup the "client".
	CHandlerCreator_Client clientCreator;
	ITCPConnectSocket *pConnector = ThreadedTCP_CreateConnector( 
		CIPAddr( 127, 0, 0, 1, iPort ),
		CIPAddr(),
		&clientCreator );


	// Wait for them to connect.
	while ( !g_pClientSocket )
	{
		if ( !pConnector->Update( &g_pClientSocket ) )
		{
			Error( "Error in client connector!\n" );
		}
	}
	pConnector->Release();


	while ( !g_pServerSocket )
	{
		if ( !pListener->Update( &g_pServerSocket ) )
			Error( "Error in server connector!\n" );
	}
	pListener->Release();


	// Send some data.
	__int64 totalBytes = 0;
	CCycleCount startTime;
	int iPacket = 1;

	startTime.Sample();
	CUtlVector<char> buf;

	while ( (GetAsyncKeyState( VK_SHIFT ) & 0x8000) == 0 )
	{
		int size = randomStream.RandomInt( 1024*0, 1024*320 );
		if ( buf.Count() < size )
			buf.SetSize( size );

		if ( g_pClientSocket->Send( buf.Base(), size ) )
		{
			// Server receives the data and echoes it back. Verify that the data is good.
			WaitForSingleObject( g_ClientPacketEvent.GetEventHandle(), INFINITE );
			Assert( memcmp( g_ClientPacket.Base(), buf.Base(), size ) == 0 );

			totalBytes += size;
			CCycleCount curTime, elapsed;
			curTime.Sample();
			CCycleCount::Sub( curTime, startTime, elapsed );
			double flSeconds = elapsed.GetSeconds();
			Msg( "Packet %d, %d bytes, %dk/sec\n", iPacket++, size, (int)(((totalBytes+511)/1024) / flSeconds) );
		}
	}
	
	g_pClientSocket->Release();
	g_pServerSocket->Release();
	return 0;
}
void jTerm_destination(j_compress_ptr cinfo)
{
	jOut.SetCountNonDestructively(jOut.Count() - cinfo->dest->free_in_buffer);
}