Exemplo n.º 1
0
        public IEnumerable <IMapObject> Create(UniqueNumberGenerator generator, Box box, string texture, int roundDecimals)
        {
            var useCentroid = _useCentroid.GetValue();

            // The lower Z plane will be the triangle, with the lower Y value getting the two corners
            var c1       = new Vector3(box.Start.X, box.Start.Y, box.Start.Z).Round(roundDecimals);
            var c2       = new Vector3(box.End.X, box.Start.Y, box.Start.Z).Round(roundDecimals);
            var c3       = new Vector3(box.Center.X, box.End.Y, box.Start.Z).Round(roundDecimals);
            var centroid = new Vector3((c1.X + c2.X + c3.X) / 3, (c1.Y + c2.Y + c3.Y) / 3, box.End.Z);
            var c4       = (useCentroid ? centroid : new Vector3(box.Center.X, box.Center.Y, box.End.Z)).Round(roundDecimals);

            var faces = new[] {
                new[] { c1, c2, c3 },
                new[] { c4, c1, c3 },
                new[] { c4, c3, c2 },
                new[] { c4, c2, c1 }
            };

            var solid = new Solid(generator.Next("MapObject"));

            solid.Data.Add(new ObjectColor(Colour.GetRandomBrushColour()));

            foreach (var arr in faces)
            {
                var face = new Face(generator.Next("Face"))
                {
                    Plane   = new Plane(arr[0], arr[1], arr[2]),
                    Texture = { Name = texture }
                };
                face.Vertices.AddRange(arr);
                solid.Data.Add(face);
            }
            solid.DescendantsChanged();
            yield return(solid);
        }
Exemplo n.º 2
0
        private void SpawnFallingObjects()
        {
            int numberOfItems = _random.Next(1, 100);

            _random.Clear();

            int    index  = _random.Next(_columns.Length);
            Column column = _columns[index];

            if (numberOfItems > 30)
            {
                Column column1;

                int index1    = _random.Next(_columns.Length);
                int index1min = MathHelper.Clamp(index1 - 1, 0, _columns.Length - 1).ToInt();
                int index1max = MathHelper.Clamp(index1 + 1, 0, _columns.Length - 1).ToInt();
                while (index == index1min || index == index1max)
                {
                    index1    = _random.Next(_columns.Length);
                    index1min = MathHelper.Clamp(index1 - 1, 0, _columns.Length - 1).ToInt();
                    index1max = MathHelper.Clamp(index1 + 1, 0, _columns.Length - 1).ToInt();
                }

                column1 = _columns[index1];
                column1.Pop();
            }

            _lastSpwaned = column;
            column.Pop();
            _random.Clear();
        }
Exemplo n.º 3
0
        public IEnumerable <IMapObject> Create(UniqueNumberGenerator generator, Box box, string texture, int roundDecimals)
        {
            var solid = new Solid(generator.Next("MapObject"));

            solid.Data.Add(new ObjectColor(Colour.GetRandomBrushColour()));

            // The lower Z plane will be base
            var c1    = new Vector3(box.Start.X, box.Start.Y, box.Start.Z).Round(roundDecimals);
            var c2    = new Vector3(box.End.X, box.Start.Y, box.Start.Z).Round(roundDecimals);
            var c3    = new Vector3(box.End.X, box.End.Y, box.Start.Z).Round(roundDecimals);
            var c4    = new Vector3(box.Start.X, box.End.Y, box.Start.Z).Round(roundDecimals);
            var c5    = new Vector3(box.Center.X, box.Center.Y, box.End.Z).Round(roundDecimals);
            var faces = new[]
            {
                new[] { c1, c2, c3, c4 },
                new[] { c2, c1, c5 },
                new[] { c3, c2, c5 },
                new[] { c4, c3, c5 },
                new[] { c1, c4, c5 }
            };

            foreach (var arr in faces)
            {
                var face = new Face(generator.Next("Face"))
                {
                    Plane   = new Plane(arr[0], arr[1], arr[2]),
                    Texture = { Name = texture }
                };
                face.Vertices.AddRange(arr);
                solid.Data.Add(face);
            }
            solid.DescendantsChanged();
            yield return(solid);
        }
