public override bool Parse(string text) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } idLexer lexer = new idLexer(idDeclFile.LexerOptions); lexer.LoadMemory(text, this.FileName, this.LineNumber); lexer.SkipUntilString("{"); idToken token; idToken token2; string value; while(true) { if((token = lexer.ReadToken()) == null) { break; } value = token.ToString(); if(value == "}") { break; } if(token.Type != TokenType.String) { lexer.Warning("Expected quoted string, but found '{0}'", value); MakeDefault(); return false; } if((token2 = lexer.ReadToken()) == null) { lexer.Warning("Unexpected end of file"); MakeDefault(); return false; } if(_dict.ContainsKey(value) == true) { lexer.Warning("'{0}' already defined", value); } _dict.Set(value, token2.ToString()); } // we always automatically set a "classname" key to our name _dict.Set("classname", this.Name); // "inherit" keys will cause all values from another entityDef to be copied into this one // if they don't conflict. We can't have circular recursions, because each entityDef will // never be parsed more than once // find all of the dicts first, because copying inherited values will modify the dict List<idDeclEntity> defList = new List<idDeclEntity>(); List<string> keysToRemove = new List<string>(); foreach(KeyValuePair<string, string> kvp in _dict.MatchPrefix("inherit")) { idDeclEntity copy = idE.DeclManager.FindType<idDeclEntity>(DeclType.EntityDef, kvp.Value, false); if(copy == null) { lexer.Warning("Unknown entityDef '{0}' inherited by '{1}'", kvp.Value, this.Name); } else { defList.Add(copy); } // delete this key/value pair keysToRemove.Add(kvp.Key); } _dict.Remove(keysToRemove.ToArray()); // now copy over the inherited key / value pairs foreach(idDeclEntity def in defList) { _dict.SetDefaults(def._dict); } // precache all referenced media // do this as long as we arent in modview idE.Game.CacheDictionaryMedia(_dict); return true; }
/// <summary> /// Parses the current material definition and finds all necessary images. /// </summary> /// <param name="text"></param> /// <returns></returns> public override bool Parse(string text) { idLexer lexer = new idLexer(idDeclFile.LexerOptions); lexer.LoadMemory(text, this.FileName, this.LineNumber); lexer.SkipUntilString("{"); // reset to the unparsed state. Clear(); _parsingData = new MaterialParsingData(); // this is only valid during parsing. // parse it ParseMaterial(lexer); // TODO: fs_copyFiles // if we are doing an fs_copyfiles, also reference the editorImage /*if ( cvarSystem->GetCVarInteger( "fs_copyFiles" ) ) { GetEditorImage(); }*/ // count non-lit stages. _ambientStageCount = 0; _stageCount = _parsingData.Stages.Count; for(int i = 0; i < _stageCount; i++) { if(_parsingData.Stages[i].Lighting == StageLighting.Ambient) { _ambientStageCount++; } } // see if there is a subview stage if(_sort == (float) MaterialSort.Subview) { _hasSubview = true; } else { _hasSubview = false; int count = _parsingData.Stages.Count; for(int i = 0; i < count; i++) { if(_parsingData.Stages[i].Texture.Dynamic != null) { _hasSubview = true; } } } // automatically determine coverage if not explicitly set. if(_coverage == MaterialCoverage.Bad) { // automatically set MC_TRANSLUCENT if we don't have any interaction stages and // the first stage is blended and not an alpha test mask or a subview. if(_stageCount == 0) { // non-visible. _coverage = MaterialCoverage.Translucent; } else if(_stageCount != _ambientStageCount) { // we have an interaction draw. _coverage = MaterialCoverage.Opaque; } else { MaterialStates drawStateBits = _parsingData.Stages[0].DrawStateBits & MaterialStates.SourceBlendBits; if(((drawStateBits & MaterialStates.DestinationBlendBits) != MaterialStates.DestinationBlendZero) || (drawStateBits == MaterialStates.SourceBlendDestinationColor) || (drawStateBits == MaterialStates.SourceBlendOneMinusDestinationColor) || (drawStateBits == MaterialStates.SourceBlendDestinationAlpha) || (drawStateBits == MaterialStates.SourceBlendOneMinusDestinationAlpha)) { // blended with the destination _coverage = MaterialCoverage.Translucent; } else { _coverage = MaterialCoverage.Opaque; } } } // translucent automatically implies noshadows. if(_coverage == MaterialCoverage.Translucent) { this.MaterialFlag = MaterialFlags.NoShadows; } else { // mark the contents as opaque. _contentFlags |= ContentFlags.Opaque; } // the sorts can make reasonable defaults. if(_sort == (float) MaterialSort.Bad) { if(TestMaterialFlag(MaterialFlags.PolygonOffset) == true) { _sort = (float) MaterialSort.Decal; } else if(_coverage == MaterialCoverage.Translucent) { _sort = (float) MaterialSort.Medium; } else { _sort = (float) MaterialSort.Opaque; } } // anything that references _currentRender will automatically get sort = SS_POST_PROCESS // and coverage = MC_TRANSLUCENT. for(int i = 0; i < _stageCount; i++) { MaterialStage stage = _parsingData.Stages[i]; if(stage.Texture.Image == idE.ImageManager.CurrentRenderImage) { if(_sort != (float) MaterialSort.PortalSky) { _sort = (float) MaterialSort.PostProcess; _coverage = MaterialCoverage.Translucent; } break; } if(stage.NewStage.IsEmpty == false) { NewMaterialStage newShaderStage = stage.NewStage; int imageCount = newShaderStage.FragmentProgramImages.Length; for(int j = 0; j < imageCount; j++) { if(newShaderStage.FragmentProgramImages[j] == idE.ImageManager.CurrentRenderImage) { if(_sort != (float) MaterialSort.PortalSky) { _sort = (float) MaterialSort.PostProcess; _coverage = MaterialCoverage.Translucent; } i = _stageCount; break; } } } } // set the drawStateBits depth flags. for(int i = 0; i < _stageCount; i++) { MaterialStage stage = _parsingData.Stages[i]; if(_sort == (float) MaterialSort.PostProcess) { // post-process effects fill the depth buffer as they draw, so only the // topmost post-process effect is rendered. stage.DrawStateBits |= MaterialStates.DepthFunctionLess; } else if((_coverage == MaterialCoverage.Translucent) || (stage.IgnoreAlphaTest == true)) { // translucent surfaces can extend past the exactly marked depth buffer. stage.DrawStateBits |= MaterialStates.DepthFunctionLess | MaterialStates.DepthMask; } else { // opaque and perforated surfaces must exactly match the depth buffer, // which gets alpha test correct. stage.DrawStateBits |= MaterialStates.DepthFunctionEqual | MaterialStates.DepthMask; } _parsingData.Stages[i] = stage; } // determine if this surface will accept overlays / decals. if(_parsingData.ForceOverlays == true) { // explicitly flaged in material definition _allowOverlays = true; } else { if(this.IsDrawn == false) { _allowOverlays = false; } if(this.Coverage != MaterialCoverage.Opaque) { _allowOverlays = false; } if((this.SurfaceFlags & Renderer.SurfaceFlags.NoImpact) == Renderer.SurfaceFlags.NoImpact) { _allowOverlays = false; } } // add a tiny offset to the sort orders, so that different materials // that have the same sort value will at least sort consistantly, instead // of flickering back and forth. /* this messed up in-game guis if ( sort != SS_SUBVIEW ) { int hash, l; l = name.Length(); hash = 0; for ( int i = 0 ; i < l ; i++ ) { hash ^= name[i]; } sort += hash * 0.01; } */ if(_stageCount > 0) { _stages = _parsingData.Stages.ToArray(); } if(_parsingData.Operations.Count > 0) { _ops = _parsingData.Operations.ToArray(); } if(_registerCount > 0) { _expressionRegisters = new float[_registerCount]; Array.Copy(_parsingData.ShaderRegisters, _expressionRegisters, _registerCount); } // see if the registers are completely constant, and don't need to be evaluated per-surface. CheckForConstantRegisters(); _parsingData = null; // finish things up if(TestMaterialFlag(MaterialFlags.Defaulted) == true) { MakeDefault(); return false; } return true; }
public override bool Parse(string text) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } idLexer lexer = new idLexer(idDeclFile.LexerOptions); lexer.LoadMemory(text, this.FileName, this.LineNumber); lexer.SkipUntilString("{"); // deeper functions can set this, which will cause MakeDefault() to be called at the end _errorDuringParse = false; if((ParseMaterial(lexer) == false) || (_errorDuringParse == true)) { MakeDefault(); return false; } return true; }
public virtual bool Parse(string text) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } idLexer lexer = new idLexer(idDeclFile.LexerOptions); lexer.LoadMemory(text, this.FileName, this.LineNumber); lexer.SkipUntilString("{"); lexer.SkipBracedSection(false); return true; }
public override bool Parse(string text) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } idLexer lexer = new idLexer(idDeclFile.LexerOptions); lexer.LoadMemory(text, this.FileName, this.LineNumber); lexer.SkipUntilString("{"); int defaultAnimationCount = 0; idToken token; idToken token2; string tokenValue; string fileName; string extension; int count; idMD5Joint[] md5Joints; while(true) { if((token = lexer.ReadToken()) == null) { break; } tokenValue = token.ToString(); if(tokenValue == "}") { break; } if(tokenValue == "inherit") { idConsole.WriteLine("TODO: inherit"); /*if( !src.ReadToken( &token2 ) ) { src.Warning( "Unexpected end of file" ); MakeDefault(); return false; } const idDeclModelDef *copy = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, token2, false ) ); if ( !copy ) { common->Warning( "Unknown model definition '%s'", token2.c_str() ); } else if ( copy->GetState() == DS_DEFAULTED ) { common->Warning( "inherited model definition '%s' defaulted", token2.c_str() ); MakeDefault(); return false; } else { CopyDecl( copy ); numDefaultAnims = anims.Num(); }*/ } else if(tokenValue == "skin") { if((token2 = lexer.ReadToken()) == null) { lexer.Warning("Unexpected end of file"); MakeDefault(); return false; } _skin = idE.DeclManager.FindSkin(token2.ToString()); if(_skin == null) { lexer.Warning("Skin '{0}' not found", token2.ToString()); MakeDefault(); return false; } } else if(tokenValue == "mesh") { if((token2 = lexer.ReadToken()) == null) { lexer.Warning("Unexpected end of file"); MakeDefault(); return false; } fileName = token2.ToString(); extension = Path.GetExtension(fileName); if(extension != idRenderModel_MD5.MeshExtension) { lexer.Warning("Invalid model for MD5 mesh"); MakeDefault(); return false; } _model = idE.RenderModelManager.FindModel(fileName); if(_model == null) { lexer.Warning("Model '{0}' not found", fileName); MakeDefault(); return false; } else if(_model.IsDefault == true) { lexer.Warning("Model '{0}' defaulted", fileName); MakeDefault(); return false; } // get the number of joints count = _model.JointCount; if(count == 0) { lexer.Warning("Model '{0}' has no joints", fileName); } // set up the joint hierarchy md5Joints = _model.Joints; _joints = new JointInfo[count]; _jointParents = new int[count]; _channelJoints = new int[(int) AnimationChannel.Count][]; _channelJoints[0] = new int[count]; for(int i = 0; i < count; i++) { _joints[i] = new JointInfo(); _joints[i].Channel = AnimationChannel.All; _joints[i].Index = i; if(md5Joints[i].Parent != null) { _joints[i].ParentIndex = _model.GetJointIndex(md5Joints[i].Parent); } else { _joints[i].ParentIndex = -1; } _jointParents[i] = _joints[i].ParentIndex; _channelJoints[0][i] = i; } } else if(tokenValue == "remove") { idConsole.Warning("TODO: remove"); // removes any anims whos name matches /*if( !src.ReadToken( &token2 ) ) { src.Warning( "Unexpected end of file" ); MakeDefault(); return false; } num = 0; for( i = 0; i < anims.Num(); i++ ) { if ( ( token2 == anims[ i ]->Name() ) || ( token2 == anims[ i ]->FullName() ) ) { delete anims[ i ]; anims.RemoveIndex( i ); if ( i >= numDefaultAnims ) { src.Warning( "Anim '%s' was not inherited. Anim should be removed from the model def.", token2.c_str() ); MakeDefault(); return false; } i--; numDefaultAnims--; num++; continue; } } if ( !num ) { src.Warning( "Couldn't find anim '%s' to remove", token2.c_str() ); MakeDefault(); return false; }*/ } else if(tokenValue == "anim") { if(_model == null) { lexer.Warning("Must specify mesh before defining anims"); MakeDefault(); return false; } else if(ParseAnimation(lexer, defaultAnimationCount) == false) { MakeDefault(); return false; } } else if(tokenValue == "offset") { float[] tmp = lexer.Parse1DMatrix(3); if(tmp == null) { lexer.Warning("Expected vector following 'offset'"); MakeDefault(); return false; } _offset = new Vector3(tmp[0], tmp[1], tmp[2]); } else if(tokenValue == "channel") { if(_model == null) { lexer.Warning("Must specify mesh before defining channels"); MakeDefault(); return false; } // set the channel for a group of joints if((token2 = lexer.ReadToken()) == null) { lexer.Warning("Unexpected end of file"); MakeDefault(); return false; } if(lexer.CheckTokenString("(") == false) { lexer.Warning("Expected { after '{0}'", token2.ToString()); MakeDefault(); return false; } int i; int channelCount = (int) AnimationChannel.Count; for(i = (int) AnimationChannel.All + 1; i < channelCount; i++) { if(ChannelNames[i].Equals(token2.ToString(), StringComparison.OrdinalIgnoreCase) == true) { break; } } if(i >= channelCount) { lexer.Warning("Unknown channel '{0}'", token2.ToString()); MakeDefault(); return false; } int channel = i; StringBuilder jointNames = new StringBuilder(); string token2Value; while(lexer.CheckTokenString(")") == false) { if((token2 = lexer.ReadToken()) == null) { lexer.Warning("Unexpected end of file"); MakeDefault(); return false; } token2Value = token2.ToString(); jointNames.Append(token2Value); if((token2Value != "*") && (token2Value != "-")) { jointNames.Append(" "); } } int[] jointList = GetJointList(jointNames.ToString()); int jointLength = jointList.Length; List<int> channelJoints = new List<int>(); for(count = i = 0; i < jointLength; i++) { int jointIndex = jointList[i]; if(_joints[jointIndex].Channel != AnimationChannel.All) { lexer.Warning("Join '{0}' assigned to multiple channels", _model.GetJointName(jointIndex)); continue; } _joints[jointIndex].Channel = (AnimationChannel) channel; channelJoints.Add(jointIndex); } _channelJoints[channel] = channelJoints.ToArray(); } else { lexer.Warning("unknown token '{0}'", token.ToString()); MakeDefault(); return false; } } return true; }