Beispiel #1
0
// Run through a string copying ident to buffer
int CExpression::ConsumeAppendIdentifier(char* buf, const char* str)
{
	int i;

	bool alpha = false;
	bool floatNum = false;

	// Read chars up to first '.': if only digits, interpret as being a number and continue.  Else, use as identifier.
	for (i = 0; ; i++) {
		if (str[i] == '.')
			break;
		if (IsChAlpha(str[i]))
			alpha = true;
		else if (!IsChDigit(str[i]) && str[i] != '[' && str[i] != ']')
			break;
		buf[i] = str[i];
	}

	// Identifier found
	if (alpha) {
		buf[i] = NULL;
		AppendToken(T_IDENTIFIER, buf);
		CheckForKeywords(toks[toks.size() - 1]);
		return i - 1;
	}
	else if (str[i] == '.') {

		// Continue with dot
		buf[i++] = '.';
		floatNum = true;
	}

	// Only digits preceding .
	// Carry on reading digits
	for ( ; (str[i] <= '9' && str[i] >= '0'); i++)
		buf[i] = str[i];

	buf[i] = NULL;

	if (floatNum)
		AppendToken(T_FLOAT, buf);
	else
		AppendToken(T_INTEGER, buf);

	return i-1;
}
Beispiel #2
0
/*
===================
R_ParseImageProgram_r

If pic is NULL, the timestamps will be filled in, but no image will be generated
If both pic and timestamps are NULL, it will just advance past it, which can be
used to parse an image program from a text stream.
===================
*/
static bool R_ParseImageProgram_r( idLexer &src, byte **pic, int *width, int *height,
								  ID_TIME_T *timestamps, textureDepth_t *depth ) {
	idToken		token;
	float		scale;
	ID_TIME_T		timestamp;

	src.ReadToken( &token );
	AppendToken( token );

	if ( !token.Icmp( "heightmap" ) ) {
		MatchAndAppendToken( src, "(" );

		if ( !R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ) ) {
			return false;
		}

		MatchAndAppendToken( src, "," );

		src.ReadToken( &token );
		AppendToken( token );
		scale = token.GetFloatValue();
		
		// process it
		if ( pic ) {
			R_HeightmapToNormalMap( *pic, *width, *height, scale );
			if ( depth ) {
				*depth = TD_BUMP;
			}
		}

		MatchAndAppendToken( src, ")" );
		return true;
	}

	if ( !token.Icmp( "addnormals" ) ) {
		byte	*pic2;
		int		width2, height2;

		MatchAndAppendToken( src, "(" );

		if ( !R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ) ) {
			return false;
		}

		MatchAndAppendToken( src, "," );

		if ( !R_ParseImageProgram_r( src, pic ? &pic2 : NULL, &width2, &height2, timestamps, depth ) ) {
			if ( pic ) {
				R_StaticFree( *pic );
				*pic = NULL;
			}
			return false;
		}
		
		// process it
		if ( pic ) {
			R_AddNormalMaps( *pic, *width, *height, pic2, width2, height2 );
			R_StaticFree( pic2 );
			if ( depth ) {
				*depth = TD_BUMP;
			}
		}

		MatchAndAppendToken( src, ")" );
		return true;
	}

	if ( !token.Icmp( "smoothnormals" ) ) {
		MatchAndAppendToken( src, "(" );

		if ( !R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ) ) {
			return false;
		}

		if ( pic ) {
			R_SmoothNormalMap( *pic, *width, *height );
			if ( depth ) {
				*depth = TD_BUMP;
			}
		}

		MatchAndAppendToken( src, ")" );
		return true;
	}

	if ( !token.Icmp( "add" ) ) {
		byte	*pic2;
		int		width2, height2;

		MatchAndAppendToken( src, "(" );

		if ( !R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ) ) {
			return false;
		}

		MatchAndAppendToken( src, "," );

		if ( !R_ParseImageProgram_r( src, pic ? &pic2 : NULL, &width2, &height2, timestamps, depth ) ) {
			if ( pic ) {
				R_StaticFree( *pic );
				*pic = NULL;
			}
			return false;
		}
		
		// process it
		if ( pic ) {
			R_ImageAdd( *pic, *width, *height, pic2, width2, height2 );
			R_StaticFree( pic2 );
		}

		MatchAndAppendToken( src, ")" );
		return true;
	}

	if ( !token.Icmp( "scale" ) ) {
		float	scale[4];
		int		i;

		MatchAndAppendToken( src, "(" );

		R_ParseImageProgram_r( src, pic, width, height, timestamps, depth );

		for ( i = 0 ; i < 4 ; i++ ) {
			MatchAndAppendToken( src, "," );
			src.ReadToken( &token );
			AppendToken( token );
			scale[i] = token.GetFloatValue();
		}

		// process it
		if ( pic ) {
			R_ImageScale( *pic, *width, *height, scale );
		}

		MatchAndAppendToken( src, ")" );
		return true;
	}

	if ( !token.Icmp( "invertAlpha" ) ) {
		MatchAndAppendToken( src, "(" );

		R_ParseImageProgram_r( src, pic, width, height, timestamps, depth );

		// process it
		if ( pic ) {
			R_InvertAlpha( *pic, *width, *height );
		}

		MatchAndAppendToken( src, ")" );
		return true;
	}

	if ( !token.Icmp( "invertColor" ) ) {
		MatchAndAppendToken( src, "(" );

		R_ParseImageProgram_r( src, pic, width, height, timestamps, depth );

		// process it
		if ( pic ) {
			R_InvertColor( *pic, *width, *height );
		}

		MatchAndAppendToken( src, ")" );
		return true;
	}

	if ( !token.Icmp( "makeIntensity" ) ) {
		int		i;

		MatchAndAppendToken( src, "(" );

		R_ParseImageProgram_r( src, pic, width, height, timestamps, depth );

		// copy red to green, blue, and alpha
		if ( pic ) {
			int		c;
			c = *width * *height * 4;
			for ( i = 0 ; i < c ; i+=4 ) {
				(*pic)[i+1] = 
				(*pic)[i+2] = 
				(*pic)[i+3] = (*pic)[i];
			}
		}

		MatchAndAppendToken( src, ")" );
		return true;
	}

	if ( !token.Icmp( "makeAlpha" ) ) {
		int		i;

		MatchAndAppendToken( src, "(" );

		R_ParseImageProgram_r( src, pic, width, height, timestamps, depth );

		// average RGB into alpha, then set RGB to white
		if ( pic ) {
			int		c;
			c = *width * *height * 4;
			for ( i = 0 ; i < c ; i+=4 ) {
				(*pic)[i+3] = ( (*pic)[i+0] + (*pic)[i+1] + (*pic)[i+2] ) / 3;
				(*pic)[i+0] = 
				(*pic)[i+1] = 
				(*pic)[i+2] = 255;
			}
		}

		MatchAndAppendToken( src, ")" );
		return true;
	}

	// if we are just parsing instead of loading or checking,
	// don't do the R_LoadImage
	if ( !timestamps && !pic ) {
		return true;
	}

	// load it as an image
	R_LoadImage( token.c_str(), pic, width, height, &timestamp, true );

	if ( timestamp == -1 ) {
		return false;
	}

	// add this to the timestamp
	if ( timestamps ) {
		if ( timestamp > *timestamps ) {
			*timestamps = timestamp;
		}
	}

	return true;
}
/*
===================
R_ParseImageProgram_r

If pic is NULL, the timestamps will be filled in, but no image will be generated
If both pic and timestamps are NULL, it will just advance past it, which can be
used to parse an image program from a text stream.
===================
*/
static bool R_ParseImageProgram_r( idLexer& src, byte** pic, int* width, int* height,
								   ID_TIME_T* timestamps, textureUsage_t* usage )
{
	idToken		token;
	float		scale;
	ID_TIME_T		timestamp;
	
	src.ReadToken( &token );
	
	// Since all interaction shaders now assume YCoCG diffuse textures.  We replace all entries for the intrinsic
	// _black texture to the black texture on disk.  Doing this will cause a YCoCG compliant texture to be generated.
	// Without a YCoCG compliant black texture we will get color artifacts for any interaction
	// material that specifies the _black texture.
	if( token == "_black" )
	{
		token = "textures/black";
	}
	
	// also check for _white
	if( token == "_white" )
	{
		token = "guis/assets/white";
	}
	
	AppendToken( token );
	
	if( !token.Icmp( "heightmap" ) )
	{
		MatchAndAppendToken( src, "(" );
		
		if( !R_ParseImageProgram_r( src, pic, width, height, timestamps, usage ) )
		{
			return false;
		}
		
		MatchAndAppendToken( src, "," );
		
		src.ReadToken( &token );
		AppendToken( token );
		scale = token.GetFloatValue();
		
		// process it
		if( pic )
		{
			R_HeightmapToNormalMap( *pic, *width, *height, scale );
			if( usage )
			{
				*usage = TD_BUMP;
			}
		}
		
		MatchAndAppendToken( src, ")" );
		return true;
	}
	
	if( !token.Icmp( "addnormals" ) )
	{
		byte*	pic2 = NULL;
		int		width2, height2;
		
		MatchAndAppendToken( src, "(" );
		
		if( !R_ParseImageProgram_r( src, pic, width, height, timestamps, usage ) )
		{
			return false;
		}
		
		MatchAndAppendToken( src, "," );
		
		if( !R_ParseImageProgram_r( src, pic ? &pic2 : NULL, &width2, &height2, timestamps, usage ) )
		{
			if( pic )
			{
				R_StaticFree( *pic );
				*pic = NULL;
			}
			return false;
		}
		
		// process it
		if( pic )
		{
			R_AddNormalMaps( *pic, *width, *height, pic2, width2, height2 );
			R_StaticFree( pic2 );
			if( usage )
			{
				*usage = TD_BUMP;
			}
		}
		
		MatchAndAppendToken( src, ")" );
		return true;
	}
	
	if( !token.Icmp( "smoothnormals" ) )
	{
		MatchAndAppendToken( src, "(" );
		
		if( !R_ParseImageProgram_r( src, pic, width, height, timestamps, usage ) )
		{
			return false;
		}
		
		if( pic )
		{
			R_SmoothNormalMap( *pic, *width, *height );
			if( usage )
			{
				*usage = TD_BUMP;
			}
		}
		
		MatchAndAppendToken( src, ")" );
		return true;
	}
	
	if( !token.Icmp( "add" ) )
	{
		byte*	pic2 = NULL;
		int		width2, height2;
		
		MatchAndAppendToken( src, "(" );
		
		if( !R_ParseImageProgram_r( src, pic, width, height, timestamps, usage ) )
		{
			return false;
		}
		
		MatchAndAppendToken( src, "," );
		
		if( !R_ParseImageProgram_r( src, pic ? &pic2 : NULL, &width2, &height2, timestamps, usage ) )
		{
			if( pic )
			{
				R_StaticFree( *pic );
				*pic = NULL;
			}
			return false;
		}
		
		// process it
		if( pic )
		{
			R_ImageAdd( *pic, *width, *height, pic2, width2, height2 );
			R_StaticFree( pic2 );
		}
		
		MatchAndAppendToken( src, ")" );
		return true;
	}
	
	if( !token.Icmp( "scale" ) )
	{
		float	scale[4];
		int		i;
		
		MatchAndAppendToken( src, "(" );
		
		R_ParseImageProgram_r( src, pic, width, height, timestamps, usage );
		
		for( i = 0 ; i < 4 ; i++ )
		{
			MatchAndAppendToken( src, "," );
			src.ReadToken( &token );
			AppendToken( token );
			scale[i] = token.GetFloatValue();
		}
		
		// process it
		if( pic )
		{
			R_ImageScale( *pic, *width, *height, scale );
		}
		
		MatchAndAppendToken( src, ")" );
		return true;
	}
	
	if( !token.Icmp( "invertAlpha" ) )
	{
		MatchAndAppendToken( src, "(" );
		
		R_ParseImageProgram_r( src, pic, width, height, timestamps, usage );
		
		// process it
		if( pic )
		{
			R_InvertAlpha( *pic, *width, *height );
		}
		
		MatchAndAppendToken( src, ")" );
		return true;
	}
	
	if( !token.Icmp( "invertColor" ) )
	{
		MatchAndAppendToken( src, "(" );
		
		R_ParseImageProgram_r( src, pic, width, height, timestamps, usage );
		
		// process it
		if( pic )
		{
			R_InvertColor( *pic, *width, *height );
		}
		
		MatchAndAppendToken( src, ")" );
		return true;
	}
	
	if( !token.Icmp( "makeIntensity" ) )
	{
		int		i;
		
		MatchAndAppendToken( src, "(" );
		
		R_ParseImageProgram_r( src, pic, width, height, timestamps, usage );
		
		// copy red to green, blue, and alpha
		if( pic )
		{
			int		c;
			c = *width * *height * 4;
			for( i = 0 ; i < c ; i += 4 )
			{
				( *pic )[i + 1] =
					( *pic )[i + 2] =
						( *pic )[i + 3] = ( *pic )[i];
			}
		}
		
		MatchAndAppendToken( src, ")" );
		return true;
	}
	
	if( !token.Icmp( "makeAlpha" ) )
	{
		int		i;
		
		MatchAndAppendToken( src, "(" );
		
		R_ParseImageProgram_r( src, pic, width, height, timestamps, usage );
		
		// average RGB into alpha, then set RGB to white
		if( pic )
		{
			int		c;
			c = *width * *height * 4;
			for( i = 0 ; i < c ; i += 4 )
			{
				( *pic )[i + 3] = ( ( *pic )[i + 0] + ( *pic )[i + 1] + ( *pic )[i + 2] ) / 3;
				( *pic )[i + 0] =
					( *pic )[i + 1] =
						( *pic )[i + 2] = 255;
			}
		}
		
		MatchAndAppendToken( src, ")" );
		return true;
	}
	
	// if we are just parsing instead of loading or checking,
	// don't do the R_LoadImage
	if( !timestamps && !pic )
	{
		return true;
	}
	
	// load it as an image
	R_LoadImage( token.c_str(), pic, width, height, &timestamp, true );
	
	if( timestamp == -1 )
	{
		return false;
	}
	
	// add this to the timestamp
	if( timestamps )
	{
		if( timestamp > *timestamps )
		{
			*timestamps = timestamp;
		}
	}
	
	return true;
}
Beispiel #4
0
// Tokenise a user's typed expression string
void CExpression::ParseUserString(const char* exp, int* pchpos, bool editorMode)
{
	toks.clear();

	whitespaceCount = 0;

	// Loop every char
	for (int i = 0; exp[i] != NULL; i++) {

		if (pchpos) *pchpos = i;

		char NextCh = exp[i+1];
		char CurCh = exp[i];
		char PrevCh = exp[(i == 0 ? 0 : i-1)];
		char strbuf[128];

		// Check this char
		switch (exp[i]) {

		case '+':
			AppendToken(T_ADD, "+");
			break;
		case '-':

			// If previous token is not operand, use as negative sign
			// Fix 25/4/07: random(4) - random(5) interprets '-' as integer: explicit check for right bracket
			if (toks.size() == 0 || ((!TokenFitsRule(toks.back().t, T_ANY_VALUE) || toks.back().t == T_LEFTBRACKET) && toks.back().t != T_RIGHTBRACKET)) {

				i += ConsumeDigits(strbuf, &(exp[i]));

				// Contains a dot: float
				if (StrContains(strbuf, '.'))
					AppendToken(T_FLOAT, strbuf);
				else	// Else integer
					AppendToken(T_INTEGER, strbuf);
			}
			else
				AppendToken(T_SUBTRACT, "-");

			break;
		case '*':
			AppendToken(T_MULTIPLY, "*");
			break;
		case '/':
			AppendToken(T_DIVIDE, "/");
			break;
		case '^':
			AppendToken(T_POWER, "^");
			break;
		case '%':
			AppendToken(T_MOD, "%");
			break;
		case '(':
			AppendToken(T_LEFTBRACKET, "(");
			break;
		case ')':
			AppendToken(T_RIGHTBRACKET, ")");
			break;
		case '{':
			AppendToken(T_LEFTCURLY, "{");
			break;
		case '}':
			AppendToken(T_RIGHTCURLY, "}");
			break;
		case '@':
			AppendToken(T_AT, "@");
			break;
		case ',':
			AppendToken(T_COMMA, ",");
			break;
		case '.':
			AppendToken(T_DOT, ".");
			break;
		case '"':
			i += AppendString(&(exp[i]), editorMode);
			break;
		case '\'':
			i += AppendString(&(exp[i]), editorMode, true);
			break;
		case '=':
			AppendToken(T_EQUAL, "=");
			break;
		case '<':
			if (NextCh == '=') {
				AppendToken(T_LESSEQUAL, "<=");
				i++;
			}
			else if (NextCh == '>') {
				AppendToken(T_NOTEQUAL, "<>");
				i++;
			}
			else
				AppendToken(T_LESS, "<");
			break;
		// Alternative not equal operator != <>
		case '!':
			if (NextCh == '=') {
				AppendToken(T_NOTEQUAL, "!=");
				i++;
			}
			else
				NotifyError("Syntax error: '!'");
			break;
		case '&':
			AppendToken(T_AND, "&");
			break;
		case '|':
			AppendToken(T_OR, "|");
			break;
		case '>':
			if (NextCh == '=') {
				AppendToken(T_GREATEREQUAL, ">=");
				i++;
			}
			else
				AppendToken(T_GREATER, ">");
			break;
		case '?':
			AppendToken(T_CONDITIONAL, "?");
			break;
		case ':':
			AppendToken(T_COLON, ":");
			break;
		default:

			// Parse numbers and idents
			if (IsChAlphaNumeric(CurCh))
				i += ConsumeAppendIdentifier(strbuf, &(exp[i]));

			// Skip over whitespace
			else if (IsWhitespace(CurCh)) {

				// In editor mode add a T_WHITESPACE token
				if (editorMode) {
					Token t;
					t.length = 0;
					t.t = T_WHITESPACE;

					while (IsWhitespace(exp[i])) {
						t.str += exp[i];
						i++;
					}

					// We want the next for loop iteration to see the next char
					i--;

					toks.push_back(t);
				}

				// Add to last token length
				if (toks.size() > 0)
					toks[toks.size() - 1].length++;
			}
			// Else unknown character
			else {
				string error = "Unknown character '";
				error += CurCh;
				error += "'";
				throw runtime_error(error.c_str());
			}
		}//switch

	}//for

	// Only perform preprocessing when not in edittime mode
	if (!editorMode)
		PreProcessTokStream();


	///////////////////////////
	// Final step:  parse to tree

	// Determine if the overall expression is constant, collapsing constant parts along
	// the way.
	// Runtime only
#ifdef RUNTIME
	// Make the tree
	int step = 0;
	ExpTree = DoTree(step);

	isConstant = ExpTree->Constant();

	// If constant, get the constant value.
	if (isConstant) {
		CollapseConstantTree(ExpTree);
		ExpTree->Evaluate(&constantValue);
	}
#endif

}