Exemplo n.º 4
0
        public IEnumerable <IMapObject> Create(UniqueNumberGenerator generator, Box box, string texture, int roundDecimals)
        {
            var numSides = (int)_numSides.GetValue();

            if (numSides < 3)
            {
                yield break;
            }

            // This is all very similar to the cylinder brush.
            var width  = box.Width;
            var length = box.Length;
            var major  = width / 2;
            var minor  = length / 2;
            var angle  = 2 * Math.PI / numSides;

            var points = new Vector3[numSides];

            for (var i = 0; i < numSides; i++)
            {
                var a    = i * angle;
                var xval = box.Center.X + major * (float)Math.Cos(a);
                var yval = box.Center.Y + minor * (float)Math.Sin(a);
                var zval = box.Start.Z;
                points[i] = new Vector3(xval, yval, zval).Round(roundDecimals);
            }

            var faces = new List <Vector3[]>();

            var point = new Vector3(box.Center.X, box.Center.Y, box.End.Z).Round(roundDecimals);

            for (var i = 0; i < numSides; i++)
            {
                var next = (i + 1) % numSides;
                faces.Add(new[] { points[i], point, points[next] });
            }
            faces.Add(points.ToArray());

            var solid = new Solid(generator.Next("MapObject"));

            solid.Data.Add(new ObjectColor(Colour.GetRandomBrushColour()));
            foreach (var arr in faces)
            {
                var face = new Face(generator.Next("Face"))
                {
                    Plane   = new Plane(arr[0], arr[1], arr[2]),
                    Texture = { Name = texture }
                };
                face.Vertices.AddRange(arr);
                solid.Data.Add(face);
            }
            solid.DescendantsChanged();
            yield return(solid);
        }
