コード例 #1
0
ファイル: QuakeMap.cs プロジェクト: MarkWilds/Arbatel
        public override Map Parse()
        {
            string oldCwd = Directory.GetCurrentDirectory();

            Directory.SetCurrentDirectory(Path.GetDirectoryName(AbsolutePath ?? oldCwd));

            OnProgressUpdated(this, new ProgressEventArgs(0, "Cleaning up raw input..."));

            // FIXME: Only strip leading tabs! Or just tabs not within a key or value?
            string stripped = Raw
                              .Replace("\r", String.Empty)
                              .Replace("\n", String.Empty)
                              .Replace("\t", String.Empty);

            // Modern Quake sourceports allow for transparency in textures,
            // indicated by an open curly brace in the texture name. Any open
            // curly brace that's actually a delimiter will be followed by an
            // open parenthesis or one or more whitespace characters. Texture
            // names will instead have ordinary text characters after the brace.
            List <string> split = stripped.SplitAndKeepDelimiters(
                $"{OpenDelimiter} ",
                $"{OpenDelimiter}(",
                $"{OpenDelimiter}\"",
                CloseDelimiter).ToList();

            split.RemoveAll(s => s.Trim().Length == 0 || s.Trim() == "\"");

            // The regex patterns above include capture groups to retain some
            // delimiters in the output, but they end up in the same item in the
            // list resulting from Split. This ugly loop fixes that.
            int item = 0;

            while (item < split.Count)
            {
                if (split[item] == "{(")
                {
                    split[item]     = "{";
                    split[item + 1] = $"({split[item + 1]}";
                    item++;
                }
                else if (split[item] == "{\"")
                {
                    split[item]     = "{";
                    split[item + 1] = $"\"{split[item + 1]}";
                    item++;
                }
                else
                {
                    item++;
                }
            }

            OnProgressUpdated(this, new ProgressEventArgs(25, "Creating map objects..."));

            int i = 0;

            while (i < split.Count)
            {
                int firstBraceIndex = split.IndexOf("{", i);

                var block = new QuakeBlock(split, firstBraceIndex, Definitions);
                MapObjects.Add(new QuakeMapObject(block, Definitions, Textures));

                i = firstBraceIndex + block.RawLength;
            }

            // First build the final worldspawn.
            int       worldspawnIndex = MapObjects.FindIndex(o => o.Definition.ClassName == "worldspawn");
            MapObject worldspawn      = MapObjects[worldspawnIndex];

            foreach (MapObject mo in AllObjects)
            {
                Aabb += mo.Aabb;
            }

            FixUp();

            Directory.SetCurrentDirectory(oldCwd);

            return(this);
        }
コード例 #2
0
ファイル: QuakeBlock.cs プロジェクト: MarkWilds/Arbatel
        private void Parse(List <string> rawBlock)
        {
            int i = 0;

            while (i < rawBlock.Count)
            {
                string item = rawBlock[i];

                if (item.Contains(KeyValDelimiter))
                {
                    List <KeyValuePair <string, string> > rawKeyVals = ExtractKeyVals(item);

                    string classname = rawKeyVals.Find(s => s.Key == "classname").Value;

                    foreach (KeyValuePair <string, string> rawKeyVal in rawKeyVals)
                    {
                        Option newOption;
                        if (Definitions.ContainsKey(classname) && Definitions[classname].KeyValsTemplate.ContainsKey(rawKeyVal.Key))
                        {
                            newOption = new Option(Definitions[classname].KeyValsTemplate[rawKeyVal.Key]);
                        }
                        else
                        {
                            newOption = new Option();
                        }
                        newOption.Value = rawKeyVal.Value;

                        if (!KeyVals.ContainsKey(rawKeyVal.Key))
                        {
                            KeyVals.Add(rawKeyVal.Key, newOption);
                        }
                        else
                        {
                            KeyVals[rawKeyVal.Key] = newOption;
                        }
                    }

                    ++i;
                }
                // An open delimiter that's the first item in the raw block is just the
                // start of the top level block; any others indicate children.
                else if (item == OpenDelimiter && i != 0)
                {
                    int childOpenBraceIndex = i + 1;

                    var childBlock = new QuakeBlock(rawBlock, childOpenBraceIndex, Definitions);
                    Children.Add(childBlock);

                    i = childBlock.RawStartIndex + childBlock.RawLength;
                }
                else if (item.StartsWith("(", StringComparison.OrdinalIgnoreCase))
                {
                    string solid = item;
                    int    j     = i + 1;
                    while (rawBlock[j] != CloseDelimiter)
                    {
                        solid += rawBlock[j];
                        j++;
                    }

                    Solids.Add(new Solid(ExtractSides(solid)));

                    i += j;
                }
                else
                {
                    i++;
                }
            }
        }