/* ================ idDeclParticle::ParseParametric ================ */ void idDeclParticle::ParseParametric( idLexer &src, idParticleParm *parm ) { idToken token; parm->table = NULL; parm->from = parm->to = 0.0f; if ( !src.ReadToken( &token ) ) { src.Error( "not enough parameters" ); return; } if ( token.IsNumeric() ) { // can have a to + 2nd parm parm->from = parm->to = atof( token ); if ( src.ReadToken( &token ) ) { if ( !token.Icmp( "to" ) ) { if ( !src.ReadToken( &token ) ) { src.Error( "missing second parameter" ); return; } parm->to = atof( token ); } else { src.UnreadToken( &token ); } } } else { // table parm->table = static_cast<const idDeclTable *>( declManager->FindType( DECL_TABLE, token, false ) ); } }
/* ======================== ParseInOutStruct ======================== */ void ParseInOutStruct( idLexer & src, int attribType, idList< inOutVariable_t > & inOutVars ) { src.ExpectTokenString( "{" ); while( !src.CheckTokenString( "}" ) ) { inOutVariable_t var; idToken token; src.ReadToken( &token ); var.type = token; src.ReadToken( &token ); var.nameCg = token; if ( !src.CheckTokenString( ":" ) ) { src.SkipUntilString( ";" ); continue; } src.ReadToken( &token ); var.nameGLSL = token; src.ExpectTokenString( ";" ); // convert the type for ( int i = 0; typeConversion[i].typeCG != NULL; i++ ) { if ( var.type.Cmp( typeConversion[i].typeCG ) == 0 ) { var.type = typeConversion[i].typeGLSL; break; } } // convert the semantic to a GLSL name for ( int i = 0; attribsPC[i].semantic != NULL; i++ ) { if ( ( attribsPC[i].flags & attribType ) != 0 ) { if ( var.nameGLSL.Cmp( attribsPC[i].semantic ) == 0 ) { var.nameGLSL = attribsPC[i].glsl; break; } } } // check if it was defined previously var.declareInOut = true; for ( int i = 0; i < inOutVars.Num(); i++ ) { if ( var.nameGLSL == inOutVars[i].nameGLSL ) { var.declareInOut = false; break; } } inOutVars.Append( var ); } src.ExpectTokenString( ";" ); }
/* ==================== idRenderModelMD5::ParseJoint ==================== */ void idRenderModelMD5::ParseJoint( idLexer& parser, idMD5Joint* joint, idJointQuat* defaultPose ) { // // parse name // idToken token; parser.ReadToken( &token ); joint->name = token; // // parse parent // int num = parser.ParseInt(); if( num < 0 ) { joint->parent = NULL; } else { if( num >= joints.Num() - 1 ) { parser.Error( "Invalid parent for joint '%s'", joint->name.c_str() ); } joint->parent = &joints[ num ]; } // // parse default pose // parser.Parse1DMatrix( 3, defaultPose->t.ToFloatPtr() ); parser.Parse1DMatrix( 3, defaultPose->q.ToFloatPtr() ); defaultPose->q.w = defaultPose->q.CalcW(); }
/* ============ idAASSettings::ParseBBoxes ============ */ bool idAASSettings::ParseBBoxes( idLexer &src ) { idToken token; idBounds bounds; numBoundingBoxes = 0; if ( !src.ExpectTokenString( "{" ) ) { return false; } while( src.ReadToken( &token ) ) { if ( token == "}" ) { return true; } src.UnreadToken( &token ); src.Parse1DMatrix( 3, bounds[0].ToFloatPtr() ); if ( !src.ExpectTokenString( "-" ) ) { return false; } src.Parse1DMatrix( 3, bounds[1].ToFloatPtr() ); boundingBoxes[numBoundingBoxes++] = bounds; } return false; }
/* ================ idTypeInfoTools::ParseTemplateArguments ================ */ bool idTypeInfoTools::ParseTemplateArguments( idLexer &src, idStr &arguments ) { int indent; idToken token; arguments = ""; if ( !src.ExpectTokenString( "<" ) ) { return false; } indent = 1; while( indent ) { if ( !src.ReadToken( &token ) ) { break; } if ( token == "<" ) { indent++; } else if ( token == ">" ) { indent--; } else { if ( arguments.Length() ) { arguments += " "; } arguments += token; } } return true; }
/* ================ idDeclAF::ParseFixed ================ */ bool idDeclAF::ParseFixed( idLexer &src ) { idToken token; idDeclAF_Constraint *constraint = new idDeclAF_Constraint; constraint->SetDefault( this ); constraints.Alloc() = constraint; if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } constraint->type = DECLAF_CONSTRAINT_FIXED; constraint->name = token; while( src.ReadToken( &token ) ) { if ( !token.Icmp( "body1" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body1 = token; } else if ( !token.Icmp( "body2" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body2 = token; } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in ball and socket joint", token.c_str() ); return false; } } return true; }
/* ================ idDeclAF::ParseHinge ================ */ bool idDeclAF::ParseHinge( idLexer &src ) { idToken token; idDeclAF_Constraint *constraint = new idDeclAF_Constraint; constraint->SetDefault( this ); constraints.Alloc() = constraint; if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } constraint->type = DECLAF_CONSTRAINT_HINGE; constraint->limit = idDeclAF_Constraint::LIMIT_NONE; constraint->name = token; constraint->friction = 0.5f; constraint->anchor.ToVec3().Zero(); constraint->axis.ToVec3().Zero(); while( src.ReadToken( &token ) ) { if ( !token.Icmp( "body1" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body1 = token; } else if ( !token.Icmp( "body2" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body2 = token; } else if ( !token.Icmp( "anchor" ) ) { if ( !constraint->anchor.Parse( src ) ) { return false; } } else if ( !token.Icmp( "axis" ) ) { if ( !constraint->axis.Parse( src ) ) { return false; } } else if ( !token.Icmp( "limit" ) ) { constraint->limitAngles[0] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[1] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[2] = src.ParseFloat(); constraint->limit = idDeclAF_Constraint::LIMIT_CONE; } else if ( !token.Icmp( "friction" ) ) { constraint->friction = src.ParseFloat(); } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in hinge", token.c_str() ); return false; } } return true; }
/* ================ idAFVector::Parse ================ */ bool idAFVector::Parse( idLexer &src ) { idToken token; if ( !src.ReadToken( &token ) ) { return false; } if ( token == "-" ) { negate = true; if ( !src.ReadToken( &token ) ) { return false; } } else { negate = false; } if ( token == "(" ) { type = idAFVector::VEC_COORDS; vec.x = src.ParseFloat(); src.ExpectTokenString( "," ); vec.y = src.ParseFloat(); src.ExpectTokenString( "," ); vec.z = src.ParseFloat(); src.ExpectTokenString( ")" ); } else if ( token == "joint" ) { type = idAFVector::VEC_JOINT; src.ExpectTokenString( "(" ); src.ReadToken( &token ); joint1 = token; src.ExpectTokenString( ")" ); } else if ( token == "bonecenter" ) { type = idAFVector::VEC_BONECENTER; src.ExpectTokenString( "(" ); src.ReadToken( &token ); joint1 = token; src.ExpectTokenString( "," ); src.ReadToken( &token ); joint2 = token; src.ExpectTokenString( ")" ); } else if ( token == "bonedir" ) { type = idAFVector::VEC_BONEDIR; src.ExpectTokenString( "(" ); src.ReadToken( &token ); joint1 = token; src.ExpectTokenString( "," ); src.ReadToken( &token ); joint2 = token; src.ExpectTokenString( ")" ); } else { src.Error( "unknown token %s in vector", token.c_str() ); return false; } return true; }
/* ================ idDeclAF::ParseSpring ================ */ bool idDeclAF::ParseSpring( idLexer &src ) { idToken token; idDeclAF_Constraint *constraint = new idDeclAF_Constraint; constraint->SetDefault( this ); constraints.Alloc() = constraint; if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } constraint->type = DECLAF_CONSTRAINT_SPRING; constraint->limit = idDeclAF_Constraint::LIMIT_NONE; constraint->name = token; constraint->friction = 0.5f; while( src.ReadToken( &token ) ) { if ( !token.Icmp( "body1" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body1 = token; } else if ( !token.Icmp( "body2" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body2 = token; } else if ( !token.Icmp( "anchor1" ) ) { if ( !constraint->anchor.Parse( src ) ) { return false; } } else if ( !token.Icmp( "anchor2" ) ) { if ( !constraint->anchor2.Parse( src ) ) { return false; } } else if ( !token.Icmp( "friction" ) ) { constraint->friction = src.ParseFloat(); } else if ( !token.Icmp( "stretch" ) ) { constraint->stretch = src.ParseFloat(); } else if ( !token.Icmp( "compress" ) ) { constraint->compress = src.ParseFloat(); } else if ( !token.Icmp( "damping" ) ) { constraint->damping = src.ParseFloat(); } else if ( !token.Icmp( "restLength" ) ) { constraint->restLength = src.ParseFloat(); } else if ( !token.Icmp( "minLength" ) ) { constraint->minLength = src.ParseFloat(); } else if ( !token.Icmp( "maxLength" ) ) { constraint->maxLength = src.ParseFloat(); } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in spring", token.c_str() ); return false; } } return true; }
/* ================ idDeclAF::ParseSlider ================ */ bool idDeclAF::ParseSlider( idLexer& src ) { idToken token; idDeclAF_Constraint* constraint = new( TAG_DECL ) idDeclAF_Constraint; constraint->SetDefault( this ); constraints.Alloc() = constraint; if( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } constraint->type = DECLAF_CONSTRAINT_SLIDER; constraint->limit = idDeclAF_Constraint::LIMIT_NONE; constraint->name = token; constraint->friction = 0.5f; while( src.ReadToken( &token ) ) { if( !token.Icmp( "body1" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body1 = token; } else if( !token.Icmp( "body2" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body2 = token; } else if( !token.Icmp( "axis" ) ) { if( !constraint->axis.Parse( src ) ) { return false; } } else if( !token.Icmp( "friction" ) ) { constraint->friction = src.ParseFloat(); } else if( token == "}" ) { break; } else { src.Error( "unknown token %s in slider", token.c_str() ); return false; } } return true; }
/* ================ Reachability_Special_Read ================ */ bool Reachability_Special_Read( idLexer &src, idReachability_Special *reach ) { idToken key, value; src.ExpectTokenString( "{" ); while( src.ReadToken( &key ) ) { if ( key == "}" ) { return true; } src.ExpectTokenType( TT_STRING, 0, &value ); reach->dict.Set( key, value ); } return false; }
/* ==================== idModelExport::ParseOptions ==================== */ bool idModelExport::ParseOptions( idLexer &lex ) { idToken token; idStr destdir; idStr sourcedir; if ( !lex.ReadToken( &token ) ) { lex.Error( "Expected filename" ); return false; } src = token; dest = token; while( lex.ReadToken( &token ) ) { if ( token == "-" ) { if ( !lex.ReadToken( &token ) ) { lex.Error( "Expecting option" ); return false; } if ( token == "sourcedir" ) { if ( !lex.ReadToken( &token ) ) { lex.Error( "Missing pathname after -sourcedir" ); return false; } sourcedir = token; } else if ( token == "destdir" ) { if ( !lex.ReadToken( &token ) ) { lex.Error( "Missing pathname after -destdir" ); return false; } destdir = token; } else if ( token == "dest" ) { if ( !lex.ReadToken( &token ) ) { lex.Error( "Missing filename after -dest" ); return false; } dest = token; } else { commandLine += va( " -%s", token.c_str() ); } } else { commandLine += va( " %s", token.c_str() ); } } if ( sourcedir.Length() ) { src.StripPath(); sourcedir.BackSlashesToSlashes(); sprintf( src, "%s/%s", sourcedir.c_str(), src.c_str() ); } if ( destdir.Length() ) { dest.StripPath(); destdir.BackSlashesToSlashes(); sprintf( dest, "%s/%s", destdir.c_str(), dest.c_str() ); } return true; }
/* ================ idDeclAF::ParseContents ================ */ bool idDeclAF::ParseContents( idLexer &src, int &c ) const { idToken token; idStr str; while( src.ReadToken( &token ) ) { str += token; if ( !src.CheckTokenString( "," ) ) { break; } str += ","; } c = ContentsFromString( str ); 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, ×tamp, true ); if( timestamp == -1 ) { return false; } // add this to the timestamp if( timestamps ) { if( timestamp > *timestamps ) { *timestamps = timestamp; } } return true; }
/* ==================== idMD5Mesh::ParseMesh ==================== */ void idMD5Mesh::ParseMesh( idLexer &parser, int numJoints, const idJointMat *joints ) { idToken token; idToken name; int num; int count; int jointnum; idStr shaderName; int i, j; idList<int> tris; idList<int> firstWeightForVertex; idList<int> numWeightsForVertex; int maxweight; idList<vertexWeight_t> tempWeights; parser.ExpectTokenString( "{" ); // // parse name // if ( parser.CheckTokenString( "name" ) ) { parser.ReadToken( &name ); } // // parse shader // parser.ExpectTokenString( "shader" ); parser.ReadToken( &token ); shaderName = token; shader = declManager->FindMaterial( shaderName ); // // parse texture coordinates // parser.ExpectTokenString( "numverts" ); count = parser.ParseInt(); if ( count < 0 ) { parser.Error( "Invalid size: %s", token.c_str() ); } texCoords.SetNum( count ); firstWeightForVertex.SetNum( count ); numWeightsForVertex.SetNum( count ); numWeights = 0; maxweight = 0; for( i = 0; i < texCoords.Num(); i++ ) { parser.ExpectTokenString( "vert" ); parser.ParseInt(); parser.Parse1DMatrix( 2, texCoords[ i ].ToFloatPtr() ); firstWeightForVertex[ i ] = parser.ParseInt(); numWeightsForVertex[ i ] = parser.ParseInt(); if ( !numWeightsForVertex[ i ] ) { parser.Error( "Vertex without any joint weights." ); } numWeights += numWeightsForVertex[ i ]; if ( numWeightsForVertex[ i ] + firstWeightForVertex[ i ] > maxweight ) { maxweight = numWeightsForVertex[ i ] + firstWeightForVertex[ i ]; } } // // parse tris // parser.ExpectTokenString( "numtris" ); count = parser.ParseInt(); if ( count < 0 ) { parser.Error( "Invalid size: %d", count ); } tris.SetNum( count * 3 ); numTris = count; for( i = 0; i < count; i++ ) { parser.ExpectTokenString( "tri" ); parser.ParseInt(); tris[ i * 3 + 0 ] = parser.ParseInt(); tris[ i * 3 + 1 ] = parser.ParseInt(); tris[ i * 3 + 2 ] = parser.ParseInt(); } // // parse weights // parser.ExpectTokenString( "numweights" ); count = parser.ParseInt(); if ( count < 0 ) { parser.Error( "Invalid size: %d", count ); } if ( maxweight > count ) { parser.Warning( "Vertices reference out of range weights in model (%d of %d weights).", maxweight, count ); } tempWeights.SetNum( count ); for( i = 0; i < count; i++ ) { parser.ExpectTokenString( "weight" ); parser.ParseInt(); jointnum = parser.ParseInt(); if ( ( jointnum < 0 ) || ( jointnum >= numJoints ) ) { parser.Error( "Joint Index out of range(%d): %d", numJoints, jointnum ); } tempWeights[ i ].joint = jointnum; tempWeights[ i ].jointWeight = parser.ParseFloat(); parser.Parse1DMatrix( 3, tempWeights[ i ].offset.ToFloatPtr() ); } // create pre-scaled weights and an index for the vertex/joint lookup scaledWeights = (idVec4 *) Mem_Alloc16( numWeights * sizeof( scaledWeights[0] ) ); weightIndex = (int *) Mem_Alloc16( numWeights * 2 * sizeof( weightIndex[0] ) ); memset( weightIndex, 0, numWeights * 2 * sizeof( weightIndex[0] ) ); count = 0; for( i = 0; i < texCoords.Num(); i++ ) { num = firstWeightForVertex[i]; for( j = 0; j < numWeightsForVertex[i]; j++, num++, count++ ) { scaledWeights[count].ToVec3() = tempWeights[num].offset * tempWeights[num].jointWeight; scaledWeights[count].w = tempWeights[num].jointWeight; weightIndex[count * 2 + 0] = tempWeights[num].joint * sizeof( idJointMat ); } weightIndex[count * 2 - 1] = 1; } tempWeights.Clear(); numWeightsForVertex.Clear(); firstWeightForVertex.Clear(); parser.ExpectTokenString( "}" ); // update counters c_numVerts += texCoords.Num(); c_numWeights += numWeights; c_numWeightJoints++; for ( i = 0; i < numWeights; i++ ) { c_numWeightJoints += weightIndex[i*2+1]; } // // build the information that will be common to all animations of this mesh: // silhouette edge connectivity and normal / tangent generation information // idDrawVert *verts = (idDrawVert *) _alloca16( texCoords.Num() * sizeof( idDrawVert ) ); for ( i = 0; i < texCoords.Num(); i++ ) { verts[i].Clear(); verts[i].st = texCoords[i]; } TransformVerts( verts, joints ); deformInfo = R_BuildDeformInfo( texCoords.Num(), verts, tris.Num(), tris.Ptr(), shader->UseUnsmoothedTangents() ); }
/* =================== 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, ×tamp, true ); if ( timestamp == -1 ) { return false; } // add this to the timestamp if ( timestamps ) { if ( timestamp > *timestamps ) { *timestamps = timestamp; } } return true; }
/* ================ idDeclAF::ParseSettings ================ */ bool idDeclAF::ParseSettings( idLexer &src ) { idToken token; if ( !src.ExpectTokenString( "{" ) ) { return false; } while( src.ReadToken( &token ) ) { if ( !token.Icmp( "mesh" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } } else if ( !token.Icmp( "anim" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } } else if ( !token.Icmp( "model" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } model = token; } else if ( !token.Icmp( "skin" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } skin = token; } else if ( !token.Icmp( "friction" ) ) { defaultLinearFriction = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } defaultAngularFriction = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } defaultContactFriction = src.ParseFloat(); if ( src.CheckTokenString( "," ) ) { defaultConstraintFriction = src.ParseFloat(); } } else if ( !token.Icmp( "totalMass" ) ) { totalMass = src.ParseFloat(); } else if ( !token.Icmp( "suspendSpeed" ) ) { suspendVelocity[0] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } suspendVelocity[1] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } suspendAcceleration[0] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } suspendAcceleration[1] = src.ParseFloat(); } else if ( !token.Icmp( "noMoveTime" ) ) { noMoveTime = src.ParseFloat(); } else if ( !token.Icmp( "noMoveTranslation" ) ) { noMoveTranslation = src.ParseFloat(); } else if ( !token.Icmp( "noMoveRotation" ) ) { noMoveRotation = src.ParseFloat(); } else if ( !token.Icmp( "minMoveTime" ) ) { minMoveTime = src.ParseFloat(); } else if ( !token.Icmp( "maxMoveTime" ) ) { maxMoveTime = src.ParseFloat(); } else if ( !token.Icmp( "contents" ) ) { ParseContents( src, contents ); } else if ( !token.Icmp( "clipMask" ) ) { ParseContents( src, clipMask ); } else if ( !token.Icmp( "selfCollision" ) ) { selfCollision = src.ParseBool(); } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in settings", token.c_str() ); return false; } } return true; }
/* ============ idAASSettings::FromParser ============ */ bool idAASSettings::FromParser( idLexer &src ) { idToken token; if ( !src.ExpectTokenString( "{" ) ) { return false; } // parse the file while ( 1 ) { if ( !src.ReadToken( &token ) ) { break; } if ( token == "}" ) { break; } if ( token == "bboxes" ) { if ( !ParseBBoxes( src ) ) { return false; } } else if ( token == "usePatches" ) { if ( !ParseBool( src, usePatches ) ) { return false; } } else if ( token == "writeBrushMap" ) { if ( !ParseBool( src, writeBrushMap ) ) { return false; } } else if ( token == "playerFlood" ) { if ( !ParseBool( src, playerFlood ) ) { return false; } } else if ( token == "allowSwimReachabilities" ) { if ( !ParseBool( src, allowSwimReachabilities ) ) { return false; } } else if ( token == "allowFlyReachabilities" ) { if ( !ParseBool( src, allowFlyReachabilities ) ) { return false; } } else if ( token == "fileExtension" ) { src.ExpectTokenString( "=" ); src.ExpectTokenType( TT_STRING, 0, &token ); fileExtension = token; } else if ( token == "gravity" ) { ParseVector( src, gravity ); gravityDir = gravity; gravityValue = gravityDir.Normalize(); invGravityDir = -gravityDir; } else if ( token == "maxStepHeight" ) { if ( !ParseFloat( src, maxStepHeight ) ) { return false; } } else if ( token == "maxBarrierHeight" ) { if ( !ParseFloat( src, maxBarrierHeight ) ) { return false; } } else if ( token == "maxWaterJumpHeight" ) { if ( !ParseFloat( src, maxWaterJumpHeight ) ) { return false; } } else if ( token == "maxFallHeight" ) { if ( !ParseFloat( src, maxFallHeight ) ) { return false; } } else if ( token == "minFloorCos" ) { if ( !ParseFloat( src, minFloorCos ) ) { return false; } } else if ( token == "tt_barrierJump" ) { if ( !ParseInt( src, tt_barrierJump ) ) { return false; } } else if ( token == "tt_startCrouching" ) { if ( !ParseInt( src, tt_startCrouching ) ) { return false; } } else if ( token == "tt_waterJump" ) { if ( !ParseInt( src, tt_waterJump ) ) { return false; } } else if ( token == "tt_startWalkOffLedge" ) { if ( !ParseInt( src, tt_startWalkOffLedge ) ) { return false; } } else { src.Error( "invalid token '%s'", token.c_str() ); } } if ( numBoundingBoxes <= 0 ) { src.Error( "no valid bounding box" ); } return true; }
/* ================ idDeclAF::ParseUniversalJoint ================ */ bool idDeclAF::ParseUniversalJoint( idLexer &src ) { idToken token; idDeclAF_Constraint *constraint = new idDeclAF_Constraint; constraint->SetDefault( this ); constraints.Alloc() = constraint; if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } constraint->type = DECLAF_CONSTRAINT_UNIVERSALJOINT; constraint->limit = idDeclAF_Constraint::LIMIT_NONE; constraint->name = token; constraint->friction = 0.5f; constraint->anchor.ToVec3().Zero(); constraint->shaft[0].ToVec3().Zero(); constraint->shaft[1].ToVec3().Zero(); while( src.ReadToken( &token ) ) { if ( !token.Icmp( "body1" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body1 = token; } else if ( !token.Icmp( "body2" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body2 = token; } else if ( !token.Icmp( "anchor" ) ) { if ( !constraint->anchor.Parse( src ) ) { return false; } } else if ( !token.Icmp( "shafts" ) ) { if ( !constraint->shaft[0].Parse( src ) || !src.ExpectTokenString( "," ) || !constraint->shaft[1].Parse( src ) ) { return false; } } else if ( !token.Icmp( "conelimit" ) ) { if ( !constraint->limitAxis.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[0] = src.ParseFloat(); constraint->limit = idDeclAF_Constraint::LIMIT_CONE; } else if ( !token.Icmp( "pyramidlimit" ) ) { if ( !constraint->limitAxis.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[0] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[1] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[2] = src.ParseFloat(); constraint->limit = idDeclAF_Constraint::LIMIT_PYRAMID; } else if ( !token.Icmp( "friction" ) ) { constraint->friction = src.ParseFloat(); } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in universal joint", token.c_str() ); return false; } } return true; }
/* =============== idEFXFile::ReadEffect =============== */ bool idEFXFile::ReadEffect( idLexer &src, idSoundEffect *effect ) { idToken name, token; if ( !src.ReadToken( &token ) ) return false; // reverb effect if ( token == "reverb" ) { EAXREVERBPROPERTIES *reverb = ( EAXREVERBPROPERTIES * )Mem_Alloc( sizeof( EAXREVERBPROPERTIES ) ); if ( reverb ) { src.ReadTokenOnLine( &token ); name = token; if ( !src.ReadToken( &token ) ) { Mem_Free( reverb ); return false; } if ( token != "{" ) { src.Error( "idEFXFile::ReadEffect: { not found, found %s", token.c_str() ); Mem_Free( reverb ); return false; } do { if ( !src.ReadToken( &token ) ) { src.Error( "idEFXFile::ReadEffect: EOF without closing brace" ); Mem_Free( reverb ); return false; } if ( token == "}" ) { effect->name = name; effect->data = ( void * )reverb; effect->datasize = sizeof( EAXREVERBPROPERTIES ); break; } if ( token == "environment" ) { src.ReadTokenOnLine( &token ); reverb->ulEnvironment = token.GetUnsignedIntValue(); } else if ( token == "environment size" ) { reverb->flEnvironmentSize = src.ParseFloat(); } else if ( token == "environment diffusion" ) { reverb->flEnvironmentDiffusion = src.ParseFloat(); } else if ( token == "room" ) { reverb->lRoom = src.ParseInt(); } else if ( token == "room hf" ) { reverb->lRoomHF = src.ParseInt(); } else if ( token == "room lf" ) { reverb->lRoomLF = src.ParseInt(); } else if ( token == "decay time" ) { reverb->flDecayTime = src.ParseFloat(); } else if ( token == "decay hf ratio" ) { reverb->flDecayHFRatio = src.ParseFloat(); } else if ( token == "decay lf ratio" ) { reverb->flDecayLFRatio = src.ParseFloat(); } else if ( token == "reflections" ) { reverb->lReflections = src.ParseInt(); } else if ( token == "reflections delay" ) { reverb->flReflectionsDelay = src.ParseFloat(); } else if ( token == "reflections pan" ) { reverb->vReflectionsPan.x = src.ParseFloat(); reverb->vReflectionsPan.y = src.ParseFloat(); reverb->vReflectionsPan.z = src.ParseFloat(); } else if ( token == "reverb" ) { reverb->lReverb = src.ParseInt(); } else if ( token == "reverb delay" ) { reverb->flReverbDelay = src.ParseFloat(); } else if ( token == "reverb pan" ) { reverb->vReverbPan.x = src.ParseFloat(); reverb->vReverbPan.y = src.ParseFloat(); reverb->vReverbPan.z = src.ParseFloat(); } else if ( token == "echo time" ) { reverb->flEchoTime = src.ParseFloat(); } else if ( token == "echo depth" ) { reverb->flEchoDepth = src.ParseFloat(); } else if ( token == "modulation time" ) { reverb->flModulationTime = src.ParseFloat(); } else if ( token == "modulation depth" ) { reverb->flModulationDepth = src.ParseFloat(); } else if ( token == "air absorption hf" ) { reverb->flAirAbsorptionHF = src.ParseFloat(); } else if ( token == "hf reference" ) { reverb->flHFReference = src.ParseFloat(); } else if ( token == "lf reference" ) { reverb->flLFReference = src.ParseFloat(); } else if ( token == "room rolloff factor" ) { reverb->flRoomRolloffFactor = src.ParseFloat(); } else if ( token == "flags" ) { src.ReadTokenOnLine( &token ); reverb->ulFlags = token.GetUnsignedIntValue(); } else { src.ReadTokenOnLine( &token ); src.Error( "idEFXFile::ReadEffect: Invalid parameter in reverb definition" ); Mem_Free( reverb ); } } while ( 1 ); return true; } } else { // other effect (not supported at the moment) src.Error( "idEFXFile::ReadEffect: Unknown effect definition" ); } return false; }
/* ================ idDeclAF::ParseBody ================ */ bool idDeclAF::ParseBody( idLexer &src ) { bool hasJoint = false; idToken token; idAFVector angles; idDeclAF_Body *body = new idDeclAF_Body; bodies.Alloc() = body; body->SetDefault( this ); if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } body->name = token; if ( !body->name.Icmp( "origin" ) || !body->name.Icmp( "world" ) ) { src.Error( "a body may not be named \"origin\" or \"world\"" ); return false; } while( src.ReadToken( &token ) ) { if ( !token.Icmp( "model" ) ) { if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) { return false; } if ( !token.Icmp( "box" ) ) { body->modelType = TRM_BOX; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "octahedron" ) ) { body->modelType = TRM_OCTAHEDRON; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "dodecahedron" ) ) { body->modelType = TRM_DODECAHEDRON; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "cylinder" ) ) { body->modelType = TRM_CYLINDER; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } body->numSides = src.ParseInt(); if ( !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "cone" ) ) { body->modelType = TRM_CONE; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } body->numSides = src.ParseInt(); if ( !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "bone" ) ) { body->modelType = TRM_BONE; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } body->width = src.ParseFloat(); if ( !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "custom" ) ) { src.Error( "custom models not yet implemented" ); return false; } else { src.Error( "unkown model type %s", token.c_str() ); return false; } } else if ( !token.Icmp( "origin" ) ) { if ( !body->origin.Parse( src ) ) { return false; } } else if ( !token.Icmp( "angles" ) ) { if ( !angles.Parse( src ) ) { return false; } body->angles = idAngles( angles.ToVec3().x, angles.ToVec3().y, angles.ToVec3().z ); } else if ( !token.Icmp( "joint" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } body->jointName = token; hasJoint = true; } else if ( !token.Icmp( "mod" ) ) { if ( !src.ExpectAnyToken( &token ) ) { return false; } body->jointMod = JointModFromString( token.c_str() ); } else if ( !token.Icmp( "density" ) ) { body->density = src.ParseFloat(); } else if ( !token.Icmp( "inertiaScale" ) ) { src.Parse1DMatrix( 9, body->inertiaScale[0].ToFloatPtr() ); } else if ( !token.Icmp( "friction" ) ) { body->linearFriction = src.ParseFloat(); src.ExpectTokenString( "," ); body->angularFriction = src.ParseFloat(); src.ExpectTokenString( "," ); body->contactFriction = src.ParseFloat(); } else if ( !token.Icmp( "contents" ) ) { ParseContents( src, body->contents ); } else if ( !token.Icmp( "clipMask" ) ) { ParseContents( src, body->clipMask ); } else if ( !token.Icmp( "selfCollision" ) ) { body->selfCollision = src.ParseBool(); } else if ( !token.Icmp( "containedjoints" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } body->containedJoints = token; } else if ( !token.Icmp( "frictionDirection" ) ) { if ( !body->frictionDirection.Parse( src ) ) { return false; } } else if ( !token.Icmp( "contactMotorDirection" ) ) { if ( !body->contactMotorDirection.Parse( src ) ) { return false; } } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in body", token.c_str() ); return false; } } if ( body->modelType == TRM_INVALID ) { src.Error( "no model set for body" ); return false; } if ( !hasJoint ) { src.Error( "no joint set for body" ); return false; } body->clipMask |= CONTENTS_MOVEABLECLIP; return true; }
bool idEFXFile::ReadEffect( idLexer &src, idSoundEffect *effect ) { idToken name, token; if ( !src.ReadToken( &token ) ) return false; // reverb effect if ( token != "reverb" ) { // other effect (not supported at the moment) src.Error( "idEFXFile::ReadEffect: Unknown effect definition" ); return false; } src.ReadTokenOnLine( &token ); name = token; if ( !src.ReadToken( &token ) ) return false; if ( token != "{" ) { src.Error( "idEFXFile::ReadEffect: { not found, found %s", token.c_str() ); return false; } ALenum err; alGetError(); EFXprintf("Loading EFX effect '%s' (#%u)\n", name.c_str(), effect->effect); do { if ( !src.ReadToken( &token ) ) { src.Error( "idEFXFile::ReadEffect: EOF without closing brace" ); return false; } if ( token == "}" ) { effect->name = name; break; } if ( token == "environment" ) { // <+KittyCat> the "environment" token should be ignored (efx has nothing equatable to it) src.ParseInt(); } else if ( token == "environment size" ) { float size = src.ParseFloat(); efxf(AL_EAXREVERB_DENSITY, (size < 2.0f) ? (size - 1.0f) : 1.0f); } else if ( token == "environment diffusion" ) { efxf(AL_EAXREVERB_DIFFUSION, src.ParseFloat()); } else if ( token == "room" ) { efxf(AL_EAXREVERB_GAIN, mB_to_gain(src.ParseInt(), GAIN)); } else if ( token == "room hf" ) { efxf(AL_EAXREVERB_GAINHF, mB_to_gain(src.ParseInt(), GAINHF)); } else if ( token == "room lf" ) { efxf(AL_EAXREVERB_GAINLF, mB_to_gain(src.ParseInt(), GAINLF)); } else if ( token == "decay time" ) { efxf(AL_EAXREVERB_DECAY_TIME, src.ParseFloat()); } else if ( token == "decay hf ratio" ) { efxf(AL_EAXREVERB_DECAY_HFRATIO, src.ParseFloat()); } else if ( token == "decay lf ratio" ) { efxf(AL_EAXREVERB_DECAY_LFRATIO, src.ParseFloat()); } else if ( token == "reflections" ) { efxf(AL_EAXREVERB_REFLECTIONS_GAIN, mB_to_gain(src.ParseInt(), REFLECTIONS_GAIN)); } else if ( token == "reflections delay" ) { efxf(AL_EAXREVERB_REFLECTIONS_DELAY, src.ParseFloat()); } else if ( token == "reflections pan" ) { efxfv(AL_EAXREVERB_REFLECTIONS_PAN, src.ParseFloat(), src.ParseFloat(), src.ParseFloat()); } else if ( token == "reverb" ) { efxf(AL_EAXREVERB_LATE_REVERB_GAIN, mB_to_gain(src.ParseInt(), LATE_REVERB_GAIN)); } else if ( token == "reverb delay" ) { efxf(AL_EAXREVERB_LATE_REVERB_DELAY, src.ParseFloat()); } else if ( token == "reverb pan" ) { efxfv(AL_EAXREVERB_LATE_REVERB_PAN, src.ParseFloat(), src.ParseFloat(), src.ParseFloat()); } else if ( token == "echo time" ) { efxf(AL_EAXREVERB_ECHO_TIME, src.ParseFloat()); } else if ( token == "echo depth" ) { efxf(AL_EAXREVERB_ECHO_DEPTH, src.ParseFloat()); } else if ( token == "modulation time" ) { efxf(AL_EAXREVERB_MODULATION_TIME, src.ParseFloat()); } else if ( token == "modulation depth" ) { efxf(AL_EAXREVERB_MODULATION_DEPTH, src.ParseFloat()); } else if ( token == "air absorption hf" ) { efxf(AL_EAXREVERB_AIR_ABSORPTION_GAINHF, mB_to_gain(src.ParseFloat(), AIR_ABSORPTION_GAINHF)); } else if ( token == "hf reference" ) { efxf(AL_EAXREVERB_HFREFERENCE, src.ParseFloat()); } else if ( token == "lf reference" ) { efxf(AL_EAXREVERB_LFREFERENCE, src.ParseFloat()); } else if ( token == "room rolloff factor" ) { efxf(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, src.ParseFloat()); } else if ( token == "flags" ) { src.ReadTokenOnLine( &token ); unsigned int flags = token.GetUnsignedLongValue(); efxi(AL_EAXREVERB_DECAY_HFLIMIT, (flags & 0x20) ? AL_TRUE : AL_FALSE); // the other SCALE flags have no equivalent in efx } else { src.ReadTokenOnLine( &token ); src.Error( "idEFXFile::ReadEffect: Invalid parameter in reverb definition" ); } } while ( 1 ); return true; }
/* ================ idDeclFX::ParseSingleFXAction ================ */ void idDeclFX::ParseSingleFXAction( idLexer &src, idFXSingleAction& FXAction ) { idToken token; FXAction.type = -1; FXAction.sibling = -1; FXAction.data = "<none>"; FXAction.name = "<none>"; FXAction.fire = "<none>"; FXAction.delay = 0.0f; FXAction.duration = 0.0f; FXAction.restart = 0.0f; FXAction.size = 0.0f; FXAction.fadeInTime = 0.0f; FXAction.fadeOutTime = 0.0f; FXAction.shakeTime = 0.0f; FXAction.shakeAmplitude = 0.0f; FXAction.shakeDistance = 0.0f; FXAction.shakeFalloff = false; FXAction.shakeImpulse = 0.0f; FXAction.shakeIgnoreMaster = false; FXAction.lightRadius = 0.0f; FXAction.rotate = 0.0f; FXAction.random1 = 0.0f; FXAction.random2 = 0.0f; FXAction.lightColor = vec3_origin; FXAction.offset = vec3_origin; FXAction.axis = mat3_identity; FXAction.bindParticles = false; FXAction.explicitAxis = false; FXAction.noshadows = false; FXAction.particleTrackVelocity = false; FXAction.trackOrigin = false; FXAction.soundStarted = false; while (1) { if ( !src.ReadToken( &token ) ) { break; } if ( !token.Icmp( "}" ) ) { break; } if ( !token.Icmp( "shake" ) ) { FXAction.type = FX_SHAKE; FXAction.shakeTime = src.ParseFloat(); src.ExpectTokenString(","); FXAction.shakeAmplitude = src.ParseFloat(); src.ExpectTokenString(","); FXAction.shakeDistance = src.ParseFloat(); src.ExpectTokenString(","); FXAction.shakeFalloff = src.ParseBool(); src.ExpectTokenString(","); FXAction.shakeImpulse = src.ParseFloat(); continue; } if ( !token.Icmp( "noshadows" ) ) { FXAction.noshadows = true; continue; } if ( !token.Icmp( "name" ) ) { src.ReadToken( &token ); FXAction.name = token; continue; } if ( !token.Icmp( "fire") ) { src.ReadToken( &token ); FXAction.fire = token; continue; } if ( !token.Icmp( "random" ) ) { FXAction.random1 = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.random2 = src.ParseFloat(); FXAction.delay = 0.0f; // check random continue; } if ( !token.Icmp( "delay" ) ) { FXAction.delay = src.ParseFloat(); continue; } if ( !token.Icmp( "rotate" ) ) { FXAction.rotate = src.ParseFloat(); continue; } if ( !token.Icmp( "duration" ) ) { FXAction.duration = src.ParseFloat(); continue; } if ( !token.Icmp( "trackorigin" ) ) { FXAction.trackOrigin = src.ParseBool(); continue; } if (!token.Icmp("restart")) { FXAction.restart = src.ParseFloat(); continue; } if ( !token.Icmp( "fadeIn" ) ) { FXAction.fadeInTime = src.ParseFloat(); continue; } if ( !token.Icmp( "fadeOut" ) ) { FXAction.fadeOutTime = src.ParseFloat(); continue; } if ( !token.Icmp( "size" ) ) { FXAction.size = src.ParseFloat(); continue; } if ( !token.Icmp( "offset" ) ) { FXAction.offset.x = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.offset.y = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.offset.z = src.ParseFloat(); continue; } if ( !token.Icmp( "axis" ) ) { idVec3 v; v.x = src.ParseFloat(); src.ExpectTokenString( "," ); v.y = src.ParseFloat(); src.ExpectTokenString( "," ); v.z = src.ParseFloat(); v.Normalize(); FXAction.axis = v.ToMat3(); FXAction.explicitAxis = true; continue; } if ( !token.Icmp( "angle" ) ) { idAngles a; a[0] = src.ParseFloat(); src.ExpectTokenString( "," ); a[1] = src.ParseFloat(); src.ExpectTokenString( "," ); a[2] = src.ParseFloat(); FXAction.axis = a.ToMat3(); FXAction.explicitAxis = true; continue; } if ( !token.Icmp( "uselight" ) ) { src.ReadToken( &token ); FXAction.data = token; for( int i = 0; i < events.Num(); i++ ) { if ( events[i].name.Icmp( FXAction.data ) == 0 ) { FXAction.sibling = i; FXAction.lightColor = events[i].lightColor; FXAction.lightRadius = events[i].lightRadius; } } FXAction.type = FX_LIGHT; // precache the light material declManager->FindMaterial( FXAction.data ); continue; } if ( !token.Icmp( "attachlight" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_ATTACHLIGHT; // precache it declManager->FindMaterial( FXAction.data ); continue; } if ( !token.Icmp( "attachentity" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_ATTACHENTITY; // precache the model renderModelManager->FindModel( FXAction.data ); continue; } if ( !token.Icmp( "launch" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_LAUNCH; // precache the entity def declManager->FindType( DECL_ENTITYDEF, FXAction.data ); continue; } if ( !token.Icmp( "useModel" ) ) { src.ReadToken( &token ); FXAction.data = token; for( int i = 0; i < events.Num(); i++ ) { if ( events[i].name.Icmp( FXAction.data ) == 0 ) { FXAction.sibling = i; } } FXAction.type = FX_MODEL; // precache the model renderModelManager->FindModel( FXAction.data ); continue; } if ( !token.Icmp( "light" ) ) { src.ReadToken( &token ); FXAction.data = token; src.ExpectTokenString( "," ); FXAction.lightColor[0] = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.lightColor[1] = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.lightColor[2] = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.lightRadius = src.ParseFloat(); FXAction.type = FX_LIGHT; // precache the light material declManager->FindMaterial( FXAction.data ); continue; } if ( !token.Icmp( "model" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_MODEL; // precache it renderModelManager->FindModel( FXAction.data ); continue; } if ( !token.Icmp( "particle" ) ) { // FIXME: now the same as model src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_PARTICLE; // precache it renderModelManager->FindModel( FXAction.data ); continue; } if ( !token.Icmp( "decal" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_DECAL; // precache it declManager->FindMaterial( FXAction.data ); continue; } if ( !token.Icmp( "particleTrackVelocity" ) ) { FXAction.particleTrackVelocity = true; continue; } if ( !token.Icmp( "sound" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_SOUND; // precache it declManager->FindSound( FXAction.data ); continue; } if ( !token.Icmp( "ignoreMaster" ) ) { FXAction.shakeIgnoreMaster = true; continue; } if ( !token.Icmp( "shockwave" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_SHOCKWAVE; // precache the entity def declManager->FindType( DECL_ENTITYDEF, FXAction.data ); continue; } src.Warning( "FX File: bad token" ); continue; } }
/* ==================== idMD5Mesh::ParseMesh ==================== */ void idMD5Mesh::ParseMesh( idLexer& parser, int numJoints, const idJointMat* joints ) { idToken token; idToken name; parser.ExpectTokenString( "{" ); // // parse name // if( parser.CheckTokenString( "name" ) ) { parser.ReadToken( &name ); } // // parse shader // parser.ExpectTokenString( "shader" ); parser.ReadToken( &token ); idStr shaderName = token; shader = declManager->FindMaterial( shaderName ); // // parse texture coordinates // parser.ExpectTokenString( "numverts" ); int count = parser.ParseInt(); if( count < 0 ) { parser.Error( "Invalid size: %s", token.c_str() ); } this->numVerts = count; idList<idVec2> texCoords; idList<int> firstWeightForVertex; idList<int> numWeightsForVertex; texCoords.SetNum( count ); firstWeightForVertex.SetNum( count ); numWeightsForVertex.SetNum( count ); int numWeights = 0; int maxweight = 0; for( int i = 0; i < texCoords.Num(); i++ ) { parser.ExpectTokenString( "vert" ); parser.ParseInt(); parser.Parse1DMatrix( 2, texCoords[ i ].ToFloatPtr() ); firstWeightForVertex[ i ] = parser.ParseInt(); numWeightsForVertex[ i ] = parser.ParseInt(); if( !numWeightsForVertex[ i ] ) { parser.Error( "Vertex without any joint weights." ); } numWeights += numWeightsForVertex[ i ]; if( numWeightsForVertex[ i ] + firstWeightForVertex[ i ] > maxweight ) { maxweight = numWeightsForVertex[ i ] + firstWeightForVertex[ i ]; } } // // parse tris // parser.ExpectTokenString( "numtris" ); count = parser.ParseInt(); if( count < 0 ) { parser.Error( "Invalid size: %d", count ); } idList<int> tris; tris.SetNum( count * 3 ); numTris = count; for( int i = 0; i < count; i++ ) { parser.ExpectTokenString( "tri" ); parser.ParseInt(); tris[ i * 3 + 0 ] = parser.ParseInt(); tris[ i * 3 + 1 ] = parser.ParseInt(); tris[ i * 3 + 2 ] = parser.ParseInt(); } // // parse weights // parser.ExpectTokenString( "numweights" ); count = parser.ParseInt(); if( count < 0 ) { parser.Error( "Invalid size: %d", count ); } if( maxweight > count ) { parser.Warning( "Vertices reference out of range weights in model (%d of %d weights).", maxweight, count ); } idList<vertexWeight_t> tempWeights; tempWeights.SetNum( count ); assert( numJoints < 256 ); // so we can pack into bytes for( int i = 0; i < count; i++ ) { parser.ExpectTokenString( "weight" ); parser.ParseInt(); int jointnum = parser.ParseInt(); if( ( jointnum < 0 ) || ( jointnum >= numJoints ) ) { parser.Error( "Joint Index out of range(%d): %d", numJoints, jointnum ); } tempWeights[ i ].joint = jointnum; tempWeights[ i ].jointWeight = parser.ParseFloat(); parser.Parse1DMatrix( 3, tempWeights[ i ].offset.ToFloatPtr() ); } // create pre-scaled weights and an index for the vertex/joint lookup idVec4* scaledWeights = ( idVec4* ) Mem_Alloc16( numWeights * sizeof( scaledWeights[0] ), TAG_MD5_WEIGHT ); int* weightIndex = ( int* ) Mem_Alloc16( numWeights * 2 * sizeof( weightIndex[0] ), TAG_MD5_INDEX ); memset( weightIndex, 0, numWeights * 2 * sizeof( weightIndex[0] ) ); count = 0; for( int i = 0; i < texCoords.Num(); i++ ) { int num = firstWeightForVertex[i]; for( int j = 0; j < numWeightsForVertex[i]; j++, num++, count++ ) { scaledWeights[count].ToVec3() = tempWeights[num].offset * tempWeights[num].jointWeight; scaledWeights[count].w = tempWeights[num].jointWeight; weightIndex[count * 2 + 0] = tempWeights[num].joint * sizeof( idJointMat ); } weightIndex[count * 2 - 1] = 1; } parser.ExpectTokenString( "}" ); // update counters c_numVerts += texCoords.Num(); c_numWeights += numWeights; c_numWeightJoints++; for( int i = 0; i < numWeights; i++ ) { c_numWeightJoints += weightIndex[i * 2 + 1]; } // // build a base pose that can be used for skinning // idDrawVert* basePose = ( idDrawVert* )Mem_ClearedAlloc( texCoords.Num() * sizeof( *basePose ), TAG_MD5_BASE ); for( int j = 0, i = 0; i < texCoords.Num(); i++ ) { idVec3 v = ( *( idJointMat* )( ( byte* )joints + weightIndex[j * 2 + 0] ) ) * scaledWeights[j]; while( weightIndex[j * 2 + 1] == 0 ) { j++; v += ( *( idJointMat* )( ( byte* )joints + weightIndex[j * 2 + 0] ) ) * scaledWeights[j]; } j++; basePose[i].Clear(); basePose[i].xyz = v; basePose[i].SetTexCoord( texCoords[i] ); } // build the weights and bone indexes into the verts, so they will be duplicated // as necessary at mirror seems static int maxWeightsPerVert; static float maxResidualWeight; const int MAX_VERTEX_WEIGHTS = 4; idList< bool > jointIsUsed; jointIsUsed.SetNum( numJoints ); for( int i = 0; i < jointIsUsed.Num(); i++ ) { jointIsUsed[i] = false; } numMeshJoints = 0; maxJointVertDist = 0.0f; //----------------------------------------- // new-style setup for fixed four weights and normal / tangent deformation // // Several important models have >25% residual weight in joints after the // first four, which is worrisome for using a fixed four joint deformation. //----------------------------------------- for( int i = 0; i < texCoords.Num(); i++ ) { idDrawVert& dv = basePose[i]; // some models do have >4 joint weights, so it is necessary to sort and renormalize // sort the weights and take the four largest int weights[256]; const int numWeights = numWeightsForVertex[ i ]; for( int j = 0; j < numWeights; j++ ) { weights[j] = firstWeightForVertex[i] + j; } // bubble sort for( int j = 0; j < numWeights; j++ ) { for( int k = 0; k < numWeights - 1 - j; k++ ) { if( tempWeights[weights[k]].jointWeight < tempWeights[weights[k + 1]].jointWeight ) { SwapValues( weights[k], weights[k + 1] ); } } } if( numWeights > maxWeightsPerVert ) { maxWeightsPerVert = numWeights; } const int usedWeights = Min( MAX_VERTEX_WEIGHTS, numWeights ); float totalWeight = 0; for( int j = 0; j < numWeights; j++ ) { totalWeight += tempWeights[weights[j]].jointWeight; } assert( totalWeight > 0.999f && totalWeight < 1.001f ); float usedWeight = 0; for( int j = 0; j < usedWeights; j++ ) { usedWeight += tempWeights[weights[j]].jointWeight; } const float residualWeight = totalWeight - usedWeight; if( residualWeight > maxResidualWeight ) { maxResidualWeight = residualWeight; } byte finalWeights[MAX_VERTEX_WEIGHTS] = { 0 }; byte finalJointIndecies[MAX_VERTEX_WEIGHTS] = { 0 }; for( int j = 0; j < usedWeights; j++ ) { const vertexWeight_t& weight = tempWeights[weights[j]]; const int jointIndex = weight.joint; const float fw = weight.jointWeight; assert( fw >= 0.0f && fw <= 1.0f ); const float normalizedWeight = fw / usedWeight; finalWeights[j] = idMath::Ftob( normalizedWeight * 255.0f ); finalJointIndecies[j] = jointIndex; } // Sort the weights and indices for hardware skinning for( int k = 0; k < 3; ++k ) { for( int l = k + 1; l < 4; ++l ) { if( finalWeights[l] > finalWeights[k] ) { SwapValues( finalWeights[k], finalWeights[l] ); SwapValues( finalJointIndecies[k], finalJointIndecies[l] ); } } } // Give any left over to the biggest weight finalWeights[0] += Max( 255 - finalWeights[0] - finalWeights[1] - finalWeights[2] - finalWeights[3], 0 ); dv.color[0] = finalJointIndecies[0]; dv.color[1] = finalJointIndecies[1]; dv.color[2] = finalJointIndecies[2]; dv.color[3] = finalJointIndecies[3]; dv.color2[0] = finalWeights[0]; dv.color2[1] = finalWeights[1]; dv.color2[2] = finalWeights[2]; dv.color2[3] = finalWeights[3]; for( int j = usedWeights; j < 4; j++ ) { assert( dv.color2[j] == 0 ); } for( int j = 0; j < usedWeights; j++ ) { if( !jointIsUsed[finalJointIndecies[j]] ) { jointIsUsed[finalJointIndecies[j]] = true; numMeshJoints++; } const idJointMat& joint = joints[finalJointIndecies[j]]; float dist = ( dv.xyz - joint.GetTranslation() ).Length(); if( dist > maxJointVertDist ) { maxJointVertDist = dist; } } } meshJoints = ( byte* ) Mem_Alloc( numMeshJoints * sizeof( meshJoints[0] ), TAG_MODEL ); numMeshJoints = 0; for( int i = 0; i < numJoints; i++ ) { if( jointIsUsed[i] ) { meshJoints[numMeshJoints++] = i; } } // build the deformInfo and collect a final base pose with the mirror // seam verts properly including the bone weights deformInfo = R_BuildDeformInfo( texCoords.Num(), basePose, tris.Num(), tris.Ptr(), shader->UseUnsmoothedTangents() ); for( int i = 0; i < deformInfo->numOutputVerts; i++ ) { for( int j = 0; j < 4; j++ ) { if( deformInfo->verts[i].color[j] >= numJoints ) { idLib::FatalError( "Bad joint index" ); } } } Mem_Free( basePose ); }
/* =============== idSoundShader::ParseShader =============== */ bool idSoundShader::ParseShader( idLexer &src ) { int i; idToken token; parms.minDistance = 1; parms.maxDistance = 10; parms.volume = 1; parms.shakes = 0; parms.soundShaderFlags = 0; parms.soundClass = 0; speakerMask = 0; altSound = NULL; for( i = 0; i < SOUND_MAX_LIST_WAVS; i++ ) { leadins[i] = NULL; entries[i] = NULL; } numEntries = 0; numLeadins = 0; int maxSamples = idSoundSystemLocal::s_maxSoundsPerShader.GetInteger(); if ( com_makingBuild.GetBool() || maxSamples <= 0 || maxSamples > SOUND_MAX_LIST_WAVS ) { maxSamples = SOUND_MAX_LIST_WAVS; } while ( 1 ) { if ( !src.ExpectAnyToken( &token ) ) { return false; } // end of definition else if ( token == "}" ) { break; } // minimum number of sounds else if ( !token.Icmp( "minSamples" ) ) { maxSamples = idMath::ClampInt( src.ParseInt(), SOUND_MAX_LIST_WAVS, maxSamples ); } // description else if ( !token.Icmp( "description" ) ) { src.ReadTokenOnLine( &token ); desc = token.c_str(); } // mindistance else if ( !token.Icmp( "mindistance" ) ) { parms.minDistance = src.ParseFloat(); } // maxdistance else if ( !token.Icmp( "maxdistance" ) ) { parms.maxDistance = src.ParseFloat(); } // shakes screen else if ( !token.Icmp( "shakes" ) ) { src.ExpectAnyToken( &token ); if ( token.type == TT_NUMBER ) { parms.shakes = token.GetFloatValue(); } else { src.UnreadToken( &token ); parms.shakes = 1.0f; } } // reverb else if ( !token.Icmp( "reverb" ) ) { int reg0 = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { src.FreeSource(); return false; } int reg1 = src.ParseFloat(); // no longer supported } // volume else if ( !token.Icmp( "volume" ) ) { parms.volume = src.ParseFloat(); } // leadinVolume is used to allow light breaking leadin sounds to be much louder than the broken loop else if ( !token.Icmp( "leadinVolume" ) ) { leadinVolume = src.ParseFloat(); } // speaker mask else if ( !token.Icmp( "mask_center" ) ) { speakerMask |= 1<<SPEAKER_CENTER; } // speaker mask else if ( !token.Icmp( "mask_left" ) ) { speakerMask |= 1<<SPEAKER_LEFT; } // speaker mask else if ( !token.Icmp( "mask_right" ) ) { speakerMask |= 1<<SPEAKER_RIGHT; } // speaker mask else if ( !token.Icmp( "mask_backright" ) ) { speakerMask |= 1<<SPEAKER_BACKRIGHT; } // speaker mask else if ( !token.Icmp( "mask_backleft" ) ) { speakerMask |= 1<<SPEAKER_BACKLEFT; } // speaker mask else if ( !token.Icmp( "mask_lfe" ) ) { speakerMask |= 1<<SPEAKER_LFE; } // soundClass else if ( !token.Icmp( "soundClass" ) ) { parms.soundClass = src.ParseInt(); if ( parms.soundClass < 0 || parms.soundClass >= SOUND_MAX_CLASSES ) { src.Warning( "SoundClass out of range" ); return false; } } // altSound else if ( !token.Icmp( "altSound" ) ) { if ( !src.ExpectAnyToken( &token ) ) { return false; } altSound = declManager->FindSound( token.c_str() ); } // ordered else if ( !token.Icmp( "ordered" ) ) { // no longer supported } // no_dups else if ( !token.Icmp( "no_dups" ) ) { parms.soundShaderFlags |= SSF_NO_DUPS; } // no_flicker else if ( !token.Icmp( "no_flicker" ) ) { parms.soundShaderFlags |= SSF_NO_FLICKER; } // plain else if ( !token.Icmp( "plain" ) ) { // no longer supported } // looping else if ( !token.Icmp( "looping" ) ) { parms.soundShaderFlags |= SSF_LOOPING; } // no occlusion else if ( !token.Icmp( "no_occlusion" ) ) { parms.soundShaderFlags |= SSF_NO_OCCLUSION; } // private else if ( !token.Icmp( "private" ) ) { parms.soundShaderFlags |= SSF_PRIVATE_SOUND; } // antiPrivate else if ( !token.Icmp( "antiPrivate" ) ) { parms.soundShaderFlags |= SSF_ANTI_PRIVATE_SOUND; } // once else if ( !token.Icmp( "playonce" ) ) { parms.soundShaderFlags |= SSF_PLAY_ONCE; } // global else if ( !token.Icmp( "global" ) ) { parms.soundShaderFlags |= SSF_GLOBAL; } // unclamped else if ( !token.Icmp( "unclamped" ) ) { parms.soundShaderFlags |= SSF_UNCLAMPED; } // omnidirectional else if ( !token.Icmp( "omnidirectional" ) ) { parms.soundShaderFlags |= SSF_OMNIDIRECTIONAL; } // onDemand can't be a parms, because we must track all references and overrides would confuse it else if ( !token.Icmp( "onDemand" ) ) { // no longer loading sounds on demand //onDemand = true; } // the wave files else if ( !token.Icmp( "leadin" ) ) { // add to the leadin list if ( !src.ReadToken( &token ) ) { src.Warning( "Expected sound after leadin" ); return false; } if ( soundSystemLocal.soundCache && numLeadins < maxSamples ) { leadins[ numLeadins ] = soundSystemLocal.soundCache->FindSound( token.c_str(), onDemand ); numLeadins++; } } else if ( token.Find( ".wav", false ) != -1 || token.Find( ".ogg", false ) != -1 ) { // add to the wav list if ( soundSystemLocal.soundCache && numEntries < maxSamples ) { token.BackSlashesToSlashes(); idStr lang = cvarSystem->GetCVarString( "sys_lang" ); if ( lang.Icmp( "english" ) != 0 && token.Find( "sound/vo/", false ) >= 0 ) { idStr work = token; work.ToLower(); work.StripLeading( "sound/vo/" ); work = va( "sound/vo/%s/%s", lang.c_str(), work.c_str() ); if ( fileSystem->ReadFile( work, NULL, NULL ) > 0 ) { token = work; } else { // also try to find it with the .ogg extension work.SetFileExtension( ".ogg" ); if ( fileSystem->ReadFile( work, NULL, NULL ) > 0 ) { token = work; } } } entries[ numEntries ] = soundSystemLocal.soundCache->FindSound( token.c_str(), onDemand ); numEntries++; } } else { src.Warning( "unknown token '%s'", token.c_str() ); return false; } } if ( parms.shakes > 0.0f ) { CheckShakesAndOgg(); } return true; }
/* ================ idTypeInfoTools::CompareGameState ================ */ void idTypeInfoTools::CompareGameState( const char *fileName ) { int entityNum; idToken token; src = new idLexer(); src->SetFlags( LEXFL_NOSTRINGESCAPECHARS ); if ( !src->LoadFile( fileName ) ) { common->Warning( "couldn't load %s", fileName ); delete src; src = NULL; return; } fp = NULL; Write = VerifyVariable; #ifdef DUMP_GAMELOCAL if ( !src->ExpectTokenString( "gameLocal" ) || !src->ExpectTokenString( "{" ) ) { delete src; src = NULL; return; } WriteClass_r( (void *)&gameLocal, "", "idGameLocal", "idGameLocal", "", 0 ); if ( !src->ExpectTokenString( "}" ) ) { delete src; src = NULL; return; } #endif while( src->ReadToken( &token ) ) { if ( token != "entity" ) { break; } if ( !src->ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ) ) { break; } entityNum = token.GetIntValue(); if ( entityNum < 0 || entityNum >= gameLocal.num_entities ) { src->Warning( "entity number %d out of range", entityNum ); break; } typeError = false; idEntity *ent = gameLocal.entities[entityNum]; if ( !ent ) { src->Warning( "entity %d is not spawned", entityNum ); src->SkipBracedSection( true ); continue; } if ( !src->ExpectTokenType( TT_NAME, 0, &token ) ) { break; } if ( token.Cmp( ent->GetType()->classname ) != 0 ) { src->Warning( "entity %d has wrong type", entityNum ); src->SkipBracedSection( true ); continue; } if ( !src->ExpectTokenString( "{" ) ) { src->Warning( "entity %d missing leading {", entityNum ); break; } WriteClass_r( (void *)ent, "", ent->GetType()->classname, ent->GetType()->classname, "", 0 ); if ( !src->SkipBracedSection( false ) ) { src->Warning( "entity %d missing trailing }", entityNum ); break; } } delete src; src = NULL; }