Exemplo n.º 1
0
/*virtual*/ void WBPELookup::Evaluate( const WBParamEvaluator::SPEContext& Context, WBParamEvaluator::SEvaluatedParam& EvaluatedParam ) const
{
	ASSERT( Context.m_Entity );

	WBCompPEMap* const PEMap = GET_WBCOMP( Context.m_Entity, PEMap );
	if( !PEMap )
	{
		WARNDESC( "No PEMap for PE lookup." );
		return;
	}

	WBPE* const PE = PEMap->GetPE( m_Key );
	if( !PE )
	{
#if BUILD_DEV
		if( m_WarnFailure )
		{
			WARNDESC( "PE lookup found nothing in PEMap." );
		}
#endif
		return;
	}

	PE->Evaluate( Context, EvaluatedParam );
}
Exemplo n.º 2
0
Surface::Surface( const IDataStream& Stream, ESurfaceFileType FileType )
    :	m_Width( 0 )
    ,	m_Height( 0 )
    ,	m_Stride( 0 )
    ,	m_Padding( 0 )
#if BUILD_WINDOWS_NO_SDL
    ,	m_hDC( NULL )
    ,	m_BMP( NULL )
    ,	m_OldBMP( NULL )
#endif
    ,	m_pPixels( NULL )
    ,	m_BitmapInfo()
    ,	m_ViewportLeft( 0 )
    ,	m_ViewportTop( 0 )
    ,	m_ViewportRight( 0 )
    ,	m_ViewportBottom( 0 )
{
    // Load depending on extension
    if( FileType == ESFT_BMP )
    {
        LoadBMP( Stream );
    }
    else if( FileType == ESFT_TGA )
    {
        LoadTGA( Stream );
    }
    else
    {
        WARNDESC( "Unknown file type constructing Surface." );
    }
}
Exemplo n.º 3
0
/*static*/ D3DFORMAT D3D9RenderTarget::GetD3DFormat( const ERenderTargetFormat Format )
{
	switch( Format )
	{
	case ERTF_Unknown:
		return D3DFMT_UNKNOWN;
	case ERTF_X8R8G8B8:
		return D3DFMT_X8R8G8B8;
	case ERTF_A8R8G8B8:
		return D3DFMT_A8R8G8B8;
	case ERTF_A16B16G16R16:
		return D3DFMT_A16B16G16R16;
	case ERTF_A16B16G16R16F:
		return D3DFMT_A16B16G16R16F;
	case ERTF_A32B32G32R32F:
		return D3DFMT_A32B32G32R32F;
	case ERTF_R32F:
		return D3DFMT_R32F;
	case ERTF_D24S8:
		return D3DFMT_D24S8;
	default:
		WARNDESC( "D3D texture format not matched" );
		return D3DFMT_UNKNOWN;
	}
}
Exemplo n.º 4
0
void WBCompRodinBehaviorTree::Start(RodinBTNode* pNode,
                                    RodinBTNode* pParentNode /*= NULL*/) {
  ASSERT(pNode);
  ASSERT(!pNode->m_IsSleeping);

#if BUILD_DEBUG
  // TODO: Make sure this node isn't already in the scheduled array.
  // While it is valid for two nodes to have a shared child node, it is never
  // valid for them
  // both to be running that child simultaneously (because the node only has one
  // state).
  // 12 Apr 2013: Actually, I don't think that *is* a valid use case; two child
  // nodes can
  // share the same config definition, but they'll be uniquely constructed for
  // each parent.)
  uint NodeIndex = 0;
  if (FindScheduledNode(pNode, NodeIndex)) {
    WARNDESC("WBCompRodinBehaviorTree::Start: Node pair is already scheduled!");
  }
#endif

  SScheduledNode ScheduledNode;
  ScheduledNode.m_Node = pNode;
  ScheduledNode.m_ParentNode = pParentNode;

  m_ScheduledNodes.PushBack(ScheduledNode);

  pNode->OnStart();
}
Exemplo n.º 5
0
void ReverseHash::RegisterHash( const HashedString& Hash, const SimpleString& String )
{
	if( gReverseHashEnabled )
	{
#if BUILD_DEV
		const Map<HashedString, SimpleString>::Iterator HashIter = gReverseHashMap.Search( Hash );
		if( HashIter.IsValid() )
		{
			const SimpleString ExistingString = HashIter.GetValue();
			if( ExistingString != String )
			{
				PRINTF( "ReverseHash: Hash collision detected between \"%s\" and \"%s\"!\n", ExistingString.CStr(), String.CStr() );
			}
		}
#endif

		gReverseHashMap[ Hash ] = String;
	}
	else
	{
		// Even though it's safe, this shouldn't be called if the reverse hash isn't enabled,
		// because it could be wasting time doing the SimpleString construction.
		WARNDESC( "ReverseHash: Not enabled." );
	}
}
Exemplo n.º 6
0
/*static*/ WBComponent* WBComponent::Create( const HashedString& TypeName, const SimpleString& DefinitionName, WBEntity* const pEntity )
{
	// NOTE: This supports nulling out a component in a mod by using an empty string.
	if( DefinitionName == "" )
	{
		return NULL;
	}

	FactoryMap::Iterator FactoryIter = m_WBCompFactoryMap.Search( TypeName );
	if( FactoryIter.IsNull() )
	{
		PRINTF( "Invalid type requested for WBComponent %s.\n", DefinitionName.CStr() );
		WARNDESC( "Invalid WBComponent type requested." );
		return NULL;
	}

	WBCompFactoryFunc pWBCompFactory = ( *FactoryIter );
	ASSERT( pWBCompFactory );
	WBComponent* pNewComponent = pWBCompFactory();
	ASSERT( pNewComponent );

	pNewComponent->SetEntity( pEntity );
	pNewComponent->Initialize();
	pNewComponent->InitializeFromDefinition( DefinitionName );

	return pNewComponent;
}
Exemplo n.º 7
0
RodinBTNode* RodinBTNodeFactory::Create(
    const SimpleString& DefinitionName,
    WBCompRodinBehaviorTree* const pBehaviorTree) {
  STATICHASH(NodeType);
  MAKEHASH(DefinitionName);
  HashedString NodeType =
      ConfigManager::GetHash(sNodeType, "", sDefinitionName);

  Map<HashedString, RodinBTNodeFactoryFunc>::Iterator FactoryIter =
      sFactoryFuncMap.Search(NodeType);
  if (FactoryIter.IsNull()) {
    PRINTF("Invalid type requested for RodinBTNode %s.\n",
           DefinitionName.CStr());
    WARNDESC("Invalid RodinBTNode type requested.");
    return nullptr;
  }

  RodinBTNodeFactoryFunc pFactory = (*FactoryIter);
  ASSERT(pFactory);

  RodinBTNode* pNewNode = pFactory();
  ASSERT(pNewNode);

  pNewNode->m_DefinitionName = DefinitionName;
  pNewNode->m_BehaviorTree = pBehaviorTree;
  pNewNode->InitializeFromDefinition(DefinitionName);

  return pNewNode;
}
Exemplo n.º 8
0
// If a localized month is needed, pass the return
// value to ConfigManager::GetLocalizedString
SimpleString TimeDate::GetMonthName(int Month) {
  switch (Month) {
    case 0:
      return "January";
    case 1:
      return "February";
    case 2:
      return "March";
    case 3:
      return "April";
    case 4:
      return "May";
    case 5:
      return "June";
    case 6:
      return "July";
    case 7:
      return "August";
    case 8:
      return "September";
    case 9:
      return "October";
    case 10:
      return "November";
    case 11:
      return "December";
    default:
      WARNDESC("Invalid month.");
      return "";
  }
}
Exemplo n.º 9
0
void WBCompRodinBehaviorTree::Stop(RodinBTNode* pNode) {
  ASSERT(pNode);

  uint NodeIndex = 0;
  if (FindScheduledNode(pNode, NodeIndex)) {
    Finish(NodeIndex, RodinBTNode::ETS_Fail);
  } else {
    WARNDESC("Given task was not found in the scheduler.");
  }
}
Exemplo n.º 10
0
void ConfigManager::Save( const IDataStream& Stream )
{
	Stream.WriteUInt32( 'FCCD' );						// Magic ID: DCCF
	Stream.WriteUInt32( GetInstance()->m_Vars.Size() );	// Number of contexts

	const Map< HashedString, VarMap >& Vars = GetInstance()->m_Vars;
	FOR_EACH_MAP( ContextIterator, Vars, HashedString, VarMap )
	{
		const HashedString& ContextKey = ContextIterator.GetKey();
		const VarMap& VarMap = ContextIterator.GetValue();

		Stream.WriteUInt32( ContextKey.GetHash() );	// Hashed context name
		Stream.WriteUInt32( VarMap.Size() );		// Number of vars in context

		FOR_EACH_MAP( VarIterator, VarMap, HashedString, ConfigVar )
		{
			const HashedString& Key = VarIterator.GetKey();
			const ConfigVar& Value = VarIterator.GetValue();

			Stream.WriteUInt32( Key.GetHash() );	// Hashed var name
			Stream.WriteUInt8( ( uint8 )Value.m_Type );

			switch( Value.m_Type )
			{
			case ConfigVar::EVT_Bool:
				Stream.WriteUInt8( Value.m_Bool );
				break;
			case ConfigVar::EVT_Int:
				Stream.WriteInt32( Value.m_Int );
				break;
			case ConfigVar::EVT_Float:
				Stream.WriteFloat( Value.m_Float );
				break;
			case ConfigVar::EVT_String:
				{
					// Doesn't write the terminating null
					uint Length = ( uint )strlen( Value.m_String );
					Stream.WriteUInt32( Length );
					Stream.Write( Length, Value.m_String );
					Stream.WriteUInt32( Value.m_Hash.GetHash() );
				}
				break;
			default:
				WARNDESC( "Bad config var type" );
				break;
			}
		}
	}
}
Exemplo n.º 11
0
Clock::MultiplierRequest* Clock::AddMultiplierRequest( float Duration, float Multiplier )
{
	if( Multiplier < 0.0f )
	{
		Multiplier = 0.0f;
		WARNDESC( "Clock multiplier should not be less than zero!" );
	}

	MultiplierRequest* pMultiplierRequest = new MultiplierRequest;
	pMultiplierRequest->m_Duration = Duration;
	pMultiplierRequest->m_Multiplier = Multiplier;
	m_MultiplierRequests.PushBack( pMultiplierRequest );

	return pMultiplierRequest;
}
Exemplo n.º 12
0
D3DMULTISAMPLE_TYPE GetD3DMultiSampleType(EMultiSampleType MultiSampleType) {
  switch (MultiSampleType) {
    case EMST_None:
      return D3DMULTISAMPLE_NONE;
    case EMST_2X:
      return D3DMULTISAMPLE_2_SAMPLES;
    case EMST_4X:
      return D3DMULTISAMPLE_4_SAMPLES;
    case EMST_8X:
      return D3DMULTISAMPLE_8_SAMPLES;
    default:
      WARNDESC("D3D multisample type not matched");
      return D3DMULTISAMPLE_NONE;
  }
}
Exemplo n.º 13
0
/*virtual*/ void GL2ShaderProgram::Initialize( IVertexShader* const pVertexShader, IPixelShader* const pPixelShader, IVertexDeclaration* const pVertexDeclaration )
{
	XTRACE_FUNCTION;

	m_VertexShader	= pVertexShader;
	m_PixelShader	= pPixelShader;

	ASSERT( m_VertexShader );
	ASSERT( m_PixelShader );

	m_ShaderProgram = glCreateProgram();
	ASSERT( m_ShaderProgram != 0 );

	GLuint VertexShader = *static_cast<GLuint*>( m_VertexShader->GetHandle() );
	ASSERT( VertexShader != 0 );
	glAttachShader( m_ShaderProgram, VertexShader );

	GLuint PixelShader = *static_cast<GLuint*>( m_PixelShader->GetHandle() );
	ASSERT( PixelShader != 0 );
	glAttachShader( m_ShaderProgram, PixelShader );

	BindAttributes( pVertexDeclaration );

	glLinkProgram( m_ShaderProgram );
	GLERRORCHECK;

	GLint LinkStatus;
	glGetProgramiv( m_ShaderProgram, GL_LINK_STATUS, &LinkStatus );

	if( LinkStatus != GL_TRUE )
	{
		GLint LogLength;
		glGetProgramiv( m_ShaderProgram, GL_INFO_LOG_LENGTH, &LogLength );
		Array<GLchar>	Log;
		Log.Resize( LogLength );
		glGetProgramInfoLog( m_ShaderProgram, LogLength, NULL, Log.GetData() );
		if( LogLength > 0 )
		{
			PRINTF( "GLSL shader program link failed:\n" );
			PRINTF( Log.GetData() );
		}
		WARNDESC( "GLSL shader program link failed" );
	}

	BuildUniformTable();
	SetSamplerUniforms();
}
Exemplo n.º 14
0
/*static*/ void EldritchFramework::OnSetRes(void* pUIElement, void* pVoid) {
  Unused(pVoid);

  EldritchFramework* const pFramework = EldritchFramework::GetInstance();
  Display* const pDisplay = pFramework->GetDisplay();
  UIWidget* const pWidget = static_cast<UIWidget*>(pUIElement);
  UIScreenEldSetRes* const pSetRes =
      pFramework->GetUIManager()->GetScreen<UIScreenEldSetRes>("SetResScreen");
  const SDisplayMode ChosenRes = pSetRes->GetRes(pWidget->m_Name);

  if (!pDisplay->m_Fullscreen &&
      (ChosenRes.Width > pDisplay->m_ScreenWidth ||
       ChosenRes.Height > pDisplay->m_ScreenHeight)) {
    WARNDESC("Mode too large for screen.");
  } else {
    pFramework->SetResolution(ChosenRes.Width, ChosenRes.Height);
  }
}
Exemplo n.º 15
0
void GL2PixelShader::Initialize( const IDataStream& Stream )
{
	XTRACE_FUNCTION;

	const int Length	= Stream.Size();
	byte* pBuffer		= new byte[ Length ];
	Stream.Read( Length, pBuffer );

	m_PixelShader = glCreateShader( GL_FRAGMENT_SHADER );
	ASSERT( m_PixelShader != 0 );

	// Copy the GLSL source
	const GLsizei	NumStrings		= 1;
	const GLchar*	Strings[]		= { reinterpret_cast<GLchar*>( pBuffer ) };
	const GLint		StringLengths[]	= { Length };	// I don't trust this file to be null-terminated, so explicitly declare the length.
	glShaderSource( m_PixelShader, NumStrings, Strings, StringLengths );

	// Compile the shader
	glCompileShader( m_PixelShader );
	GLERRORCHECK;

	GLint CompileStatus;
	glGetShaderiv( m_PixelShader, GL_COMPILE_STATUS, &CompileStatus );

	if( CompileStatus != GL_TRUE )
	{
		GLint LogLength;
		glGetShaderiv( m_PixelShader, GL_INFO_LOG_LENGTH, &LogLength );
		Array<GLchar>	Log;
		Log.Resize( LogLength );
		glGetShaderInfoLog( m_PixelShader, LogLength, NULL, Log.GetData() );
		if( LogLength > 0 )
		{
			PRINTF( "GLSL fragment shader compile failed:\n" );
			PRINTF( Log.GetData() );
		}
		WARNDESC( "GLSL fragment shader compile failed" );
	}

	SafeDeleteArray( pBuffer );
}
Exemplo n.º 16
0
SimpleString ReverseHash::ReversedHash( const HashedString& Hash )
{
	if( gReverseHashEnabled )
	{
		const Map<HashedString, SimpleString>::Iterator HashIter = gReverseHashMap.Search( Hash );
		if( HashIter.IsValid() )
		{
			return HashIter.GetValue();
		}
		else
		{
			WARN;
			return SimpleString( "(Hash)" );
		}
	}
	else
	{
		WARNDESC( "ReverseHash: Not enabled." );
		return SimpleString( "" );
	}
}
Exemplo n.º 17
0
GLenum GetGLFormat(const ERenderTargetFormat Format) {
  switch (Format) {
    case ERTF_Unknown:
      return 0;
    case ERTF_X8R8G8B8:
      return GL_RGBA8;  // Meh?
    case ERTF_A8R8G8B8:
      return GL_RGBA8;
#ifndef HAVE_GLES
    case ERTF_A16B16G16R16:
      return GL_RGBA16;
    case ERTF_A16B16G16R16F:
      ASSERT(GLEW_ARB_texture_float);
      return GL_RGBA16F_ARB;
    case ERTF_A32B32G32R32F:
      ASSERT(GLEW_ARB_texture_float);
      return GL_RGBA32F_ARB;
    case ERTF_R32F:
      ASSERT(GLEW_ARB_texture_float);
      return GL_INTENSITY32F_ARB;
#endif
    case ERTF_D24S8:
      return GL_DEPTH24_STENCIL8;
    case ERTF_UseDefault:
      // HACKHACK: GL doesn't support binding to the default depth buffer,
      // so promote ERTF_UseDefault to a reasonable default format.
      // NOTE: This won't work if the pass(es) associated with this target
      // needed to use data already in the buffer. It works for Eldritch
      // because the buffer was always cleared with each target, and reusing
      // the default was merely an optimization.
      return GL_DEPTH24_STENCIL8;
    default:
      WARNDESC("GL texture format not matched");
      return 0;
  }
}
Exemplo n.º 18
0
// InnerParse is poorly named; it really just accepts any character not handled in the calling function
// and determines the token type for unknown right-hand tokens.
void InnerParse( const char c, char& StrMark, Array< char >& TokenString, const int LineCount, SToken::ETokenType& InOutTokenType, bool* OutClosedString = NULL )
{
	switch( InOutTokenType )
	{
	case SToken::ET_None:
		// Determine the type of the RHS from the first character
		// (Can change from int to float later, on finding a . or f)
		if( IsNum( c ) || c == '-' )
		{
			InOutTokenType = SToken::ET_Int;
			TokenString.PushBack( c );
		}
		else if( IsBool( c ) )
		{
			InOutTokenType = SToken::ET_Bool;
			TokenString.PushBack( c );
		}
		else if( c == '\"' || c == '\'' )
		{
			InOutTokenType = SToken::ET_String;
			StrMark = c;
		}
		else if( c == '.' )
		{
			InOutTokenType = SToken::ET_Float;
			TokenString.PushBack( c );
		}
		else
		{
			PRINTF( "Unexpected character %c in undetermined token at line %d\n", c, LineCount );
			WARNDESC( "Unexpected character in undetermined token" );
		}
		break;
	case SToken::ET_Name:
	case SToken::ET_Context:
	case SToken::ET_Macro:
		TokenString.PushBack( c );
		break;
	case SToken::ET_Bool:
		TokenString.PushBack( c );
		break;
	case SToken::ET_Int:
		if( c == '.' )
		{
			InOutTokenType = SToken::ET_Float;
		}
		else
		{
			ASSERT( IsNum( c ) );
		}
		TokenString.PushBack( c );
		break;
	case SToken::ET_Float:
		ASSERT( IsNum( c ) || c == 'f' );
		TokenString.PushBack( c );
		break;
	case SToken::ET_String:
		if( c == StrMark )
		{
			TokenString.PushBack( '\0' );
			if( OutClosedString )
			{
				*OutClosedString = true;
			}
		}
		else
		{
			TokenString.PushBack( c );
		}
		break;
	default:
		WARNDESC( "Unexpected token" );
		break;
	}
}
Exemplo n.º 19
0
bool Cylinder::Intersects( const Segment& s, CollisionInfo* const pInfo /*= NULL*/ ) const
{
	Vector d = m_Point2 - m_Point1;		// Cylinder axis
	Vector m = s.m_Point1 - m_Point1;	// Vector from cylinder base to segment base?
	Vector n = s.m_Point2 - s.m_Point1;	// Segment vector

	float md = m.Dot( d );
	float nd = n.Dot( d );
	float dd = d.Dot( d );

	if( md < 0.0f && md + nd < 0.0f )
	{
		return false;
	}

	if( md > dd && md + nd > dd )
	{
		return false;
	}

	float nn = n.Dot( n );
	float mn = m.Dot( n );
	float a = dd * nn - nd * nd;
	float k = m.Dot( m ) - m_Radius * m_Radius;
	float c = dd * k - md * md;
	float t = 0.0f;

	if( Abs( a ) < SMALLER_EPSILON )
	{
		// Segment (n) runs parallel to cylinder axis (d)

		if( c > 0.0f )
		{
			return false;
		}

		if( md < 0.0f )
		{
			t = -mn / nn;
		}
		else if( md > dd )
		{
			t = ( nd - mn ) / nn;
		}
		else
		{
			// TODO: This seems to be problematic (or getting here is indicative of an earlier problem)
			WARNDESC( "THAT CYLINDER COLLISION BUG" );
			t = 0.0f;
		}

		if( pInfo )
		{
			Vector Intersection = s.m_Point1 + t * n;
			Vector PointOnLine = Line( m_Point1, m_Point2 - m_Point1 ).NearestPointTo( pInfo->m_Intersection );
			Vector Normal = ( Intersection - PointOnLine ).GetNormalized();

			pInfo->m_Collision = true;
			pInfo->m_Intersection = Intersection;
			pInfo->m_HitT = t;
			pInfo->m_Plane = Plane( Normal, PointOnLine );
		}
		return true;
	}

	float b = dd * mn - nd * md;
	float Discr = b * b - a * c;

	if( Discr < 0.0f )
	{
		return false;
	}

	t = ( -b - SqRt( Discr ) ) / a;

	if( t < 0.0f || t > 1.0f )
	{
		return false;
	}

	// Test endcaps--if we collide with them, count it as not colliding with cylinder
	if( md + t * nd < 0.0f )
	{
		return false;
		//// Segment outside cylinder on first side
		//if( nd <= 0.0f )
		//{
		//	// Segment pointing away from endcap
		//	return false;
		//}
		//float t2 = -md / nd;
		//if( k + t2 * ( 2.0f * mn + t2 * nn ) > 0.0f )
		//{
		//	return false;
		//}
	}
	else if( md + t * nd > dd )
	{
		return false;
		//// Segment outside cylinder on second side
		//if( nd >= 0.0f )
		//{
		//	// Segment pointing away from endcap
		//	return false;
		//}
		//float t2 = ( dd - md ) / nd;
		//if( k + dd - 2.0f * md + t2 * ( 2.0f * ( mn - nd ) + t2 * nn ) > 0.0f )
		//{
		//	return false;
		//}
	}

	if( pInfo )
	{
		Vector Intersection = s.m_Point1 + t * n;
		Vector PointOnLine = Line( m_Point1, m_Point2 - m_Point1 ).NearestPointTo( Intersection );
		Vector Normal = ( Intersection - PointOnLine ).GetNormalized();

		pInfo->m_Collision = true;
		pInfo->m_Intersection = Intersection;
		pInfo->m_HitT = t;
		pInfo->m_Plane = Plane( Normal, PointOnLine );
	}
	return true;
}
Exemplo n.º 20
0
void ConfigParser::Parse( const IDataStream& Stream )
{
	Array< SToken >	Tokens;
	SToken			Token;
	Token.m_TokenType						= SToken::ET_Name;
	char			StrMark					= 0;	// Stores the character (either ' or ") that opened a string
	SToken			MacroToken;
	List<int>		ArrayCounters;
	Array<char>		CounterCharArray;
	int				LineCount				= 1;

	for(;;)
	{
		char c = Stream.ReadInt8();

		// Skip the UTF-8 byte order mark if present.
		if( UTF8_BOM_0 == static_cast<byte>( c ) )
		{
			CHECK( UTF8_BOM_1 == static_cast<byte>( Stream.ReadInt8() ) );
			CHECK( UTF8_BOM_2 == static_cast<byte>( Stream.ReadInt8() ) );
			c = Stream.ReadInt8();
		}

		if( Stream.EOS() )
		{
			if( Token.m_TokenString.Empty() )
			{
				Token.m_TokenType = SToken::ET_None;
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s\n", SToken::m_TokenNames[ Token.m_TokenType ] );
			}
			else
			{
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();
			}

			break;
		}

		if( c == '&' )
		{
			if( Token.m_TokenType == SToken::ET_Name )
			{
				// Increment the current counter and add it to the current name.
				ASSERT( ArrayCounters.Size() > 0 );
				List<int>::Iterator CounterIter = ArrayCounters.Back();
				( *CounterIter )++;
				SimpleString CounterString = SimpleString::PrintF( "%d", *CounterIter );
				CounterCharArray.Clear();
				CounterString.FillArray( CounterCharArray );
				Token.m_TokenString.Append( CounterCharArray );
			}
			else if( Token.m_TokenType == SToken::ET_None )
			{
				// Add a new counter
				// Push a counter token that will be replaced with the count int later.
				ArrayCounters.PushBack( -1 );
				Token.m_TokenType = SToken::ET_Counter;
			}
			else if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				WARNDESC( "Unexpected character '&' in token." );
			}
		}
		else if( c == '^' )
		{
			if( Token.m_TokenType == SToken::ET_Name )
			{
				// Add the current counter to the current name.
				ASSERT( ArrayCounters.Size() > 0 );
				List<int>::Iterator CounterIter = ArrayCounters.Back();
				ASSERT( ( *CounterIter ) >= 0 );
				SimpleString CounterString = SimpleString::PrintF( "%d", *CounterIter );
				CounterCharArray.Clear();
				CounterString.FillArray( CounterCharArray );
				Token.m_TokenString.Append( CounterCharArray );
			}
			else if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				WARNDESC( "Unexpected character '^' in token." );
			}
		}
		else if( c == ' ' || c == '\t' )
		{
			switch( Token.m_TokenType )
			{
			case SToken::ET_None:
			case SToken::ET_Equals:
				// Ignore whitespace
				break;
			case SToken::ET_Name:
			case SToken::ET_Context:
			case SToken::ET_Macro:
				if( Token.m_TokenString.Empty() )
				{
					// If the name is empty, ignore whitespace (before the name)
				}
				else
				{
					// Close current token, push it, and expect an equals

					// If we're closing a macro, save it as such
					if( Token.m_TokenType == SToken::ET_Macro )
					{
						MacroToken = Token;
					}

					Token.m_TokenString.PushBack( '\0' );
					Tokens.PushBack( Token );
					DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
					Token.m_TokenString.Clear();

					if( Token.m_TokenType == SToken::ET_Name )
					{
						Token.m_TokenType = SToken::ET_Equals;
					}
					else if( Token.m_TokenType == SToken::ET_Context || Token.m_TokenType == SToken::ET_Macro )
					{
						Token.m_TokenType = SToken::ET_Name;
					}
				}
				break;
			case SToken::ET_Bool:
			case SToken::ET_Int:
			case SToken::ET_Float:
				// Close current token, push it, and expect nothing
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();

				Token.m_TokenType = SToken::ET_None;
				break;
			case SToken::ET_String:
				Token.m_TokenString.PushBack( c );
				break;
			default:
				WARNDESC( "Unexpected token" );
				break;
			}
		}
		else if( c == '=' )
		{
			switch( Token.m_TokenType )
			{
			case SToken::ET_Name:
				// Close current token, push it and an equals
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();

				Token.m_TokenType = SToken::ET_Equals;
				DEBUGCATPRINTF( "Core", 2, "%s\n", SToken::m_TokenNames[ Token.m_TokenType ] );
				Tokens.PushBack( Token );

				Token.m_TokenType = SToken::ET_None;
				break;
			case SToken::ET_Equals:
				// Already expecting =, just push it
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s\n", SToken::m_TokenNames[ Token.m_TokenType ] );

				Token.m_TokenType = SToken::ET_None;
				break;
			case SToken::ET_String:
				Token.m_TokenString.PushBack( c );
				break;
			default:
				WARNDESC( "Unexpected token" );
				break;
			}
		}
		else if( c == '#' )
		{
			// # starts a comment

			// Allow # inside a string
			if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				c = Stream.ReadInt8();
				
				if( c == '!' )	// #! and !# indicate the start and end of block comments
				{
					while( !Stream.EOS() )
					{
						if( Stream.ReadInt8() == '!' && Stream.ReadInt8() == '#' )
						{
							break;
						}
					}
				}
				else
				{
					// Read to end of line
					while( c != '\n' && c!= '\v' && !Stream.EOS() )	// Vertical tab stupidity again
					{
						c = Stream.ReadInt8();
					}

					// Change the context because we're on a new line
					Token.m_TokenType = SToken::ET_Name;

					++LineCount;
				}
			}
		}
		else if( c == '\\' && Token.m_TokenType == SToken::ET_String )
		{
			// Escape sequence, intended to insert linebreaks (and maybe other things in the future)
			// Config string escape sequences are not the same as C++ escape sequences. They can be
			// \\, \n, \?, \", or \xx (where x are hex digits, to specify any character by hex).

			char next = Stream.ReadInt8();
			if( next == 'n' )
			{
				Token.m_TokenString.PushBack( '\n' );
			}
			else if( next == '\"' )
			{
				Token.m_TokenString.PushBack( '\"' );
			}
			else if( next == '\\' )
			{
				Token.m_TokenString.PushBack( '\\' );
			}
			else if( next == 'x' )
			{
				char Hex = 0;
				for( uint HexIndex = 0; HexIndex < 2; ++HexIndex )
				{
					next = Stream.ReadInt8();
					ASSERT( IsHex( next ) );
					Hex = ( Hex << 4 ) | GetHex( next );
				}
				Token.m_TokenString.PushBack( Hex );
			}
			else if( next == 'u' )
			{
				// First, extract a unicode code point (e.g. \u00d7 for U+00D7)
				// NOTE: This only support the first Unicode plane, and is strict about
				// using four characters, so \ud7 is not a valid substitute for \u00d7.
				unicode_t CodePoint = 0;
				for( uint UnicodeIndex = 0; UnicodeIndex < 4; ++UnicodeIndex )
				{
					next = Stream.ReadInt8();
					ASSERT( IsHex( next ) );
					CodePoint = ( CodePoint << 4 ) | GetHex( next );
				}

				// Then convert the two-byte code point to UTF-8.
				Array<unicode_t> CodePointArray;
				CodePointArray.PushBack( CodePoint );
				const SimpleString UTF8String = SimpleString::SetUTF8( CodePointArray );

				for( uint CharIndex = 0; CharIndex < UTF8String.Length(); ++CharIndex )
				{
					const char NextChar = UTF8String.GetChar( CharIndex );
					Token.m_TokenString.PushBack( NextChar );
				}
			}
			else
			{
				PRINTF( "Unrecognized escape sequence \\%c at line %d\n", next, LineCount );
				WARNDESC( "Unrecognized escape sequence" );
			}
		}
		else if( c == 0x0d )
		{
			// DOS linebreak is 0D 0A, so ignore and expect \n to follow
		}
		else if( c == '\0' )
		{
			// Don't know how these are getting in either, but ignore them
		}
		else if( c == '\n' || c == '\v' )
		{
			if( Token.m_TokenType == SToken::ET_Macro )
			{
				MacroToken = Token;
			}

			// Dunno how vertical tabs are getting in, but treat them as linebreaks
			if( Token.m_TokenString.Empty() )
			{
				if( Token.m_TokenType != SToken::ET_Counter )
				{
					Token.m_TokenType = SToken::ET_None;
				}
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s\n", SToken::m_TokenNames[ Token.m_TokenType ] );

				Token.m_TokenType = SToken::ET_Name;
			}
			else
			{
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();

				Token.m_TokenType = SToken::ET_Name;
			}

			++LineCount;
		}
		else if( c == '[' )
		{
			if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				// We should only ever open a context when we're expecting a name
				ASSERT( Token.m_TokenType == SToken::ET_Name );
				Token.m_TokenType = SToken::ET_Context;

				// Opening a new context, clear the macro token.
				MacroToken = SToken();
			}
		}
		else if( c == ']' )
		{
			// If we've already closed the context, ignore; else, push token
			if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				ASSERT( Token.m_TokenType == SToken::ET_Context );
				Token.m_TokenString.PushBack( '\0' );
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();
			}
		}
		else if( c == '@' )
		{
			if( Token.m_TokenType == SToken::ET_String )
			{
				Token.m_TokenString.PushBack( c );
			}
			else
			{
				// We should only ever declare or insert a macro when we're expecting a name
				ASSERT( Token.m_TokenType == SToken::ET_Name );
				c = Stream.ReadInt8();
				if( c == '@' )
				{
					// @@... means we're inserting the current macro into a name

					// Make sure there is a current macro. If this fails, a macro probably
					// wasn't opened in the current context.
					ASSERT( MacroToken.m_TokenString.Size() > 0 );

					const uint MacroLength = MacroToken.m_TokenString.Size();
					for( uint MacroIndex = 0; MacroIndex < MacroLength; ++MacroIndex )
					{
						Token.m_TokenString.PushBack( MacroToken.m_TokenString[ MacroIndex ] );
					}
				}
				else
				{
					// @... means we're declaring a new macro
					Token.m_TokenType = SToken::ET_Macro;
					if( c == ' ' || c == '\t' )
					{
						// Ignore whitespace at the front of macro
					}
					else
					{
						Token.m_TokenString.PushBack( c );
					}
				}
			}
		}
		else
		{
			bool ClosedString = false;
			InnerParse( c, StrMark, Token.m_TokenString, LineCount, Token.m_TokenType, &ClosedString );
			if( ClosedString )
			{
				Tokens.PushBack( Token );
				DEBUGCATPRINTF( "Core", 2, "%s: %s\n", SToken::m_TokenNames[ Token.m_TokenType ], Token.m_TokenString.GetData() );
				Token.m_TokenString.Clear();
				Token.m_TokenType = SToken::ET_None;
			}
		}
	}

	SimpleString Context = "";

	// Tokens are made, now create config vars
	for( uint i = 0; i < Tokens.Size(); ++i )
	{
		SToken& NameToken = Tokens[i];
		SimpleString Name = "";
		const char* ValueString = NULL;
		if( NameToken.m_TokenType == SToken::ET_Name )
		{
			Name = NameToken.m_TokenString.GetData();
			ASSERT( Tokens[ i + 1 ].m_TokenType == SToken::ET_Equals );

			SToken& ValueToken = Tokens[ i + 2 ];
			ValueString = ValueToken.m_TokenString.GetData();

			if( Context != "" )
			{
				CATPRINTF( "Core", 2, "%s:", Context.CStr() );
			}
			CATPRINTF( "Core", 2, "%s: %s: %s\n", Name.CStr(), SToken::m_TokenNames[ ValueToken.m_TokenType ], ValueString );

			switch( ValueToken.m_TokenType )
			{
			case SToken::ET_Bool:
				{
					// Just use the first character to determine truth
					bool Value = false;
					char first = ValueString[0];
					if( first == 't' || first == 'T' )
					{
						Value = true;
					}
					ConfigManager::SetBool( Name, Value, Context );
				}
				break;
			case SToken::ET_Int:
				{
					int Value = atoi( ValueString );
					ConfigManager::SetInt( Name, Value, Context );
				}
				break;
			case SToken::ET_Counter:
				{
					List<int>::Iterator NextCounterIter = ArrayCounters.Front();
					( *NextCounterIter )++;	// Add one to the last value we incremented, and that's the total for this array
					ConfigManager::SetInt( Name, *NextCounterIter, Context );
					ArrayCounters.PopFront();
				}
				break;
			case SToken::ET_Float:
				{
					float Value = (float)atof( ValueString );
					ConfigManager::SetFloat( Name, Value, Context );
				}
				break;
			case SToken::ET_String:
				{
					// Make a permanent copy of the string
					uint Length = (uint)strlen( ValueString );
					char* pString = new char[ Length + 1];
					memcpy_s( pString, Length + 1, ValueString, Length );
					pString[ Length ] = '\0';
					StringManager::AddString( StringManager::ESL_Permanent, pString );

					ConfigManager::SetString( Name, pString, Context );
				}

				break;
			default:
				WARNDESC( "Unexpected token" );
				break;
			}

			i += 2;
		}
		else if( NameToken.m_TokenType == SToken::ET_Context )
		{
			Context = NameToken.m_TokenString.GetData();
			//CATPRINTF( "Core", 2, "Pushed context %s\n", Context.CStr() );
		}
		else
		{
			DEBUGCATPRINTF( "Core", 2, "Skipped unexpected token %s (expected ET_Name)\n", SToken::m_TokenNames[ NameToken.m_TokenType ] );
		}
	}

	// Clean up
	for( uint i = 0; i < Tokens.Size(); ++i )
	{
		Tokens[i].m_TokenString.Clear();
	}
	Tokens.Clear();
}
Exemplo n.º 21
0
// NOTE: This is a lot of duplicated code from the value parsing parts
// of Parse(). Could do to clean this up and use common functions.
void ConfigParser::ParseTiny( const IDataStream& Stream )
{
	Array< char >		FirstPart;	// Could be name or context
	Array< char >		SecondPart;	// Name if first part is context
	Array< char >		ValuePart;
	SToken::ETokenType	Type = SToken::ET_None;
	char				QuoteType = '\"';
	bool				StringClosed = false;

	enum EParseState
	{
		EPS_FirstPart,
		EPS_SecondPart,
		EPS_ValuePart,
	} ParseState = EPS_FirstPart;

	while( !Stream.EOS() )
	{
		char c = Stream.ReadInt8();

		if( ParseState == EPS_FirstPart )
		{
			if( c == ' ' || c == '\t' || c == '\n' || c == '\0' )
			{
				// Ignore whitespace
				continue;
			}
			else if( c == ':' )
			{
				FirstPart.PushBack( '\0' );
				ParseState = EPS_SecondPart;
				continue;
			}
			else if( c == '=' )
			{
				FirstPart.PushBack( '\0' );
				ParseState = EPS_ValuePart;
				continue;
			}
			else
			{
				FirstPart.PushBack( c );
			}
		}
		else if( ParseState == EPS_SecondPart )
		{
			if( c == ' ' || c == '\t' || c == '\n' || c == '\0' )
			{
				// Ignore whitespace
				continue;
			}
			else if( c == '=' )
			{
				SecondPart.PushBack( '\0' );
				ParseState = EPS_ValuePart;
				continue;
			}
			else
			{
				SecondPart.PushBack( c );
			}
		}
		else if( ParseState == EPS_ValuePart )
		{
			if( ( ( Type != SToken::ET_String || StringClosed ) && ( c == ' ' || c == '\t' ) ) || c == '\n' || c == '\0' )
			{
				// Parse the value and set the config var
				ValuePart.PushBack( '\0' );

				SimpleString Name = ( SecondPart.Size() > 1 ) ? SecondPart.GetData() : FirstPart.GetData();
				SimpleString Context = ( SecondPart.Size() > 1 ) ? FirstPart.GetData() : "";

				switch( Type )
				{
				case SToken::ET_Bool:
					{
						// Just use the first character to determine truth
						bool Value = false;
						char first = ValuePart[0];
						if( first == 't' || first == 'T' )
						{
							Value = true;
						}
						ConfigManager::SetBool( Name, Value, Context );
					}
					break;
				case SToken::ET_Int:
					{
						int Value = atoi( ValuePart.GetData() );
						ConfigManager::SetInt( Name, Value, Context );
					}
					break;
				case SToken::ET_Float:
					{
						float Value = (float)atof( ValuePart.GetData() );
						ConfigManager::SetFloat( Name, Value, Context );
					}
					break;
				case SToken::ET_String:
					{
						// Make a permanent copy of the string
						uint Length = (uint)strlen( ValuePart.GetData() );
						char* pString = new char[ Length + 1];
						memcpy_s( pString, Length + 1, ValuePart.GetData(), Length );
						pString[ Length ] = '\0';
						StringManager::AddString( StringManager::ESL_Permanent, pString );

						ConfigManager::SetString( Name, pString, Context );
					}

					break;
				default:
					WARNDESC( "Unexpected token" );
					break;
				}

				// Prepare for next variable
				FirstPart.Clear();
				SecondPart.Clear();
				ValuePart.Clear();
				Type = SToken::ET_None;
				ParseState = EPS_FirstPart;
				StringClosed = false;
				continue;
			}
			else
			{
				InnerParse( c, QuoteType, ValuePart, 0, Type, &StringClosed );
			}
		}
	}
}
Exemplo n.º 22
0
void ConfigManager::Load( const IDataStream& Stream )
{
	uint Pos = Stream.GetPos();
	if( 'FCCD' == Stream.ReadUInt32() )
	{
		uint NumContexts = Stream.ReadUInt32();
		for( uint ContextIndex = 0; ContextIndex < NumContexts; ++ContextIndex )
		{
			HashedString ContextKey( Stream.ReadUInt32() );
			uint NumVars = Stream.ReadUInt32();

			VarMap& VarMap = GetInstance()->m_Vars[ ContextKey ];

			for( uint VarIndex = 0; VarIndex < NumVars; ++VarIndex )
			{
				ConfigVar ConfigVar;
				HashedString Key( Stream.ReadUInt32() );
				ConfigVar.m_Type = ( ConfigVar::EVarType )Stream.ReadUInt8();

				switch( ConfigVar.m_Type )
				{
				case ConfigVar::EVT_Bool:
					ConfigVar.m_Bool = ( Stream.ReadUInt8() != 0 );
					break;
				case ConfigVar::EVT_Int:
					ConfigVar.m_Int = Stream.ReadInt32();
					break;
				case ConfigVar::EVT_Float:
					ConfigVar.m_Float = Stream.ReadFloat();
					break;
				case ConfigVar::EVT_String:
					{
						uint Length = Stream.ReadUInt32();

						char* pString = AllocateString( Length + 1 );
						Stream.Read( Length, pString );
						pString[ Length ] = '\0';
						StringManager::AddString( StringManager::ESL_Permanent, pString );

						ConfigVar.m_String = pString;
						ConfigVar.m_Hash = Stream.ReadUInt32();

						if( ReverseHash::IsEnabled() )
						{
							ReverseHash::RegisterHash( ConfigVar.m_Hash, ConfigVar.m_String );
						}
					}
					break;
				default:
					WARNDESC( "Bad config var type" );
					break;
				}

				VarMap.Insert( Key, ConfigVar );
			}
		}

	}
	else
	{
		Stream.SetPos( Pos );
		ConfigParser::Parse( Stream );
	}
}
Exemplo n.º 23
0
void WBCompEldRope::DropRope() {
  WBEntity* const pEntity = GetEntity();
  DEVASSERT(pEntity);

  WBCompEldTransform* const pTransform =
      pEntity->GetTransformComponent<WBCompEldTransform>();
  DEVASSERT(pTransform);

  // HookVector is directed away from the surface (same as hit normal)
  const Vector HookVector = Quantize(pTransform->GetOrientation().ToVector());
  const Vector DropVector = Vector(0.0f, 0.0f, -1.0f);

  ASSERT(HookVector.LengthSquared() == 1.0f);
  ASSERT((HookVector.y == 0.0f && HookVector.z == 0.0f) ||
         (HookVector.x == 0.0f && HookVector.z == 0.0f) ||
         (HookVector.x == 0.0f && HookVector.y == 0.0f));

  WBCompEldCollision* const pCollision = GET_WBCOMP(pEntity, EldCollision);
  DEVASSERT(pCollision);

  WBCompEldMesh* const pMesh = GET_WBCOMP(pEntity, EldMesh);
  DEVASSERT(pMesh);

  EldritchWorld* const pWorld = GetWorld();

  const Vector HitLocation = pTransform->GetLocation();
  const Vector StartLocation = HitLocation + (HookVector * m_HookLength);
  const Ray TraceRay = Ray(StartLocation, DropVector);

  CollisionInfo Info;
  Info.m_CollideWorld = true;
  Info.m_CollideEntities = true;
  Info.m_CollidingEntity = pEntity;
  Info.m_UserFlags = EECF_CollideAsEntity | EECF_CollideStaticEntities;

  if (pWorld->Trace(TraceRay, Info)) {
    m_Dropped = true;

    // Reset orientation now that it is being "baked" into extents.
    pTransform->SetOrientation(Angles());

    // StartLocation is where the rope attaches to the hook
    // EndLocation is where the rope dangles above the ground
    ASSERT(Info.m_Plane.m_Normal.Equals(Vector::Up, EPSILON));
    const Vector EndLocation =
        Info.m_Intersection + Info.m_Plane.m_Normal * m_DangleHeight;
    pTransform->SetLocation(0.5f * (StartLocation + EndLocation));

    const Vector HalfExtents = (0.5f * (EndLocation - StartLocation)).GetAbs();
    const Vector CollisionFatten =
        Vector(m_CollisionFatten, m_CollisionFatten, m_CollisionFatten);
    pCollision->SetExtents(HalfExtents + CollisionFatten);

    const Vector MeshFatten = Vector(m_MeshFatten, m_MeshFatten, m_MeshFatten);
    pMesh->SetMeshScale(HalfExtents + MeshFatten);

    m_Anchor = HitLocation - (HookVector * m_AnchorDepth);

    // Spawn rope hook entity and set up its transform and anchor
    {
      WBEntity* const pHookEntity =
          WBWorld::GetInstance()->CreateEntity(m_HookEntity);
      ASSERT(pHookEntity);

      WBCompEldTransform* const pHookTransform =
          pHookEntity->GetTransformComponent<WBCompEldTransform>();
      ASSERT(pHookTransform);

      WBCompEldAnchor* const pHookAnchor = GET_WBCOMP(pHookEntity, EldAnchor);
      ASSERT(pHookAnchor);

      pHookTransform->SetLocation(StartLocation);
      pHookTransform->SetOrientation((-HookVector).ToAngles());
    }
  } else {
    WARNDESC("Rope could not be launched.");
    pEntity->Destroy();
  }
}