Exemplo n.º 5
0
        private IEnumerable <IMapObject> GroupCopy(UniqueNumberGenerator gen, IMapObject allGroup, List <IMapObject> copy, PasteSpecialDialog.PasteSpecialGrouping grouping)
        {
            switch (grouping)
            {
            case PasteSpecialDialog.PasteSpecialGrouping.None:
                // No grouping - add directly to tree
                return(copy);

            case PasteSpecialDialog.PasteSpecialGrouping.Individual:
                // Use one group per copy
                var group = new Group(gen.Next("MapObject"));
                copy.ForEach(x => x.Hierarchy.Parent = group);
                return(new List <IMapObject> {
                    group
                });

            case PasteSpecialDialog.PasteSpecialGrouping.All:
                // Use one group for all copies
                copy.ForEach(x => x.Hierarchy.Parent = allGroup);
                return(new IMapObject[0]);

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Exemplo n.º 6
0
            public override IMapObject ToMapObject(UniqueNumberGenerator generator)
            {
                var grp = new Group(generator.Next("MapObject"));

                Editor.Apply(grp);
                return(grp);
            }
Exemplo n.º 7
0
        private Face ReadFace(string line, UniqueNumberGenerator generator)
        {
            const NumberStyles ns = NumberStyles.Float;

            var parts = line.Split(' ').Where(x => !String.IsNullOrWhiteSpace(x)).ToList();

            Assert(parts[0] == "(");
            Assert(parts[4] == ")");
            Assert(parts[5] == "(");
            Assert(parts[9] == ")");
            Assert(parts[10] == "(");
            Assert(parts[14] == ")");

            var face = new Face(generator.Next("Face"))
            {
                Plane = new Plane(
                    NumericsExtensions.Parse(parts[1], parts[2], parts[3], ns, CultureInfo.InvariantCulture),
                    NumericsExtensions.Parse(parts[6], parts[7], parts[8], ns, CultureInfo.InvariantCulture),
                    NumericsExtensions.Parse(parts[11], parts[12], parts[13], ns, CultureInfo.InvariantCulture)
                    ),
                Texture = { Name = parts[15] }
            };

            // Cater for older-style map formats
            // TODO Quake 3: when the MAP face has 24 parts, the last three parts are: content_flags, surface_flags, value
            if (parts.Count == 21 || parts.Count == 24)
            {
                QuakeEdAlignTextureToWorld(face);

                var xshift = float.Parse(parts[16], ns, CultureInfo.InvariantCulture);
                var yshift = float.Parse(parts[17], ns, CultureInfo.InvariantCulture);
                var rotate = float.Parse(parts[18], ns, CultureInfo.InvariantCulture);
                var xscale = float.Parse(parts[19], ns, CultureInfo.InvariantCulture);
                var yscale = float.Parse(parts[20], ns, CultureInfo.InvariantCulture);

                face.Texture.Rotation = -rotate;
                face.Texture.Rotation = rotate;
                face.Texture.XScale   = xscale;
                face.Texture.YScale   = yscale;
                face.Texture.XShift   = xshift;
                face.Texture.YShift   = yshift;
            }
            else
            {
                Assert(parts[16] == "[");
                Assert(parts[21] == "]");
                Assert(parts[22] == "[");
                Assert(parts[27] == "]");

                face.Texture.UAxis    = NumericsExtensions.Parse(parts[17], parts[18], parts[19], ns, CultureInfo.InvariantCulture);
                face.Texture.XShift   = float.Parse(parts[20], ns, CultureInfo.InvariantCulture);
                face.Texture.VAxis    = NumericsExtensions.Parse(parts[23], parts[24], parts[25], ns, CultureInfo.InvariantCulture);
                face.Texture.YShift   = float.Parse(parts[26], ns, CultureInfo.InvariantCulture);
                face.Texture.Rotation = float.Parse(parts[28], ns, CultureInfo.InvariantCulture);
                face.Texture.XScale   = float.Parse(parts[29], ns, CultureInfo.InvariantCulture);
                face.Texture.YScale   = float.Parse(parts[30], ns, CultureInfo.InvariantCulture);
            }

            return(face);
        }
Exemplo n.º 8
0
            public override IMapObject ToMapObject(UniqueNumberGenerator generator)
            {
                var sol = new Solid(generator.Next("MapObject"));

                Editor.Apply(sol);
                CreateFaces(sol, Sides, generator);
                return(sol);
            }
Exemplo n.º 9
0
        private Solid MakeSolid(UniqueNumberGenerator generator, IEnumerable <Vector3[]> faces, string texture, Color col)
        {
            var solid = new Solid(generator.Next("MapObject"));

            solid.Data.Add(new ObjectColor(col));
            foreach (var arr in faces)
            {
                var face = new Face(generator.Next("Face"))
                {
                    Plane   = new Plane(arr[0], arr[1], arr[2]),
                    Texture = { Name = texture }
                };
                face.Vertices.AddRange(arr);
                solid.Data.Add(face);
            }
            solid.DescendantsChanged();
            return(solid);
        }
Exemplo n.º 10
0
        private Solid ReadSolid(StreamReader rdr, UniqueNumberGenerator generator)
        {
            var    faces = new List <Face>();
            string line;

            while ((line = CleanLine(rdr.ReadLine())) != null)
            {
                if (String.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                if (line == "}")
                {
                    if (!faces.Any())
                    {
                        return(null);
                    }

                    var poly = new Polyhedron(faces.Select(x => x.Plane));
                    var ret  = new Solid(generator.Next("MapObject"));
                    ret.Data.Add(new ObjectColor(Colour.GetRandomBrushColour()));

                    foreach (var face in faces)
                    {
                        var pg = poly.Polygons.FirstOrDefault(x => x.Plane.Normal.EquivalentTo(face.Plane.Normal));
                        if (pg == null)
                        {
                            // TODO: Report invalid solids
                            Debug.WriteLine("Invalid solid!");
                            return(null);
                        }
                        face.Vertices.AddRange(pg.Vertices);
                    }
                    ret.Data.AddRange(faces);
                    ret.DescendantsChanged();
                    return(ret);
                }
                else if (line == "patchDef2")
                {
                    // Quake 3 has bezier faces
                    // TODO: support bezier faces...
                    while (CleanLine(rdr.ReadLine()) != "}")
                    {
                        // Skip...
                    }
                }
                else if (line == "brushDef")
                {
                    throw new Exception("Maps containing the 'brushDef' structure are not currently supported");
                }
                else
                {
                    faces.Add(ReadFace(line, generator));
                }
            }
            return(null);
        }
Exemplo n.º 11
0
 public IMapElement Copy(UniqueNumberGenerator numberGenerator)
 {
     return(new Visgroup
     {
         ID = numberGenerator.Next("Visgroup"),
         Name = Name,
         Visible = Visible,
         Colour = Colour,
     });
 }
Exemplo n.º 12
0
        public IEnumerable <IMapObject> Create(UniqueNumberGenerator idGenerator, Box box, string texture, int roundDecimals)
        {
            var solid = new Solid(idGenerator.Next("MapObject"));

            solid.Data.Add(new ObjectColor(Colour.GetRandomBrushColour()));

            foreach (var arr in box.GetBoxFaces())
            {
                var face = new Face(idGenerator.Next("Face"))
                {
                    Plane   = new Plane(arr[0], arr[1], arr[2]),
                    Texture = { Name = texture }
                };
                face.Vertices.AddRange(arr.Select(x => x.Round(roundDecimals)));
                solid.Data.Add(face);
            }
            solid.DescendantsChanged();
            yield return(solid);
        }
Exemplo n.º 13
0
        public Face ToFace(UniqueNumberGenerator idGenerator)
        {
            var f = new Face(idGenerator.Next("Face"))
            {
                Texture = Texture.Clone()
            };

            f.Vertices.AddRange(Vertices.Select(x => x.Position));

            return(f);
        }
Exemplo n.º 14
0
            public override IMapObject ToMapObject(UniqueNumberGenerator generator)
            {
                var ent = new Entity(generator.Next("MapObject"));

                ent.Data.Add(EntityData);
                if (Origin != null)
                {
                    ent.Data.Add(new Origin(Origin.Value));
                }

                Editor.Apply(ent);

                return(ent);
            }
Exemplo n.º 15
0
            private void CreateFaces(Solid solid, List <VmfSide> sides, UniqueNumberGenerator generator)
            {
                // If all the sides don't have enough vertices, calculate them
                if (!sides.All(x => x.Vertices.Count >= 3))
                {
                    // We need to create the solid from intersecting planes
                    var poly = new Polyhedron(sides.Select(x => x.Plane));
                    foreach (var side in sides)
                    {
                        side.Vertices.Clear();
                        var pg = poly.Polygons.FirstOrDefault(x => x.Plane.Normal.EquivalentTo(side.Plane.Normal));
                        if (pg == null)
                        {
                            continue;
                        }
                        side.Vertices.AddRange(pg.Vertices.Select(x => x.ToStandardVector3()));
                    }
                }

                foreach (var emptySide in sides.Where(x => !x.Vertices.Any()))
                {
                    Console.WriteLine(emptySide.ID);
                }

                // We know the vertices, now create the faces
                foreach (var side in sides)
                {
                    var face = new Face(generator.Next("Face"))
                    {
                        Plane   = side.Plane.ToStandardPlane(),
                        Texture = side.Texture
                    };
                    face.Vertices.AddRange(side.Vertices);
                    if (face.Vertices.Any())
                    {
                        solid.Data.Add(face);
                    }
                }

                solid.DescendantsChanged();
            }
Exemplo n.º 16
0
        private IMapObject GetBrush(MapDocument document, Box bounds, UniqueNumberGenerator idg)
        {
            var brush = _activeBrush;

            if (brush == null)
            {
                return(null);
            }

            // Don't round if the box is rather small
            var rounding = RoundVertices ? 0 : 2;

            if (bounds.SmallestDimension < 10)
            {
                rounding = 2;
            }

            var ti      = document.Map.Data.GetOne <ActiveTexture>()?.Name ?? "aaatrigger";
            var created = brush.Create(idg, bounds, ti, rounding).ToList();

            // Align all textures to the face and set the texture scale
            foreach (var f in created.SelectMany(x => x.Data.OfType <Face>()))
            {
                f.Texture.XScale = f.Texture.YScale = (float)document.Environment.DefaultTextureScale;
                f.Texture.AlignToNormal(f.Plane.Normal);
            }

            // If there's more than one object in the result, group them up
            if (created.Count > 1)
            {
                var g = new Group(idg.Next("MapObject"));
                created.ForEach(x => x.Hierarchy.Parent = g);
                g.DescendantsChanged();
                return(g);
            }

            return(created.FirstOrDefault());
        }
Exemplo n.º 17
0
        private Entity ReadEntity(StreamReader rdr, UniqueNumberGenerator generator, BspFileLoadResult result)
        {
            var ent = new Entity(generator.Next("Face"))
            {
                Data =
                {
                    new EntityData(),
                    new ObjectColor(Colour.GetRandomBrushColour())
                }
            };
            string line;

            while ((line = CleanLine(rdr.ReadLine())) != null)
            {
                if (String.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                if (line[0] == '"')
                {
                    ReadProperty(ent, line);
                }
                else if (line[0] == '{')
                {
                    var s = ReadSolid(rdr, generator, result);
                    if (s != null)
                    {
                        s.Hierarchy.Parent = ent;
                    }
                }
                else if (line[0] == '}')
                {
                    break;
                }
            }
            ent.DescendantsChanged();
            return(ent);
        }
Exemplo n.º 18
0
        /// <inheritdoc />
        public virtual IMapElement Copy(UniqueNumberGenerator numberGenerator)
        {
            var inst = (BaseMapObject)GetType().GetConstructor(new[] { typeof(long) }).Invoke(new object[] { numberGenerator.Next("MapObject") });

            CopyBase(inst, numberGenerator);
            return(inst);
        }
Exemplo n.º 19
0
        public IEnumerable <IMapObject> Create(UniqueNumberGenerator generator, Box box, string texture, int roundfloats)
        {
            var length  = Math.Max(1, Math.Abs((int)box.Length));
            var height  = box.Height;
            var flatten = (float)_flattenFactor.Value;
            var text    = _text.GetValue();

            var family = _fontChooser.GetFontFamily();
            var style  = Enum.GetValues(typeof(FontStyle)).OfType <FontStyle>().FirstOrDefault(fs => family.IsStyleAvailable(fs));

            if (!family.IsStyleAvailable(style))
            {
                family = FontFamily.GenericSansSerif;
            }

            var set = new List <Polygon>();

            var sizes = new List <RectangleF>();

            using (var bmp = new Bitmap(1, 1))
            {
                using (var g = Graphics.FromImage(bmp))
                {
                    using (var font = new Font(family, length, style, GraphicsUnit.Pixel))
                    {
                        for (var i = 0; i < text.Length; i += 32)
                        {
                            using (var sf = new StringFormat(StringFormat.GenericTypographic))
                            {
                                var rem   = Math.Min(text.Length, i + 32) - i;
                                var range = Enumerable.Range(0, rem).Select(x => new CharacterRange(x, 1)).ToArray();
                                sf.SetMeasurableCharacterRanges(range);
                                var reg = g.MeasureCharacterRanges(text.Substring(i, rem), font, new RectangleF(0, 0, float.MaxValue, float.MaxValue), sf);
                                sizes.AddRange(reg.Select(x => x.GetBounds(g)));
                            }
                        }
                    }
                }
            }

            var xOffset = box.Start.X;
            var yOffset = box.End.Y;

            for (var ci = 0; ci < text.Length; ci++)
            {
                var c    = text[ci];
                var size = sizes[ci];

                var gp = new GraphicsPath();
                gp.AddString(c.ToString(CultureInfo.InvariantCulture), family, (int)style, length, new PointF(0, 0), StringFormat.GenericTypographic);
                gp.Flatten(new System.Drawing.Drawing2D.Matrix(), flatten);

                var polygons = new List <Polygon>();
                var poly     = new List <PolygonPoint>();

                for (var i = 0; i < gp.PointCount; i++)
                {
                    var type  = gp.PathTypes[i];
                    var point = gp.PathPoints[i];

                    poly.Add(new PolygonPoint(point.X + xOffset, -point.Y + yOffset));

                    if ((type & 0x80) == 0x80)
                    {
                        polygons.Add(new Polygon(poly));
                        poly.Clear();
                    }
                }

                var     tri     = new List <Polygon>();
                Polygon polygon = null;
                foreach (var p in polygons)
                {
                    if (polygon == null)
                    {
                        polygon = p;
                        tri.Add(p);
                    }
                    else if (p.CalculateWindingOrder() != polygon.CalculateWindingOrder())
                    {
                        polygon.AddHole(p);
                    }
                    else
                    {
                        polygon = null;
                        tri.Add(p);
                    }
                }

                foreach (var pp in tri)
                {
                    try
                    {
                        P2T.Triangulate(pp);
                        set.Add(pp);
                    }
                    catch
                    {
                        // Ignore
                    }
                }

                xOffset += size.Width;
            }

            var zOffset = box.Start.Z;

            foreach (var polygon in set)
            {
                foreach (var t in polygon.Triangles)
                {
                    var points = t.Points.Select(x => new Vector3((float)x.X, (float)x.Y, zOffset).Round(roundfloats)).ToList();

                    var faces = new List <Vector3[]>();

                    // Add the vertical faces
                    var z = new Vector3(0, 0, height).Round(roundfloats);
                    for (var j = 0; j < points.Count; j++)
                    {
                        var next = (j + 1) % points.Count;
                        faces.Add(new[] { points[j], points[j] + z, points[next] + z, points[next] });
                    }
                    // Add the top and bottom faces
                    faces.Add(points.ToArray());
                    faces.Add(points.Select(x => x + z).Reverse().ToArray());

                    // Nothing new here, move along
                    var solid = new Solid(generator.Next("MapObject"));
                    solid.Data.Add(new ObjectColor(Colour.GetRandomBrushColour()));

                    foreach (var arr in faces)
                    {
                        var face = new Face(generator.Next("Face"))
                        {
                            Plane   = new Plane(arr[0], arr[1], arr[2]),
                            Texture = { Name = texture }
                        };
                        face.Vertices.AddRange(arr.Select(x => x.Round(roundfloats)));
                        solid.Data.Add(face);
                    }
                    solid.DescendantsChanged();
                    yield return(solid);
                }
            }
        }
Exemplo n.º 20
0
        public IEnumerable <IMapObject> Create(UniqueNumberGenerator generator, Box box, string texture, int roundDecimals)
        {
            var numSides = (int)_numSides.GetValue();

            if (numSides < 3)
            {
                yield break;
            }

            // Cylinders can be elliptical so use both major and minor rather than just the radius
            // NOTE: when a low number (< 10ish) of faces are selected this will cause the cylinder to not touch all the edges of the box.
            var width  = box.Width;
            var length = box.Length;
            var height = box.Height;
            var major  = width / 2;
            var minor  = length / 2;
            var angle  = 2 * (float)Math.PI / numSides;

            // Calculate the X and Y points for the ellipse
            var points = new Vector3[numSides];

            for (var i = 0; i < numSides; i++)
            {
                var a    = i * angle;
                var xval = box.Center.X + major * (float)Math.Cos(a);
                var yval = box.Center.Y + minor * (float)Math.Sin(a);
                var zval = box.Start.Z;
                points[i] = new Vector3(xval, yval, zval).Round(roundDecimals);
            }

            var faces = new List <Vector3[]>();

            // Add the vertical faces
            var z = new Vector3(0, 0, height).Round(roundDecimals);

            for (var i = 0; i < numSides; i++)
            {
                var next = (i + 1) % numSides;
                faces.Add(new[] { points[i], points[i] + z, points[next] + z, points[next] });
            }

            // Add the elliptical top and bottom faces
            faces.Add(points.ToArray());
            faces.Add(points.Select(x => x + z).Reverse().ToArray());

            // Nothing new here, move along
            var solid = new Solid(generator.Next("MapObject"));

            solid.Data.Add(new ObjectColor(Colour.GetRandomBrushColour()));

            foreach (var arr in faces)
            {
                var face = new Face(generator.Next("Face"))
                {
                    Plane   = new Plane(arr[0], arr[1], arr[2]),
                    Texture = { Name = texture }
                };
                face.Vertices.AddRange(arr);
                solid.Data.Add(face);
            }
            solid.DescendantsChanged();
            yield return(solid);
        }