Example #1
0
void Patcher_HandleReceipt_NextPatchFile()
{
	char* MessageContent = strstr( g_HTTPResultBuffer.GetData(), CRLF CRLF );
	if( !MessageContent )
	{
		// If we were updating, we're not anymore
		g_Patcher_IsUpdating = false;

		AddStatus( "Error receiving patch file.", g_StatusWarningColor );
		++g_NumWarnings;
		return;
	}

	MessageContent += 4;

	uint Offset = ( uint )( MessageContent - g_HTTPResultBuffer.GetData() );
	uint ContentSize = g_HTTPSocket->AsyncGetBytesReceived() - Offset;

	// Compute the checksum for the payload and compare with the data in the manifest file
	uint32 ContentChecksum = Checksum::Adler32( ( uint8* )MessageContent, ContentSize );
	SimpleString ContentLengthString = SimpleString::PrintF( "%d", ContentSize );
	SimpleString ContentChecksumString = SimpleString::PrintF( "0x%08X", ContentChecksum );

	SManifestFile& ManifestFile = g_FilesInManifest[ g_NextPatchFileIndex ];
	SimpleString PatchFile = ManifestFile.m_Filename;

	if( ContentLengthString == ManifestFile.m_Length && ContentChecksumString == ManifestFile.m_Checksum )
	{
		ManifestFile.m_Validated = true;

		FileStream TempFile( GetTempFileForPatchFile( PatchFile ).CStr(), FileStream::EFM_Write );
		TempFile.Write( ContentSize, MessageContent );

		AddStatus( SimpleString::PrintF( "%s received.", PatchFile.CStr() ), g_StatusColor );
	}
	else
	{
		AddStatus( SimpleString::PrintF( "Checksum failure for %s.", PatchFile.CStr() ), g_StatusWarningColor );
		++g_NumWarnings;
	}

	g_NextPatchFileIndex++;

	// If there are remaining files, get them.
	if( g_NextPatchFileIndex < g_FilesInManifest.Size() )
	{
		Patcher_GetNextPatchFile();
	}
	else
	{
		FinishPatching();
	}
}
Example #2
0
void StreamReader::ReadString(String *result, const String &delimiter) {
    Array<Char> retString;
    Array<Char> delString;
    String strDelimiter = delimiter;
    Char c;
    if (strDelimiter.IsEmpty()) {
        strDelimiter.Resize(1);
        strDelimiter.Append("\0");
    }
    while (true) {
        c = ReadByte();
        if (this->GetError())
            break;
        if (c == strDelimiter.GetData()[0]) {
            delString.Clear();
            delString.Append(c);
            for (Int i = 1; i < strDelimiter.GetSizeInBytes(); i++) {
                c = ReadByte();
                if (this->GetError()) {
                    for (Int j = 0; j < delString.GetElementCount(); j++)
                        retString.Append(delString[j]);
                    break;
                }
                delString.Append(c);
                if (c != strDelimiter.GetData()[i])
                    break;
            }
            if (strDelimiter.GetSizeInBytes() > delString.GetElementCount())
                for (Int i = 0; i < delString.GetElementCount(); i++)
                    retString.Append(delString[i]);
            else {
                if (memcmp(strDelimiter.GetData(),
                           delString.GetData(), delString.GetElementCount()))
                {
                    for (Int i = 0; i < delString.GetElementCount(); i++)
                        retString.Append(delString[i]);
                }
                else
                    break;
            }
        } else {
            retString.Append(c);
        }
    }
    result->Resize(retString.GetElementCount());
    memcpy((Char*)result->GetData(),
           retString.GetData(), retString.GetElementCount());
}
Example #3
0
void BlockVector::Update(const Array<int> &bOffsets)
{
   blockOffsets = bOffsets.GetData();
   if (OwnsData())
   {
      // check if 'bOffsets' agree with the 'blocks'
      if (bOffsets.Size() == numBlocks+1)
      {
         if (numBlocks == 0) { return; }
         if (Size() == bOffsets.Last())
         {
            for (int i = numBlocks - 1; true; i--)
            {
               if (i < 0) { return; }
               if (blocks[i].Size() != bOffsets[i+1] - bOffsets[i]) { break; }
               MFEM_ASSERT(blocks[i].GetData() == data + bOffsets[i],
                           "invalid blocks[" << i << ']');
            }
         }
      }
   }
   else
   {
      Destroy();
   }
   SetSize(bOffsets.Last());
   if (numBlocks != bOffsets.Size()-1)
   {
      delete [] blocks;
      numBlocks = bOffsets.Size()-1;
      blocks = new Vector[numBlocks];
   }
   SetBlocks();
}
Example #4
0
void SimpleString::FillArray( Array<char>& OutArray, bool WithNull /*= false*/ ) const
{
	const uint Length = WithNull ? m_Length + 1 : m_Length;
	OutArray.Clear();
	OutArray.Resize( Length );
	memcpy_s( OutArray.GetData(), Length, m_String, Length );
}
/*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();
}
Example #6
0
//! View constructor
BlockVector::BlockVector(double *data, const Array<int> & bOffsets):
   Vector(data, bOffsets.Last()),
   numBlocks(bOffsets.Size()-1),
   blockOffsets(bOffsets.GetData())
{
   blocks = new Vector[numBlocks];
   SetBlocks();
}
Example #7
0
static void TestDataAlignmentT()
{
    Array<TYPE> v;
    v.PushBack( TYPE() );

    UT_ASSERT(v.GetSize() == 1);
    UT_ASSERT(((long)v.GetData()) % AligmentSize == 0);

}
Example #8
0
// helper to set submatrix of A repeated vdim times
static void SetVDofSubMatrixTranspose(SparseMatrix& A,
                                      Array<int>& rows, Array<int>& cols,
                                      const DenseMatrix& subm, int vdim)
{
   if (vdim == 1)
   {
      A.SetSubMatrixTranspose(rows, cols, subm, 1);
   }
   else
   {
      int nr = subm.Width(), nc = subm.Height();
      for (int d = 0; d < vdim; d++)
      {
         Array<int> rows_sub(rows.GetData() + d*nr, nr); // (not owner)
         Array<int> cols_sub(cols.GetData() + d*nc, nc); // (not owner)
         A.SetSubMatrixTranspose(rows_sub, cols_sub, subm, 1);
      }
   }
}
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 );
}
Example #10
0
void BlockVector::Update(double *data, const Array<int> & bOffsets)
{
   NewDataAndSize(data, bOffsets.Last());
   blockOffsets = bOffsets.GetData();
   if (numBlocks != bOffsets.Size()-1)
   {
      delete [] blocks;
      numBlocks = bOffsets.Size()-1;
      blocks = new Vector[numBlocks];
   }
   SetBlocks();
}
Example #11
0
void Patcher_HandleReceipt_ManifestFile()
{
	g_FilesInManifest.Clear();
	g_NextPatchFileIndex = 0;

	char* MessageContent = strstr( g_HTTPResultBuffer.GetData(), CRLF CRLF );
	if( !MessageContent )
	{
		AddStatus( "Error receiving manifest file.", g_StatusWarningColor );
		++g_NumWarnings;
		return;
	}

	MessageContent += 4;

	uint Offset = ( uint )( MessageContent - g_HTTPResultBuffer.GetData() );
	uint ContentSize = g_HTTPSocket->AsyncGetBytesReceived() - Offset;

	Array<SimpleString>	Lines;
	SplitIntoLines( MessageContent, ContentSize, Lines );

	for( uint LinesIndex = 0; LinesIndex + 2 < Lines.Size(); LinesIndex += 3 )
	{
		SManifestFile ManifestFile;
		ManifestFile.m_Filename = Lines[ LinesIndex ];
		ManifestFile.m_Length = Lines[ LinesIndex + 1 ];
		ManifestFile.m_Checksum = Lines[ LinesIndex + 2 ];
		ManifestFile.m_Validated = false;

		g_FilesInManifest.PushBack( ManifestFile );
	}

	AddStatus( "Manifest file received.", g_StatusColor );

	if( g_NextPatchFileIndex < g_FilesInManifest.Size() )
	{
		Patcher_GetNextPatchFile();
	}
}
Example #12
0
SimpleString SimpleString::Replace( const char* const Find, const char* const Replace ) const
{
	DEVASSERT( Find );
	DEVASSERT( Replace );

	Array<char> NewStringBuffer;
	NewStringBuffer.Resize( m_Length + 1 );
	memcpy( NewStringBuffer.GetData(), m_String, m_Length + 1	);

	const size_t FindLength		= strlen( Find );
	const size_t ReplaceLength	= strlen( Replace );
	const size_t Difference		= ReplaceLength - FindLength;

	for( size_t Iterator = 0; Iterator < NewStringBuffer.Size(); )
	{
		const char* const		SubStr	= strstr( NewStringBuffer.GetData() + Iterator, Find );
		if( SubStr )
		{
			const char* const	Base	= NewStringBuffer.GetData();
			const size_t		Offset	= SubStr - Base;

			for( size_t DifferenceIndex = 0; DifferenceIndex < Difference; ++DifferenceIndex )
			{
				NewStringBuffer.Insert( 0, static_cast<uint>( Offset ) );
			}

			memcpy( NewStringBuffer.GetData() + Offset, Replace, ReplaceLength );

			Iterator += ReplaceLength;
		}
		else
		{
			break;
		}
	}

	return SimpleString( NewStringBuffer );
}
Example #13
0
void Patcher_HandleReceipt_VersionNumber()
{
	char* MessageContent = strstr( g_HTTPResultBuffer.GetData(), CRLF CRLF );
	if( !MessageContent )
	{
		AddStatus( "Error receiving version number.", g_StatusWarningColor );
		++g_NumWarnings;
		return;
	}

	MessageContent += 4;	// Skip the CRLF CRLF

	// If there's additional content, only get the first line
	char* LineBreak = strstr( MessageContent, LF );
	if( LineBreak )
	{
		*LineBreak = '\0';
	}

	SimpleString LatestVersion = MessageContent;

	STATICHASH( Version );
	STATICHASH( ContentSyncer );
	SimpleString LocalVersion = ConfigManager::GetString( sVersion, "", sContentSyncer );

	if( LocalVersion == LatestVersion )
	{
		AddStatus( "Game is up to date.", g_StatusColor );
		g_ShouldLaunchApp = true;
	}
	else
	{
		AddStatus( "New updates are available.", g_StatusColor );
		BeginUpdating();
	}
}
Example #14
0
MIDIEvent* MIDI::EventFactory( const uint8 EventCode, const IDataStream& Stream ) const
{
	const uint8 MIDIEventType = ( EventCode & 0xF0 ) >> 4;

	if( MIDIEventType == 0x08 )
	{
		// Note off
		return new MIDINoteOffEvent();
	}
	else if( MIDIEventType == 0x09 )
	{
		// Note on
		return new MIDINoteOnEvent();
	}
	else if( MIDIEventType == 0x0A )
	{
		// Note aftertouch
	}
	else if( MIDIEventType == 0x0B )
	{
		// Controller
		return new MIDIControllerEvent();
	}
	else if( MIDIEventType == 0x0C )
	{
		// Program change
		return new MIDIProgramChangeEvent();
	}
	else if( MIDIEventType == 0x0D )
	{
		// Channel aftertouch
	}
	else if( MIDIEventType == 0x0E )
	{
		// Pitch bend
		return new MIDIPitchBendEvent();
	}
	else if( EventCode == 0xF0 || EventCode == 0xF7 )
	{
		// SysEx event

		// For now, skip SysEx events because I don't care (TODO: I'll need to load them to resave them, though)
		const uint SysExLength = LoadVariableLengthValue( Stream );
		Stream.Skip( SysExLength );

		//PRINTF( "Skipped SysEx of length %d\n", SysExLength );

		return NULL;
	}
	else if( EventCode == 0xFF )
	{
		// Meta event
		const uint8 MetaType = Stream.ReadUInt8();
		Unused( MetaType );

		// For now, skip meta events because I don't care (TODO: I'll need to load them to resave them, though)
		const uint MetaLength = LoadVariableLengthValue( Stream );
		//Stream.Skip( MetaLength );
		Array<uint8> MetaString;
		MetaString.Resize( MetaLength );
		Stream.Read( MetaLength, MetaString.GetData() );
		MetaString.PushBack( '\0' );

		//PRINTF( "Skipped meta (0x%02X) of length %d\n", MetaType, MetaLength );
		//PRINTF( "%s\n", MetaString.GetData() );

		return NULL;
	}
	else
	{
		// Unknown event
		WARN;
		return NULL;
	}

	// Not yet handled
	WARN;
	return NULL;
}
Example #15
0
// It might be useful to have some arithmetic parsing for more complex expressions,
// but eventually that would just become writing a whole little language...
// NOTE: This is very error-prone if the format isn't exactly "A OP B", so
// don't use this for anything that the user can touch.
bool ConfigParser::EvaluateConditional( const IDataStream& Stream )
{
	// Parse three tokens: a left side, an operator, and a right side
	// Valid expressions:
	// bool b-op bool
	// int n-op int
	// int n-op float
	// float n-op float
	// float n-op int
	// string s-op string
	// b-op: == !=
	// n-op: < <= > >= == !=
	// s-op: == != ~= ~!= (case-insensitive)

	// Use same rules as above to determine the type of each value
	// This would be a good place to refactor to reuse some code

	SToken::ETokenType LeftSideType = SToken::ET_None;
	SToken::ETokenType RightSideType = SToken::ET_None;

	Array< char > LeftSideString;
	Array< char > OperatorString;
	Array< char > RightSideString;

	char StrMark = '\"';

	// Parse left side
	for(;;)
	{
		char c = Stream.ReadInt8();
		if( c == ' ' || Stream.EOS() )
		{
			LeftSideString.PushBack( '\0' );
			break;
		}
		else
		{
			InnerParse( c, StrMark, LeftSideString, 0, LeftSideType );
		}
	}

	// Parse operator
	for(;;)
	{
		char c = Stream.ReadInt8();
		if( c == ' ' || Stream.EOS() )
		{
			OperatorString.PushBack( '\0' );
			break;
		}
		OperatorString.PushBack( c );
	}

	// Parse right side
	for(;;)
	{
		char c = Stream.ReadInt8();
		if( c == '\0' || c == ' ' || Stream.EOS() )
		{
			RightSideString.PushBack( '\0' );
			break;
		}
		else
		{
			InnerParse( c, StrMark, RightSideString, 0, RightSideType );
		}
	}

	// Evaluate
	if( LeftSideType == RightSideType ||
		( LeftSideType == SToken::ET_Int && RightSideType == SToken::ET_Float ) ||
		( LeftSideType == SToken::ET_Float && RightSideType == SToken::ET_Int ) )
	{
		SimpleString LeftSide = LeftSideString.GetData();
		SimpleString RightSide = RightSideString.GetData();
		SimpleString Operator = OperatorString.GetData();

		if( LeftSideType == SToken::ET_Bool )
		{
			bool LeftSideBool = LeftSide.AsBool();
			bool RightSideBool = RightSide.AsBool();

			if( Operator == "==" )
			{
				return ( LeftSideBool == RightSideBool );
			}
			else if( Operator == "!=" )
			{
				return ( LeftSideBool != RightSideBool );
			}
			else
			{
				DEBUGWARNDESC( "Unknown operator in conditional expression" );
				return false;
			}
		}
		else if( LeftSideType == SToken::ET_Int )
		{
			int LeftSideInt = LeftSide.AsInt();
			int RightSideInt = ( RightSideType == SToken::ET_Int ) ? RightSide.AsInt() : (int)RightSide.AsFloat();

			if( Operator == "==" )
			{
				return ( LeftSideInt == RightSideInt );
			}
			else if( Operator == "!=" )
			{
				return ( LeftSideInt != RightSideInt );
			}
			else if( Operator == "<" )
			{
				return ( LeftSideInt < RightSideInt );
			}
			else if( Operator == "<=" )
			{
				return ( LeftSideInt <= RightSideInt );
			}
			else if( Operator == ">" )
			{
				return ( LeftSideInt > RightSideInt );
			}
			else if( Operator == ">=" )
			{
				return ( LeftSideInt >= RightSideInt );
			}
			else
			{
				DEBUGWARNDESC( "Unknown operator in conditional expression" );
				return false;
			}
		}
		else if( LeftSideType == SToken::ET_Float )
		{
			float LeftSideFloat = LeftSide.AsFloat();
			float RightSideFloat = ( RightSideType == SToken::ET_Float ) ? RightSide.AsFloat() : (float)RightSide.AsInt();

			if( Operator == "==" )
			{
				return ( LeftSideFloat == RightSideFloat );
			}
			else if( Operator == "!=" )
			{
				return ( LeftSideFloat != RightSideFloat );
			}
			else if( Operator == "<" )
			{
				return ( LeftSideFloat < RightSideFloat );
			}
			else if( Operator == "<=" )
			{
				return ( LeftSideFloat <= RightSideFloat );
			}
			else if( Operator == ">" )
			{
				return ( LeftSideFloat > RightSideFloat );
			}
			else if( Operator == ">=" )
			{
				return ( LeftSideFloat >= RightSideFloat );
			}
			else
			{
				DEBUGWARNDESC( "Unknown operator in conditional expression" );
				return false;
			}
		}
		else if( LeftSideType == SToken::ET_String )
		{
			if( Operator == "==" )
			{
				return ( LeftSide == RightSide );
			}
			else if( Operator == "!=" )
			{
				return ( LeftSide != RightSide );
			}
			else if( Operator == "~=" )
			{
				return ( LeftSide.StrICmp( RightSide ) );
			}
			else if( Operator == "~!=" )
			{
				return ( !LeftSide.StrICmp( RightSide ) );
			}
			else
			{
				DEBUGWARNDESC( "Unknown operator in conditional expression" );
				return false;
			}
		}
		else
		{
			DEBUGWARNDESC( "Unknown types in conditional expression" );
			return false;
		}
	}
	else
	{
		DEBUGWARNDESC( "Mismatched types in conditional expression" );
		return false;
	}
}
Example #16
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 );
			}
		}
	}
}
Example #17
0
SimpleString::SimpleString( const Array<char>& String )
:	m_String( NULL )
,	m_Length( 0 )
{
	Initialize( String.GetData() );
}
Mesh* UIWidgetFrame::CreateMesh() const
{
	static const uint kNumVertices	= 16;
	static const uint kNumIndices	= 54;

	const Vector TopLeft		= Vector( m_TopLeft.x, 0.0f, m_TopLeft.y );
	const Vector BottomRight	= TopLeft + Vector( m_Dimensions.x, 0.0f, m_Dimensions.y );

	Array<Vector> Positions;
	Positions.Reserve( kNumVertices );

	{
		Array<float> PositionsX;
		PositionsX.Reserve( 4 );

		PositionsX.PushBack( TopLeft.x );
		PositionsX.PushBack( TopLeft.x + m_Border );
		PositionsX.PushBack( BottomRight.x - m_Border );
		PositionsX.PushBack( BottomRight.x );

		Array<float> PositionsY;
		PositionsY.Reserve( 4 );

		PositionsY.PushBack( TopLeft.z );
		PositionsY.PushBack( TopLeft.z + m_Border );
		PositionsY.PushBack( BottomRight.z - m_Border );
		PositionsY.PushBack( BottomRight.z );

		for( uint Y = 0; Y < 4; ++Y )
		{
			for( uint X = 0; X < 4; ++X )
			{
				Positions.PushBack( Vector( PositionsX[ X ], 0.0f, PositionsY[ Y ] ) );
			}
		}
	}

	Array<Vector2> UVs;
	UVs.Reserve( kNumVertices );

	{
		Array<float> UVValues;
		UVValues.Reserve( 4 );

		UVValues.PushBack( 0.0f );
		UVValues.PushBack( 0.25f );
		UVValues.PushBack( 0.75f );
		UVValues.PushBack( 1.0f );

		for( uint V = 0; V < 4; ++V )
		{
			for( uint U = 0; U < 4; ++U )
			{
				UVs.PushBack( Vector2( UVValues[ U ], UVValues[ V ] ) );
			}
		}
	}

	Array<index_t> Indices;
	Indices.Reserve( kNumIndices );

	for( index_t Y = 0; Y < 3; ++Y )
	{
		for( index_t X = 0; X < 3; ++X )
		{
			const index_t Base = X + Y * 4;
			Indices.PushBack( Base + 0 );
			Indices.PushBack( Base + 4 );
			Indices.PushBack( Base + 1 );
			Indices.PushBack( Base + 4 );
			Indices.PushBack( Base + 5 );
			Indices.PushBack( Base + 1 );
		}
	}

	IRenderer* const			pRenderer			= m_UIManager->GetRenderer();
	IVertexBuffer* const		VertexBuffer		= pRenderer->CreateVertexBuffer();
	IVertexDeclaration* const	VertexDeclaration	= pRenderer->GetVertexDeclaration( VD_POSITIONS | VD_UVS );
	IIndexBuffer* const			IndexBuffer			= pRenderer->CreateIndexBuffer();

	IVertexBuffer::SInit InitStruct;
	InitStruct.NumVertices	= kNumVertices;
	InitStruct.Positions	= Positions.GetData();
	InitStruct.UVs			= UVs.GetData();

	VertexBuffer->Init( InitStruct );
	IndexBuffer->Init( kNumIndices, Indices.GetData() );
	IndexBuffer->SetPrimitiveType( EPT_TRIANGLELIST );

	Mesh* const pMesh = new Mesh( VertexBuffer, VertexDeclaration, IndexBuffer );

	pMesh->m_AABB = AABB( TopLeft, BottomRight );

	return pMesh;
}
void UIScreenEldMirror::CreateBackdropMesh()
{
	ASSERT( !m_BackdropMesh );

	EldritchFramework* const	pFramework		= EldritchFramework::GetInstance();
	EldritchWorld* const		pWorld			= pFramework->GetWorld();
	IRenderer* const			pRenderer		= pFramework->GetRenderer();

	ASSERT( pWorld );

	static const uint kNumVertices	= 4;
	static const uint kNumIndices	= 6;

	Vector2 UVMin;
	Vector2 UVMax;
	pWorld->GetTileUVs( m_MirrorBackdropTile, UVMin, UVMax );

	Array<Vector>	Positions;
	Array<Vector4>	Colors;
	Array<Vector2>	UVs;
	Array<index_t>	Indices;

	// For beauty lighting with cube lights
	const Matrix	MirrorRotation	= Matrix::CreateRotationAboutZ( m_MirrorYaw );

	Positions.PushBack( MirrorRotation * Vector( m_MirrorBackdropExtents,	-m_MirrorBackdropDistance, -m_MirrorBackdropExtents + m_MirrorViewHeight ) );
	Positions.PushBack( MirrorRotation * Vector( -m_MirrorBackdropExtents,	-m_MirrorBackdropDistance, -m_MirrorBackdropExtents + m_MirrorViewHeight ) );
	Positions.PushBack( MirrorRotation * Vector( m_MirrorBackdropExtents,	-m_MirrorBackdropDistance, m_MirrorBackdropExtents + m_MirrorViewHeight ) );
	Positions.PushBack( MirrorRotation * Vector( -m_MirrorBackdropExtents,	-m_MirrorBackdropDistance, m_MirrorBackdropExtents + m_MirrorViewHeight ) );

	Colors.PushBack( m_MirrorBackdropColor );
	Colors.PushBack( m_MirrorBackdropColor );
	Colors.PushBack( m_MirrorBackdropColor );
	Colors.PushBack( m_MirrorBackdropColor );

	UVs.PushBack( Vector2( UVMin.uv_u, UVMax.uv_v ) );
	UVs.PushBack( Vector2( UVMax.uv_u, UVMax.uv_v ) );
	UVs.PushBack( Vector2( UVMin.uv_u, UVMin.uv_v ) );
	UVs.PushBack( Vector2( UVMax.uv_u, UVMin.uv_v ) );

	Indices.PushBack( 0 );
	Indices.PushBack( 1 );
	Indices.PushBack( 3 );
	Indices.PushBack( 0 );
	Indices.PushBack( 3 );
	Indices.PushBack( 2 );

	IVertexBuffer* const		pVertexBuffer		= pRenderer->CreateVertexBuffer();
	IVertexDeclaration* const	pVertexDeclaration	= pRenderer->GetVertexDeclaration( VD_POSITIONS | VD_FLOATCOLORS_SM2 | VD_UVS );
	IIndexBuffer* const			pIndexBuffer		= pRenderer->CreateIndexBuffer();
	IVertexBuffer::SInit InitStruct;
	InitStruct.NumVertices	= kNumVertices;
	InitStruct.Positions	= Positions.GetData();
	InitStruct.FloatColors1	= Colors.GetData();
	InitStruct.UVs			= UVs.GetData();
	pVertexBuffer->Init( InitStruct );
	pIndexBuffer->Init( kNumIndices, Indices.GetData() );
	pIndexBuffer->SetPrimitiveType( EPT_TRIANGLELIST );

	m_BackdropMesh = new Mesh( pVertexBuffer, pVertexDeclaration, pIndexBuffer );

	m_BackdropMesh->SetTexture( 0, pWorld->GetTileTexture() );
	m_BackdropMesh->SetMaterialDefinition( "Material_World", pRenderer );
	m_BackdropMesh->SetMaterialFlags( MAT_OFFSCREEN_0 | MAT_ALWAYS );
}