/// <summary> /// /// </summary> /// <remarks> /// Normally this will use a .reg file instead of a .map file if it exists, /// which is what the game and dmap want, but the editor will want to always /// load a .map file. /// </remarks> /// <param name="fileName">Does not require an extension.</param> /// <param name="ignoreRegion"></param> /// <param name="osPath"></param> /// <returns></returns> public bool Parse(string fileName, bool ignoreRegion = false, bool osPath = false) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } _hasPrimitiveData = false; _name = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName)); string fullName = _name; // no string concatenation for epairs and allow path names for materials idLexer lexer = new idLexer(LexerOptions.NoStringConcatination | LexerOptions.NoStringEscapeCharacters | LexerOptions.AllowPathNames); idMapEntity mapEnt; if(ignoreRegion == false) { // try loading a .reg file first lexer.LoadFile(fullName + ".reg", osPath); } if(lexer.IsLoaded == false) { // now try a .map file lexer.LoadFile(fullName + ".map", osPath); if(lexer.IsLoaded == false) { // didn't get anything at all return false; } } _version = idMapFile.OldMapVersion; _fileTime = lexer.FileTime; _entities.Clear(); if(lexer.CheckTokenString("Version") == true) { _version = lexer.ReadTokenOnLine().ToFloat(); } while(true) { if((mapEnt = idMapEntity.Parse(lexer, (_entities.Count == 0), _version)) == null) { break; } _entities.Add(mapEnt); } idConsole.Warning("TODO: SetGeometryCRC();"); // if the map has a worldspawn if(_entities.Count > 0) { // "removeEntities" "classname" can be set in the worldspawn to remove all entities with the given classname foreach(KeyValuePair<string, string> removeEntities in _entities[0].Dict.MatchPrefix("removeEntities")) { RemoveEntities(removeEntities.Value); } // "overrideMaterial" "material" can be set in the worldspawn to reset all materials string material; int entityCount = _entities.Count; int primitiveCount = 0; int sideCount = 0; if((material = (_entities[0].Dict.GetString("overrideMaterial", ""))) != string.Empty) { for(int i = 0; i < entityCount; i++) { mapEnt = _entities[i]; primitiveCount = mapEnt.Primitives.Count; for(int j = 0; j < primitiveCount; j++) { idMapPrimitive mapPrimitive = mapEnt.GetPrimitive(j); switch(mapPrimitive.Type) { case MapPrimitiveType.Brush: idMapBrush mapBrush = (idMapBrush) mapPrimitive; sideCount = mapBrush.SideCount; for(int k = 0; k < sideCount; k++) { mapBrush.GetSide(k).Material = material; } break; case MapPrimitiveType.Patch: idConsole.Warning("TODO: PATCH"); // TODO: ((idMapPatch) mapPrimitive).Material = material; break; } } } } // force all entities to have a name key/value pair if(_entities[0].Dict.GetBool("forceEntityNames") == true) { for(int i = 1; i < entityCount; i++) { mapEnt = _entities[i]; if(mapEnt.Dict.ContainsKey("name") == false) { mapEnt.Dict.Set("name", string.Format("{0}{1}", mapEnt.Dict.GetString("classname", "forcedName"), i)); } } } // move the primitives of any func_group entities to the worldspawn if(_entities[0].Dict.GetBool("moveFuncGroups") == true) { for(int i = 1; i < entityCount; i++) { mapEnt = _entities[i]; if(mapEnt.Dict.GetString("classname").ToLower() == "func_group") { _entities[0].Primitives.AddRange(mapEnt.Primitives); mapEnt.Primitives.Clear(); } } } } _hasPrimitiveData = true; return true; }
public bool LoadAnimation(string fileName) { idToken token; idLexer lexer = new idLexer(LexerOptions.AllowPathNames | LexerOptions.NoStringEscapeCharacters | LexerOptions.NoStringConcatination); if(lexer.LoadFile(fileName) == false) { return false; } Clear(); _name = fileName; lexer.ExpectTokenString(idRenderModel_MD5.VersionString); int version = lexer.ParseInt(); if(version != idRenderModel_MD5.Version) { lexer.Error("Invalid version {0}. Should be version {1}", version, idRenderModel_MD5.Version); } // skip the commandline lexer.ExpectTokenString("commandline"); lexer.ReadToken(); // parse num frames lexer.ExpectTokenString("numFrames"); int frameCount = lexer.ParseInt(); if(frameCount <= 0) { lexer.Error("Invalid number of frames: {0}", frameCount); } // parse num joints lexer.ExpectTokenString("numJoints"); int jointCount = lexer.ParseInt(); if(jointCount <= 0) { lexer.Error("Invalid number of joints: {0}", jointCount); } // parse frame rate lexer.ExpectTokenString("frameRate"); _frameRate = lexer.ParseInt(); if(_frameRate < 0) { lexer.Error("Invalid frame rate: {0}", _frameRate); } // parse number of animated components lexer.ExpectTokenString("numAnimatedComponents"); _animatedComponentCount = lexer.ParseInt(); if((_animatedComponentCount < 0) || (_animatedComponentCount > (jointCount * 6))) { lexer.Error("Invalid number of animated components: {0}", _animatedComponentCount); } // parse the hierarchy _jointInfo = new JointAnimationInfo[jointCount]; lexer.ExpectTokenString("hierarchy"); lexer.ExpectTokenString("{"); for(int i = 0; i < jointCount; i++) { token = lexer.ReadToken(); _jointInfo[i] = new JointAnimationInfo(); _jointInfo[i].NameIndex = idR.AnimManager.GetJointIndex(token.ToString()); // parse parent num _jointInfo[i].ParentIndex = lexer.ParseInt(); if(_jointInfo[i].ParentIndex >= i) { lexer.Error("Invalid parent num: {0}", _jointInfo[i].ParentIndex); } if((i != 0) && (_jointInfo[i].ParentIndex < 0)) { lexer.Error("Animations may have only one root joint"); } // parse anim bits _jointInfo[i].AnimationBits = (AnimationBits) lexer.ParseInt(); if(((int) _jointInfo[i].AnimationBits & ~63) != 0) { lexer.Error("Invalid anim bits: {0}", _jointInfo[i].AnimationBits); } // parse first component _jointInfo[i].FirstComponent = lexer.ParseInt(); if((_animatedComponentCount > 0) && ((_jointInfo[i].FirstComponent < 0) || (_jointInfo[i].FirstComponent >= _animatedComponentCount))) { lexer.Error("Invalid first component: {0}", _jointInfo[i].FirstComponent); } } lexer.ExpectTokenString("}"); // parse bounds lexer.ExpectTokenString("bounds"); lexer.ExpectTokenString("{"); _bounds = new idBounds[frameCount]; for(int i = 0; i < frameCount; i++) { float[] tmp = lexer.Parse1DMatrix(3); float[] tmp2 = lexer.Parse1DMatrix(3); _bounds[i] = new idBounds( new Vector3(tmp[0], tmp[1], tmp[2]), new Vector3(tmp2[0], tmp2[1], tmp2[2]) ); } lexer.ExpectTokenString("}"); // parse base frame _baseFrame = new idJointQuaternion[jointCount]; lexer.ExpectTokenString("baseframe"); lexer.ExpectTokenString("{"); for(int i = 0; i < jointCount; i++) { float[] tmp = lexer.Parse1DMatrix(3); float[] tmp2 = lexer.Parse1DMatrix(3); idCompressedQuaternion q = new idCompressedQuaternion(tmp2[0], tmp2[1], tmp2[2]); _baseFrame[i] = new idJointQuaternion(); _baseFrame[i].Translation = new Vector3(tmp[0], tmp[1], tmp[2]); _baseFrame[i].Quaternion = q.ToQuaternion(); } lexer.ExpectTokenString("}"); // parse frames _componentFrames = new float[_animatedComponentCount * frameCount]; int frameOffset = 0; for(int i = 0; i < frameCount; i++) { lexer.ExpectTokenString("frame"); int count = lexer.ParseInt(); if(count != i) { lexer.Error("Expected frame number {0}", i); } lexer.ExpectTokenString("{"); for(int j = 0; j < _animatedComponentCount; j++, frameOffset++) { _componentFrames[frameOffset] = lexer.ParseFloat(); } lexer.ExpectTokenString("}"); } // get total move delta if(_animatedComponentCount == 0) { _totalDelta = Vector3.Zero; } else { int componentOffset = _jointInfo[0].FirstComponent; if((_jointInfo[0].AnimationBits & AnimationBits.TranslationX) == AnimationBits.TranslationX) { for(int i = 0; i < frameCount; i++) { _componentFrames[componentOffset + (_animatedComponentCount * i)] -= _baseFrame[0].Translation.X; } _totalDelta.X = _componentFrames[componentOffset + (_animatedComponentCount * (frameCount - 1))]; componentOffset++; } else { _totalDelta.X = 0; } if((_jointInfo[0].AnimationBits & AnimationBits.TranslationY) == AnimationBits.TranslationY) { for(int i = 0; i < frameCount; i++) { _componentFrames[componentOffset + (_animatedComponentCount * i)] -= _baseFrame[0].Translation.Y; } _totalDelta.Y = _componentFrames[componentOffset + (_animatedComponentCount * (frameCount - 1))]; componentOffset++; } else { _totalDelta.Y = 0; } if((_jointInfo[0].AnimationBits & AnimationBits.TranslationZ) == AnimationBits.TranslationZ) { for(int i = 0; i < frameCount; i++) { _componentFrames[componentOffset + (_animatedComponentCount * i)] -= _baseFrame[0].Translation.Z; } _totalDelta.Z = _componentFrames[componentOffset + (_animatedComponentCount * (frameCount - 1))]; } else { _totalDelta.Z = 0; } } _baseFrame[0].Translation = Vector3.Zero; // we don't count last frame because it would cause a 1 frame pause at the end _animLength = ((frameCount - 1) * 1000 + _frameRate - 1) / _frameRate; // done return true; }
private bool Directive_Include() { idLexer script; idToken token; string path; if((token = ReadSourceToken()) == null) { Error("#include without file name"); return false; } else if(token.LinesCrossed > 0) { Error("#include without file name"); return false; } else if(token.Type == TokenType.String) { script = new idLexer(); // try relative to the current file path = Path.Combine(Path.GetDirectoryName(_scriptStack.Peek().FileName), token.ToString()); if(script.LoadFile(path, _osPath) == false) { // try absolute path path = token.ToString(); if(script.LoadFile(path, _osPath) == false) { // try from the include path path = _includePath + token.ToString(); if(script.LoadFile(path, _osPath) == false) { script = null; } } } } else if((token.Type == TokenType.Punctuation) && (token.ToString() == "<")) { path = _includePath; while((token = ReadSourceToken()) != null) { if(token.LinesCrossed > 0) { UnreadSourceToken(token); break; } else if((token.Type == TokenType.Punctuation) && (token.ToString() == ">")) { break; } path += token.ToString(); } if(token.ToString() != ">") { Warning("#include missing trailing >"); } else if(path == string.Empty) { Error("#include without file name between < >"); return false; } else if((_options & LexerOptions.NoBaseIncludes) == LexerOptions.NoBaseIncludes) { return true; } script = new idLexer(); throw new Exception("ZZ"); /*if(script.LoadFile(_includePath + path, _osPath) == false) { script = null; }*/ } else { Error("#include without file name"); return false; } if(script == null) { Error("file '{0}' not found", path); return false; } script.Options = _options; script.Punctuation = _punctuation; PushScript(script); return true; }
/// <summary> /// Load the given source. /// </summary> /// <returns></returns> public bool LoadFile(string fileName, bool osPath) { if(_loaded == true) { idConsole.FatalError("idScriptParser::LoadMemory: another source already loaded"); return false; } idLexer script = new idLexer(_options); script.Punctuation = _punctuation; script.LoadFile(fileName, osPath); if(script.IsLoaded == false) { return false; } _fileName = fileName; _scriptStack.Clear(); _indentStack.Clear(); _tokens.Clear(); _skip = 0; _loaded = true; _scriptStack.Push(script); if(_defineDict == null) { _defines.Clear(); _defineDict = new Dictionary<string, ScriptDefinition>(StringComparer.OrdinalIgnoreCase); AddGlobalDefinesToSource(); } return true; }
private bool LoadCollisionModelFile(string name, ulong mapFileCRC) { // load it string fileName = Path.Combine(Path.GetDirectoryName(name), Path.GetFileNameWithoutExtension(name) + Extension); idLexer lexer = new idLexer(LexerOptions.NoStringConcatination | LexerOptions.NoDollarPrecompilation); if(lexer.LoadFile(fileName) == false) { return false; } idToken token; if(lexer.ExpectTokenString(TokenFileID) == false) { idConsole.Warning("{0} is not a CM file.", fileName); } else if(((token = lexer.ReadToken()) == null) || (token.ToString() != FileVersion)) { idConsole.Warning("{0} has version {1} instead of {2}", fileName, token, FileVersion); } else if((token = lexer.ExpectTokenType(TokenType.Number, TokenSubType.Integer)) == null) { idConsole.Warning("{0} has no map file CRC", fileName); } else { ulong crc = token.ToUInt64(); if((mapFileCRC != 0) && (crc != mapFileCRC)) { idConsole.WriteLine("{0} is out of date", fileName); } else { // parse the file while(true) { if((token = lexer.ReadToken()) == null) { break; } if(token.ToString().ToLower() == "collisionmodel") { if(ParseCollisionModel(lexer) == false) { return false; } } else { lexer.Error("idCollisionModelManagerLocal::LoadCollisionModelFile: bad token \"{0}\"", token); } } return true; } } return false; }
/// <summary> /// Used for initial loads, reloadModel, and reloading the data of purged models. /// </summary> /// <remarks> /// Upon exit, the model will absolutely be valid, but possibly as a default model. /// </remarks> public override void Load() { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } if(_purged == false) { Purge(); } _purged = false; idLexer lexer = new idLexer(LexerOptions.AllowPathNames | LexerOptions.NoStringEscapeCharacters); if(lexer.LoadFile(Name) == false) { MakeDefault(); return; } lexer.ExpectTokenString(VersionString); int version = lexer.ParseInt(); int count = 0; idToken token; if(version != Version) { lexer.Error("Invalid version {0}. Should be version {1}", version, Version); } // // skip commandline // lexer.ExpectTokenString("commandline"); lexer.ReadToken(); // parse num joints lexer.ExpectTokenString("numJoints"); count = lexer.ParseInt(); _joints = new idMD5Joint[count]; _defaultPose = new idJointQuaternion[count]; idJointMatrix[] poseMat3 = new idJointMatrix[count]; // parse num meshes lexer.ExpectTokenString("numMeshes"); count = lexer.ParseInt(); if(count < 0) { lexer.Error("Invalid size: {0}", count); } _meshes = new idMD5Mesh[count]; // // parse joints // lexer.ExpectTokenString("joints"); lexer.ExpectTokenString("{"); int jointCount = _joints.Length; for(int i = 0; i < jointCount; i++) { idMD5Joint joint = _joints[i] = new idMD5Joint(); idJointQuaternion pose = new idJointQuaternion(); ParseJoint(lexer, joint, ref pose); poseMat3[i] = idJointMatrix.Zero; poseMat3[i].Rotation = Matrix.CreateFromQuaternion(pose.Quaternion); poseMat3[i].Translation = pose.Translation; if(joint.Parent != null) { int parentIndex = GetJointIndex(joint.Parent); pose.Quaternion = Quaternion.CreateFromRotationMatrix(poseMat3[i].ToMatrix() * Matrix.Transpose(poseMat3[parentIndex].ToMatrix())); pose.Translation = Vector3.Transform(poseMat3[i].ToVector3() - poseMat3[parentIndex].ToVector3(), Matrix.Transpose(poseMat3[parentIndex].ToMatrix())); } _defaultPose[i] = pose; } lexer.ExpectTokenString("}"); int meshCount = _meshes.Length; for(int i = 0; i < meshCount; i++) { lexer.ExpectTokenString("mesh"); _meshes[i] = new idMD5Mesh(); _meshes[i].Parse(lexer, poseMat3); } // // calculate the bounds of the model // CalculateBounds(poseMat3); // set the timestamp for reloadmodels idConsole.Warning("TODO: fileSystem->ReadFile( name, NULL, &timeStamp );"); }
/// <summary> /// /// </summary> /// <remarks> /// A NULL or empty name will make a world without a map model, which /// is still useful for displaying a bare model. /// </remarks> /// <param name="name"></param> /// <returns></returns> public bool InitFromMap(string name) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } // if this is an empty world, initialize manually if((name == null) || (name == string.Empty)) { FreeWorld(); ClearWorld(); _mapName = string.Empty; return true; } // load it string fileName = string.Format("{0}.{1}", Path.Combine(Path.GetDirectoryName(name), Path.GetFileNameWithoutExtension(name)), idE.ProcFileExtension); // if we are reloading the same map, check the timestamp // and try to skip all the work // TODO: timestamps /*ID_TIME_T currentTimeStamp; fileSystem->ReadFile( filename, NULL, ¤tTimeStamp );*/ /*if ( name == mapName ) { if ( currentTimeStamp != FILE_NOT_FOUND_TIMESTAMP && currentTimeStamp == mapTimeStamp ) { common->Printf( "idRenderWorldLocal::InitFromMap: retaining existing map\n" ); FreeDefs(); TouchWorldModels(); AddWorldModelEntities(); ClearPortalStates(); return true; } common->Printf( "idRenderWorldLocal::InitFromMap: timestamp has changed, reloading.\n" ); }*/ FreeWorld(); idLexer lexer = new idLexer(LexerOptions.NoStringConcatination | LexerOptions.NoDollarPrecompilation); if(lexer.LoadFile(fileName) == false) { idConsole.WriteLine("idRenderWorld.InitFromMap: {0} not found", fileName); ClearWorld(); return false; } _mapName = name; // TODO: mapTimeStamp = currentTimeStamp; // if we are writing a demo, archive the load command // TODO: demo /*if ( session->writeDemo ) { WriteLoadMap(); }*/ idToken token; idRenderModel lastModel; string tokenValue; if(((token = lexer.ReadToken()) == null) || (token.ToString().Equals(idE.ProcFileID, StringComparison.OrdinalIgnoreCase) == false)) { idConsole.WriteLine("idRenderWorld.InitFromMap: bad id '{0}' instead of '{1}'", token, idE.ProcFileID); return false; } // parse the file while(true) { if((token = lexer.ReadToken()) == null) { break; } tokenValue = token.ToString(); if((tokenValue == "model") || (tokenValue == "shadowModel")) { if(tokenValue == "model") { lastModel = ParseModel(lexer); } else { lastModel = ParseShadowModel(lexer); } // add it to the model manager list idE.RenderModelManager.AddModel(lastModel); // save it in the list to free when clearing this map _localModels.Add(lastModel); } else if(tokenValue == "interAreaPortals") { ParseInterAreaPortals(lexer); } else if(tokenValue == "nodes") { ParseNodes(lexer); } else { lexer.Error("idRenderWorld.InitFromMap: bad token \"{0}\"", tokenValue); } } // if it was a trivial map without any areas, create a single area if(_portalAreaCount == 0) { ClearWorld(); } // find the points where we can early-our of reference pushing into the BSP tree CommonChildrenArea(_areaNodes[0]); AddWorldModelEntities(); ClearPortalStates(); // done! return true; }