示例#1
0
文件: OrgOp.cpp 项目: eriser/es
bool COrgOp::Decode_GetNextLine( CStr &roDst, CStr &roSrc ) const
{
	int j;

	j = roSrc.Find( 0, ORG_OP_DELIM );
	if( j < 0 )
		return false;
	roSrc.Del( 0, ++j );

	j = roSrc.Find( 0, ORG_OP_NEWLINE );
	if( j < 0 )
		return false;
	roDst = roSrc.GetSub( 0, j );
	roSrc.Del( 0, j+sizeof( ORG_OP_NEWLINE ) );
	ORG_OP_LOG( "line: %s\n", roDst.GetData() );
	return true;
}
示例#2
0
文件: OrgOp.cpp 项目: eriser/es
bool COrgOp::Decode_GetNextToken( CStr &roDst, CStr &roSrc ) const
{
	int j = roSrc.Find( 0, ORG_OP_DELIM );
	if( j < 0 )
		return false;
	roDst = roSrc.GetSub( 0, j );
	roSrc.Del( 0, j+1 ); // ORG_OP_DELIM auch löschen
	ORG_OP_LOG( "token: %s\n", roDst.GetData() );
	return true;
}
示例#3
0
int
CIniFile::Split( const CStr &source, LPCTSTR sep, CStrArray &dest, BOOL trim /* = TRUE */ )
{
	int pos = source.Find( sep );
	int startPos = 0;
	CStr elem;
	int sepLen = wcslen( sep );

	dest.RemoveAll();
	while( pos != -1 )
	{
		elem = source.Mid( startPos, pos-startPos );
        if ( trim ) { elem.TrimLeft(); elem.TrimRight(); }
		dest.Add( elem );

		startPos = pos+sepLen;
		pos      = source.Find( sep, startPos );
	}
	elem = source.Mid( startPos );
    if ( trim ) { elem.TrimLeft(); elem.TrimRight(); }
	dest.Add( elem );

	return dest.GetSize();
}
示例#4
0
void CCurvePathBezier3::Load( const CStr &roData )
{
	Clear();
	
	int i = 0;
	while( true )
	{
		const int j = roData.Find( i, DELIM );
		if( j < 0 )
			break;
		CCurveBezier3 *poC = new CCurveBezier3;
		poC->Load( roData.GetSub( i, j-i ) );
		m_oLstCurve.Append( poC );
		i = j + 1;
	}
}
示例#5
0
void CCurveBezier3::Load( const CStr &roData )
{
	const char * pcD = roData.GetData();
	unsigned int i = 0;
	unsigned int uiVertex = 0, uiToken = 0, uiSub = 0;
	
	while( true )
	{
		const int j = roData.Find( i, DELIM );
		if( j < 0 )
			break;
		float fVal;
		sscanf( pcD + i, "%g", &fVal );
		switch( uiToken )
		{
		case 0:
			m_aoVertex[uiVertex].m_oPos[uiSub] = fVal;
			if( ++uiSub >= 4 )
			{
				uiSub = 0;
				++uiToken;
			}
		break;
		case 1:
			m_aoVertex[uiVertex].m_oColor[uiSub] = fVal;
			if( ++uiSub >= 4 )
			{
				uiSub = 0;
				++uiToken;
			}
		break;
		case 2:
			m_aoVertex[uiVertex].m_fWeight0 = fVal;
			if( ++uiSub >= 1 )
			{
				m_aoVertex[uiVertex].m_uiVertex = uiVertex;
				uiSub = 0;
				uiToken = 0;
				++uiVertex;
				if( uiVertex >= 4 )
					break;
			}
		break;
		}
		i = j + 1;
	}
}
示例#6
0
bool CPrsBDF::Parse( const char *pcFont )
{
#define TOK(T) TPairTokenNameID( #T, PBDF_TOKEN_##T )
	static const TPairTokenNameID m_aoToken_[] = 
	{
		TOK( STARTFONT ),
		TOK( COMMENT ),
		TOK( CONTENTVERSION ),
		TOK( FONT ),
		TOK( SIZE ),
		TOK( FONTBOUNDINGBOX ),
		TOK( METRICSSET ),
		TOK( SWIDTH ),
		TOK( DWIDTH ),
		TOK( SWIDTH1 ),
		TOK( DWIDTH1 ),
		TOK( VVECTOR ),
		TOK( STARTPROPERTIES ),
		TOK( ENDPROPERTIES ),
		TOK( CHARS ),
		TOK( STARTCHAR ),
		TOK( ENCODING ),
		TOK( BBX ),
		TOK( BITMAP ),
		TOK( ENDCHAR ),
		TOK( ENDFONT )
	};
	static const unsigned int uiTokenNum = sizeof( m_aoToken_ ) / sizeof( TPairTokenNameID );
	CStr oStrFontFile( pcFont );
	const int iFontSize = oStrFontFile.GetSize();
	int iPropertiesStartPos = -1;
	CGlyph oGylphNew;
	CGlyph *poGlyph = &m_oGlyphDefault;
	bool bIsReadingChar = false;
	
	Reset();
	
	PBDF_LOG( "parse: start\n" );
	
	int iPos = 0;
	while( iPos < iFontSize )
	{
		int iEndOfLine = oStrFontFile.Find( iPos, PBDF_NEWLINE );
		if( iEndOfLine < 0 )
			iEndOfLine = iFontSize;
		
		CStr oStrLine = oStrFontFile.GetSub( iPos, iEndOfLine - iPos );
		RemoveLeadingSpace( oStrLine );
		
		//PBDF_LOG( "line: %s", oStrLine.GetData() );
		//PBDF_LOG( "line_size: %s", oStrLine.GetSize() );
		
		unsigned int uiTokenNext = PBDF_TOKEN_NONE;
		
		for( unsigned int t=0; t<uiTokenNum; ++t )
		{
			CStr oStrToken = m_aoToken_[t].GetFirst() ;
			const unsigned int uiTokenSize = oStrToken.GetSize();
			
			//PBDF_LOG( "token: %s", oStrToken.GetData() );
			
			int iPosToken = oStrLine.Find( 0, oStrToken );
			if( iPosToken != 0 ) 
				continue;
			
			// Danach müssen Leerzeichen oder das Ende folgen!
			const unsigned int uiPosNext = iPosToken + uiTokenSize;
			if( uiPosNext < oStrLine.GetSize() )
			{
				const char cNext = oStrLine[ uiPosNext ];
				if( !( cNext == ' ' || cNext == '\t' ) )
					continue;
			}
			
			if( iPosToken >= 0 )
			{
				oStrLine.Del( 0, uiTokenSize );
				RemoveLeadingSpace( oStrLine );
				uiTokenNext = m_aoToken_[t].GetSecond();
				PBDF_LOG( "token: %s\n", oStrToken.GetData() );
				break;
			}
		}
		
		if( uiTokenNext != PBDF_TOKEN_NONE )
		{
			switch( uiTokenNext )
			{
			case PBDF_TOKEN_STARTFONT:
				ReadValue( oStrLine, &m_dVersion );
				PBDF_LOG( "version: %g\n", m_dVersion );
			break;
			case PBDF_TOKEN_COMMENT:
			break;
			case PBDF_TOKEN_CONTENTVERSION: // optional
				ReadValue( oStrLine, &m_iContentVersion );
				PBDF_LOG( "content_version: %d\n", m_iContentVersion );
			break;
			case PBDF_TOKEN_FONT:
				ReadValue( oStrLine, &m_oStrFont );
				PBDF_LOG( "font: %s\n", m_oStrFont.GetData() );
			break;
			case PBDF_TOKEN_SIZE:
				ReadValue( oStrLine, &m_iPointSize );
				PBDF_LOG( "point_size: %d\n", m_iPointSize );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &m_iResX );
				PBDF_LOG( "res_x: %d\n", m_iResX );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &m_iResY );
				PBDF_LOG( "res_y: %d\n", m_iResY );
			break;
			case PBDF_TOKEN_FONTBOUNDINGBOX:
				ReadValue( oStrLine, &m_iBBX );
				PBDF_LOG( "bounding_box_x: %d\n", m_iBBX );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &m_iBBY );
				PBDF_LOG( "bounding_box_y: %d\n", m_iBBY );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &m_iOffX );
				PBDF_LOG( "offset_y: %d\n", m_iOffX );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &m_iOffY );
				PBDF_LOG( "offset_x: %d\n", m_iOffY );
				RemoveNextWord( oStrLine );
			break;
			case PBDF_TOKEN_METRICSSET: // optional
				ReadValue( oStrLine, &m_iMetricsSet );
				PBDF_LOG( "metrics_set: %d\n", m_iMetricsSet );
			break;
			case PBDF_TOKEN_SWIDTH:
				ReadValue( oStrLine, &poGlyph->m_dSX );
				PBDF_LOG( "sx: %g\n", poGlyph->m_dSX );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &poGlyph->m_dSY );
				PBDF_LOG( "sy: %g\n", poGlyph->m_dSY );
			break;
			case PBDF_TOKEN_DWIDTH:
				ReadValue( oStrLine, &poGlyph->m_iDX );
				PBDF_LOG( "dx: %d\n", poGlyph->m_iDX );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &poGlyph->m_iDY );
				PBDF_LOG( "dy: %d\n", poGlyph->m_iDY );
			break;
			case PBDF_TOKEN_SWIDTH1:
				ReadValue( oStrLine, &poGlyph->m_dSX1 );
				PBDF_LOG( "sx1: %g\n", poGlyph->m_dSX1 );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &poGlyph->m_dSY1 );
				PBDF_LOG( "sy1: %g\n", poGlyph->m_dSY1 );
			break;
			case PBDF_TOKEN_DWIDTH1:
				ReadValue( oStrLine, &poGlyph->m_iDX1 );
				PBDF_LOG( "dx1: %d\n", poGlyph->m_iDX1 );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &poGlyph->m_iDY1 );
				PBDF_LOG( "dy1: %d\n", poGlyph->m_iDY1 );
			break;
			case PBDF_TOKEN_VVECTOR: // optional
				ReadValue( oStrLine, &poGlyph->m_dVVX );
				PBDF_LOG( "vvx: %g\n", poGlyph->m_dVVX );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &poGlyph->m_dVVY );
				PBDF_LOG( "vvy: %g\n", poGlyph->m_dVVY );
			break;
			case PBDF_TOKEN_STARTPROPERTIES: // optional
				ReadValue( oStrLine, &m_iProperties );
				PBDF_LOG( "properties: %d\n", m_iProperties );
				iPropertiesStartPos = iEndOfLine + 1;
			break;
			case PBDF_TOKEN_ENDPROPERTIES: // optional
				if( iPropertiesStartPos < 0 )
					break;
				m_oStrProperties = oStrFontFile.GetSub( 
					iPropertiesStartPos, iPos - iPropertiesStartPos );
				PBDF_LOG( "properties:\n%s\n", m_oStrProperties.GetData() );
			break;
			case PBDF_TOKEN_CHARS:
				ReadValue( oStrLine, &m_iChars );
				PBDF_LOG( "chars: %d\n", m_iChars );
				
				poGlyph = &oGylphNew;
			break;
			case PBDF_TOKEN_STARTCHAR:
				if( bIsReadingChar )
				{
					PBDF_ERROR( "glyph %s\n", oStrLine.GetData() );
					return false;
				}
				bIsReadingChar = true;
				
				oGylphNew = m_oGlyphDefault;
				ReadValue( oStrLine, &poGlyph->m_oStrName );
				PBDF_LOG( "char_name: %s\n", poGlyph->m_oStrName.GetData() );
				PBDF_LOG( "char_num: %d\n", m_oArrGlyph.GetSize() );
			break;
			case PBDF_TOKEN_ENCODING:
				ReadValue( oStrLine, &poGlyph->m_iEncoding0  );
				PBDF_LOG( "encoding0: %d\n", poGlyph->m_iEncoding0 );
				RemoveNextWord( oStrLine );
				if( !oStrLine.GetSize() )
					break;
				ReadValue( oStrLine, &poGlyph->m_iEncoding1 );
				PBDF_LOG( "encoding1: %d\n", poGlyph->m_iEncoding1 );
			break;
			case PBDF_TOKEN_BBX:
				ReadValue( oStrLine, &poGlyph->m_iBBX );
				PBDF_LOG( "bbx: %d\n", poGlyph->m_iBBX );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &poGlyph->m_iBBY );
				PBDF_LOG( "bby: %d\n", poGlyph->m_iBBY );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &poGlyph->m_iBBOffX );
				PBDF_LOG( "bb_off_x: %d\n", poGlyph->m_iBBOffX );
				RemoveNextWord( oStrLine );
				ReadValue( oStrLine, &poGlyph->m_iBBOffY );
				PBDF_LOG( "bb_off_y: %d\n", poGlyph->m_iBBOffY );
			break;
			case PBDF_TOKEN_BITMAP:
			{
				CArray<unsigned char> oArrBitmap;
				const int iHeight = poGlyph->m_iBBY;
				
				// Da hier sowieso kein Token folgt, kann ohne weiteres
				// auch über das Zeilenende hinaus gearbeitet werden.
				int iPosBegin = iEndOfLine + 1;
				int l = 0;
				
				poGlyph->m_oArrBitmap.Clear();
				
				while( l < iHeight )
				{
					const int iEOL = oStrFontFile.Find( iPosBegin, PBDF_NEWLINE ); 
					if( iEOL < 0 )
						break;
					CStr oCodeLine = oStrFontFile.GetSub( iPosBegin, iEOL - iPosBegin );
					ReadValue( oCodeLine, &oArrBitmap );
					poGlyph->m_oArrBitmap.Append( oArrBitmap );
					iPosBegin = iEOL + 1;
					++l;
				}		
			}
			break;
			case PBDF_TOKEN_ENDCHAR:
				m_oArrGlyph.Append( oGylphNew );
				bIsReadingChar = false;
			break;
			case PBDF_TOKEN_ENDFONT:
				PBDF_LOG( "glyph_count: %d\n", m_oArrGlyph.GetSize() );
				if( m_oArrGlyph.GetSize() != (unsigned int)m_iChars )
				{
					PBDF_ERROR( "glyph_cout: %d != %d", m_oArrGlyph.GetSize(), m_iChars );
					return false;
				}
			break;
			};
		}
		iPos = iEndOfLine + 1; // falls "\r\n"??
	}
	
	PBDF_LOG( "parse: end\n" );
	return true;
}
示例#7
0
void GUIRenderer::UpdateDrawCallCache(DrawCalls& Calls, const CStr& SpriteName, const CRect& Size, int CellID, std::map<CStr, CGUISprite*>& Sprites)
{
	// This is called only when something has changed (like the size of the
	// sprite), so it doesn't need to be particularly efficient.

	// Clean up the old data
	Calls.clear();

	// If this object has zero size, there's nothing to render. (This happens
	// with e.g. tooltips that have zero size before they're first drawn, so
	// it isn't necessarily an error.)
	if (Size.left == Size.right && Size.top == Size.bottom)
		return;


	std::map<CStr, CGUISprite*>::iterator it(Sprites.find(SpriteName));
	if (it == Sprites.end())
	{
		/*
		 * Sprite not found. Check whether this a special sprite,
		 * and if so create a new sprite:
		 * "stretched:filename.ext" - stretched image
		 * "stretched:grayscale:filename.ext" - stretched grayscale image.
		 * "cropped:0.5, 0.25"    - stretch this ratio (x,y) of the top left of the image
		 * "color:r g b a"        - solid color
		 *     > "textureAsMask"  - when using color, use the (optional) texture alpha channel as mask.
		 * These can be combined, but they must be separated by a ":"
		 * so you can have a white overlay over an stretched grayscale image with:
		 * "grayscale:color:255 255 255 100:stretched:filename.ext"
		 */
		// Check that this can be a special sprite.
		if (SpriteName.ReverseFind(":") == -1 && SpriteName.Find("color(") == -1)
		{
			LOGERROR("Trying to use a sprite that doesn't exist (\"%s\").", SpriteName.c_str());
			return;
		}
		CGUISprite* Sprite = new CGUISprite;
		VfsPath TextureName = VfsPath("art/textures/ui") / wstring_from_utf8(SpriteName.AfterLast(":"));
		if (SpriteName.Find("stretched:") != -1)
		{
			// TODO: Should check (nicely) that this is a valid file?
			SGUIImage* Image = new SGUIImage;

			Image->m_TextureName = TextureName;
			// Allow grayscale images for disabled portraits
			if (SpriteName.Find("grayscale:") != -1)
			{
				Image->m_Effects = new SGUIImageEffects;
				Image->m_Effects->m_Greyscale = true;
			}

			CClientArea ca(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
			Image->m_Size = ca;
			Image->m_TextureSize = ca;

			Sprite->AddImage(Image);

			Sprites[SpriteName] = Sprite;
		}
		else if (SpriteName.Find("cropped:") != -1)
		{
			// TODO: Should check (nicely) that this is a valid file?
			SGUIImage* Image = new SGUIImage;

			CStr info = SpriteName.AfterLast("cropped:").BeforeFirst(":");
			double xRatio = info.BeforeFirst(",").ToDouble();
			double yRatio = info.AfterLast(",").ToDouble();

			Image->m_TextureName = TextureName;

			CClientArea ca(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
			CClientArea cb(CRect(0, 0, 0, 0), CRect(0, 0, 100/xRatio, 100/yRatio));
			Image->m_Size = ca;
			Image->m_TextureSize = cb;

			Sprite->AddImage(Image);

			Sprites[SpriteName] = Sprite;
		}
		if (SpriteName.Find("color:") != -1)
		{
			CStrW value = wstring_from_utf8(SpriteName.AfterLast("color:").BeforeFirst(":"));
			CColor color;

			// Check color is valid
			if (!GUI<CColor>::ParseString(value, color))
			{
				LOGERROR("GUI: Error parsing sprite 'color' (\"%s\")", utf8_from_wstring(value));
				return;
			}

			SGUIImage* Image = new SGUIImage;

			// If we are using a mask, this is an effect.
			// Otherwise we can fallback to the "back color" attribute
			// TODO: we are assuming there is a filename here.
			if (SpriteName.Find("textureAsMask:") != -1)
			{
				Image->m_TextureName = TextureName;
				Image->m_Effects = new SGUIImageEffects;
				Image->m_Effects->m_SolidColor = color;
			}
			else
				Image->m_BackColor = color;

			CClientArea ca(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
			Image->m_Size = ca;
			Image->m_TextureSize = ca;

			Sprite->AddImage(Image);

			Sprites[SpriteName] = Sprite;
		}
		it = Sprites.find(SpriteName);

		// Otherwise, just complain and give up:
		if (it == Sprites.end())
		{
			SAFE_DELETE(Sprite);
			LOGERROR("Trying to use a sprite that doesn't exist (\"%s\").", SpriteName.c_str());
			return;
		}
	}

	Calls.reserve(it->second->m_Images.size());

	// Iterate through all the sprite's images, loading the texture and
	// calculating the texture coordinates
	std::vector<SGUIImage*>::const_iterator cit;
	for (cit = it->second->m_Images.begin(); cit != it->second->m_Images.end(); ++cit)
	{
		SDrawCall Call(*cit); // pointers are safe since we never modify sprites/images after startup

		CRect ObjectSize = (*cit)->m_Size.GetClientArea(Size);

		if (ObjectSize.GetWidth() == 0.0 || ObjectSize.GetHeight() == 0.0)
		{
			// Zero sized object. Don't report as an error, since it's common for e.g. hitpoint bars.
			continue; // i.e. don't continue with this image
		}

		Call.m_Vertices = ObjectSize;
		if ((*cit)->m_RoundCoordinates)
		{
			// Round the vertex coordinates to integers, to avoid ugly filtering artifacts
			Call.m_Vertices.left = (int)(Call.m_Vertices.left + 0.5f);
			Call.m_Vertices.right = (int)(Call.m_Vertices.right + 0.5f);
			Call.m_Vertices.top = (int)(Call.m_Vertices.top + 0.5f);
			Call.m_Vertices.bottom = (int)(Call.m_Vertices.bottom + 0.5f);
		}

		if (!(*cit)->m_TextureName.empty())
		{
			CTextureProperties textureProps(g_L10n.LocalizePath((*cit)->m_TextureName));
			textureProps.SetWrap((*cit)->m_WrapMode);
			CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps);
			texture->Prefetch();
			Call.m_HasTexture = true;
			Call.m_Texture = texture;

			Call.m_EnableBlending = false; // will be overridden if the texture has an alpha channel

			Call.m_ObjectSize = ObjectSize;
			Call.m_CellID = CellID;
		}
		else
		{
			Call.m_HasTexture = false;
			// Enable blending if it's transparent (allowing a little error in the calculations)
			Call.m_EnableBlending = !(fabs((*cit)->m_BackColor.a - 1.0f) < 0.0000001f);
		}

		Call.m_BackColor = (*cit)->m_BackColor;
		Call.m_BorderColor = (*cit)->m_Border ? (*cit)->m_BorderColor : CColor();
		Call.m_DeltaZ = (*cit)->m_DeltaZ;

		if (!Call.m_HasTexture)
		{
			Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid);
		}
		else if ((*cit)->m_Effects)
		{
			if ((*cit)->m_Effects->m_AddColor != CColor())
			{
				Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect(str_gui_add);
				Call.m_ShaderColorParameter = (*cit)->m_Effects->m_AddColor;
				// Always enable blending if something's being subtracted from
				// the alpha channel
				if ((*cit)->m_Effects->m_AddColor.a < 0.f)
					Call.m_EnableBlending = true;
			}
			else if ((*cit)->m_Effects->m_Greyscale)
			{
				Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect(str_gui_grayscale);
			}
			else if ((*cit)->m_Effects->m_SolidColor != CColor())
			{
				Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid_mask);
				Call.m_ShaderColorParameter = (*cit)->m_Effects->m_SolidColor;
				Call.m_EnableBlending = !(fabs((*cit)->m_Effects->m_SolidColor.a - 1.0f) < 0.0000001f);
			}
			else /* Slight confusion - why no effects? */
			{
				Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect(str_gui_basic);
			}
		}
		else
		{
			Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect(str_gui_basic);
		}

		Calls.push_back(Call);
	}
}
示例#8
0
void
CIniFile::Parse( LPCTSTR cont )
{
	CStr content = cont;
	CStr sectionName, key, value;
    CMapStrToString *section = NULL;
	BOOL hasEmptySection = FALSE;

	Sections.RemoveAll();

	while ( content.GetLength() > 0 )
	{
		CStr line;
		int pos = content.Find( _T("\n") );
		if ( pos != -1 )
		{
			line    = content.Left( pos );
			content = content.Mid( pos+1 );
		}
		else
		{
			line = content;
			content = _T("");
		}
		line.TrimLeft(); line.TrimRight();

		if ( line.GetLength() > 0 && line.GetAt(0) != '#' && line.GetAt(0) != ';' )
		{
			if ( line.GetAt(0) == '[' && line.Right(1) == L"]" )
			{
				sectionName = line.Mid( 1, line.GetLength()-2 );
                sectionName.MakeLower();
                section = new CMapStrToString();
                Sections.SetAt( sectionName, section );
			}
			else
			{
				int eqPos = line.Find( '=' );
				if ( eqPos != -1 )
				{
					key   = line.Left( eqPos );
					key.TrimLeft(); key.TrimRight();
					value = line.Mid( eqPos+1 );
					value.TrimLeft(); value.TrimRight();
					if ( value.Left(1) == L"\"" && value.Right(1) == L"\"" )
					{
						value = value.Mid( 1, value.GetLength()-2 );
					}
					key.MakeLower();
					if ( section == NULL && hasEmptySection == FALSE )
					{
						section = new CMapStrToString();
						Sections.SetAt( L"", section );
						hasEmptySection = TRUE;
					}
					section->SetAt( key, value );
				}
			}
		}
	}
}
示例#9
0
void ActorViewer::SetActor(const CStrW& name, const CStrW& animation, player_id_t playerID)
{
	bool needsAnimReload = false;

	CStrW id = name;

	// Recreate the entity, if we don't have one or if the new one is different
	if (m.Entity == INVALID_ENTITY || id != m.CurrentUnitID)
	{
		// Delete the old entity (if any)
		if (m.Entity != INVALID_ENTITY)
		{
			m.Simulation2.DestroyEntity(m.Entity);
			m.Simulation2.FlushDestroyedEntities();
			m.Entity = INVALID_ENTITY;
		}

		// Clear particles associated with deleted entity
		g_Renderer.GetParticleManager().ClearUnattachedEmitters();

		// If there's no actor to display, return with nothing loaded
		if (id.empty())
			return;

		m.Entity = m.Simulation2.AddEntity(L"preview|" + id);
		if (m.Entity == INVALID_ENTITY)
			return;

		CmpPtr<ICmpPosition> cmpPosition(m.Simulation2, m.Entity);
		if (cmpPosition)
		{
			ssize_t c = TERRAIN_TILE_SIZE * m.Terrain.GetPatchesPerSide()*PATCH_SIZE/2;
			cmpPosition->JumpTo(entity_pos_t::FromInt(c), entity_pos_t::FromInt(c));
			cmpPosition->SetYRotation(entity_angle_t::Pi());
		}

		CmpPtr<ICmpOwnership> cmpOwnership(m.Simulation2, m.Entity);
		if (cmpOwnership)
			cmpOwnership->SetOwner(playerID);

		needsAnimReload = true;
	}

	if (animation != m.CurrentUnitAnim)
		needsAnimReload = true;

	if (needsAnimReload)
	{
		CStr anim = animation.ToUTF8().LowerCase();

		// Emulate the typical simulation animation behaviour
		float speed;
		float repeattime = 0.f;
		if (anim == "walk")
		{
			CmpPtr<ICmpUnitMotion> cmpUnitMotion(m.Simulation2, m.Entity);
			if (cmpUnitMotion)
				speed = cmpUnitMotion->GetWalkSpeed().ToFloat();
			else
				speed = 7.f; // typical unit speed

			m.CurrentSpeed = speed;
		}
		else if (anim == "run")
		{
			CmpPtr<ICmpUnitMotion> cmpUnitMotion(m.Simulation2, m.Entity);
			if (cmpUnitMotion)
				speed = cmpUnitMotion->GetRunSpeed().ToFloat();
			else
				speed = 12.f; // typical unit speed

			m.CurrentSpeed = speed;
		}
		else if (anim == "melee")
		{
			speed = 1.f; // speed will be ignored if we have a repeattime
			m.CurrentSpeed = 0.f;

			CStr code = "var cmp = Engine.QueryInterface("+CStr::FromUInt(m.Entity)+", IID_Attack); " +
				"if (cmp) cmp.GetTimers(cmp.GetBestAttack()).repeat; else 0;";
			m.Simulation2.GetScriptInterface().Eval(code.c_str(), repeattime);
		}
		else
		{
			// Play the animation at normal speed, but movement speed is zero
			speed = 1.f;
			m.CurrentSpeed = 0.f;
		}

		CStr sound;
		if (anim == "melee")
			sound = "attack";
		else if (anim == "build")
			sound = "build";
		else if (anim.Find("gather_") == 0)
			sound = anim;

		std::wstring soundgroup;
		if (!sound.empty())
		{
			CStr code = "var cmp = Engine.QueryInterface("+CStr::FromUInt(m.Entity)+", IID_Sound); " +
				"if (cmp) cmp.GetSoundGroup('"+sound+"'); else '';";
			m.Simulation2.GetScriptInterface().Eval(code.c_str(), soundgroup);
		}

		CmpPtr<ICmpVisual> cmpVisual(m.Simulation2, m.Entity);
		if (cmpVisual)
		{
			// TODO: SetEntitySelection(anim)
			cmpVisual->SelectAnimation(anim, false, fixed::FromFloat(speed), soundgroup);
			if (repeattime)
				cmpVisual->SetAnimationSyncRepeat(fixed::FromFloat(repeattime));
		}

		// update prop list for new entity/animation (relies on needsAnimReload also getting called for entire entity changes)
		m.UpdatePropList();
	}

	m.CurrentUnitID = id;
	m.CurrentUnitAnim = animation;
}