/// <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;
}