Пример #1
0
 public LuaVector2D GetCenterPoint()
 {
     if (linedef.IsDisposed)
     {
         throw new ScriptRuntimeException("Linedef has been disposed, can't GetCenterPoint.");
     }
     return(new LuaVector2D(linedef.GetCenterPoint()));
 }
		//mxd
		public override void OnMouseDown(MouseEventArgs e)
		{
			base.OnMouseDown(e);
			closestline = MapSet.NearestLinedef(selectedlines, mousedownmappos);

			// Special cases...
			int distance;
			if(panel.FixedCurve)
			{
				if(panel.Angle > 0)
				{
					// Calculate diameter for current angle...
					double ma = Angle2D.DegToRad(panel.Angle);
					double d = (closestline.Length / Math.Tan(ma / 2f)) / 2;
					double D = d / Math.Cos(ma / 2f);
					distance = (int)Math.Round(D - d) * Math.Sign(panel.Distance);
				}
				else
				{
					distance = 0; // Special cases...
				}
			}
			else
			{
				distance = panel.Distance;
			}

			// Store offset between intial mouse position and curve top
			Vector2D perpendicular = closestline.Line.GetPerpendicular().GetNormal();
			if(distance != 0) perpendicular *= distance; // Special cases...
			Vector2D curvetop = closestline.GetCenterPoint() - perpendicular;
			mousedownoffset = mousedownmappos - curvetop;
		}
Пример #3
0
        /// <summary>
        /// Sets the association to a map element. Only works with an instance of Thing, Sector, or Linedef.
        /// Also gets the forward and reverse associations
        /// </summary>
        /// <param name="element">An instance of Thing, Sector, or Linedef</param>
        public void Set(SelectableElement element)
        {
            this.element = element;
            things       = new List <Thing>();
            sectors      = new List <Sector>();
            linedefs     = new List <Linedef>();
            eventlines   = new Dictionary <string, List <Line3D> >();

            if (element is Sector)
            {
                Sector s = element as Sector;
                center = (s.Labels.Count > 0 ? s.Labels[0].position : new Vector2D(s.BBox.X + s.BBox.Width / 2, s.BBox.Y + s.BBox.Height / 2));

                type = UniversalType.SectorTag;
                tags = new HashSet <int>(s.Tags);
            }
            else if (element is Linedef)
            {
                Linedef ld = element as Linedef;
                center = ld.GetCenterPoint();

                type = UniversalType.LinedefTag;
                tags = new HashSet <int>(ld.Tags);
            }
            else if (element is Thing)
            {
                Thing t = element as Thing;
                center = t.Position;

                ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);

                if (ti != null)
                {
                    directlinktype = ti.ThingLink;
                }
                else
                {
                    directlinktype = 0;
                }

                type = UniversalType.ThingTag;
                tags = new HashSet <int>(new int[] { t.Tag });
            }

            // Remove the tag 0, because nothing sensible will come from it
            tags.Remove(0);

            // Get forward and reverse associations
            GetAssociations();

            // Cache width of label text and generate the labels
            textwidths = new Dictionary <string, Vector2D>(eventlines.Count);
            textlabels = new Dictionary <string, List <TextLabel> >(eventlines.Count);

            foreach (KeyValuePair <string, List <Line3D> > kvp in eventlines)
            {
                SizeF size = General.Interface.MeasureString(kvp.Key, font);
                textwidths[kvp.Key] = new Vector2D(size.Width, size.Height);

                // Create one label for each line. We might not need them all, but better
                // to have them all at the beginning than to generate them later
                textlabels[kvp.Key] = new List <TextLabel>(kvp.Value.Count);

                for (int i = 0; i < kvp.Value.Count; i++)
                {
                    // We don't need to set the position here, since it'll be done on the fly later
                    TextLabel l = new TextLabel();
                    l.AlignX          = TextAlignmentX.Center;
                    l.AlignY          = TextAlignmentY.Middle;
                    l.TransformCoords = true;
                    l.Text            = kvp.Key;

                    textlabels[kvp.Key].Add(l);
                }

                textwidths[kvp.Key] = new Vector2D(textlabels[kvp.Key][0].TextSize.Width, textlabels[kvp.Key][0].TextSize.Height);
            }

            SetEventLineColors();
        }
Пример #4
0
        //mxd
        public override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            // Anything to do?
            if ((!selectpressed && !editpressed) || closestline == null)
            {
                hintlabel.Text = string.Empty;
                return;
            }

            // Do something...
            Vector2D perpendicular = closestline.Line.GetPerpendicular().GetNormal();

            if (panel.Distance != 0)
            {
                perpendicular *= panel.Distance;                                 // Special cases...
            }
            Vector2D center         = closestline.GetCenterPoint();
            Line2D   radius         = new Line2D(center, center - perpendicular);
            float    u              = radius.GetNearestOnLine(mousemappos - mousedownoffset);
            int      dist           = (panel.Distance == 0 ? 1 : panel.Distance); // Special cases...
            int      offset         = (int)Math.Round(dist * u - dist);
            bool     updaterequired = false;

            // Clamp values?
            bool clampvalue = !General.Interface.ShiftState;

            // Change verts amount
            if (selectpressed && editpressed)
            {
                if (prevoffset != 0)
                {
                    // Set new verts count without triggering the update...
                    panel.SetValues(panel.Vertices + Math.Sign(prevoffset - offset), panel.Distance, panel.Angle, panel.FixedCurve);

                    // Update hint text
                    hintlabel.Text = "Vertices: " + panel.Vertices;
                    updaterequired = true;
                }
            }
            // Change distance
            else if (selectpressed && !panel.FixedCurve)
            {
                if (float.IsNaN(u))
                {
                    // Set new distance without triggering the update...
                    panel.SetValues(panel.Vertices, 0, panel.Angle, panel.FixedCurve);                     // Special cases...
                }
                else
                {
                    int newoffset;
                    if (clampvalue)
                    {
                        newoffset = (panel.Distance + offset) / panel.DistanceIncrement * panel.DistanceIncrement;                         // Clamp to 8 mu increments
                    }
                    else
                    {
                        newoffset = panel.Distance + offset;
                    }

                    // Set new distance without triggering the update...
                    panel.SetValues(panel.Vertices, newoffset, panel.Angle, panel.FixedCurve);
                }

                // Update hint text
                hintlabel.Text = "Distance: " + panel.Distance;
                updaterequired = true;
            }
            // Change angle
            else if (editpressed && prevoffset != 0)
            {
                int newangle = 0;
                if (panel.FixedCurve)
                {
                    // Flip required?
                    if (panel.Angle == 0 && (Math.Sign(offset - prevoffset) != Math.Sign(panel.Distance)))
                    {
                        // Set new distance without triggering the update...
                        panel.SetValues(panel.Vertices, -panel.Distance, panel.Angle, panel.FixedCurve);

                        // Recalculate affected values...
                        perpendicular *= -1;
                        radius.v2      = center - perpendicular;
                        u              = radius.GetNearestOnLine(mousemappos - mousedownoffset);
                    }

                    //TODO: there surely is a way to get new angle without iteration...
                    float targetoffset = radius.GetLength() * u;
                    float prevdiff     = float.MaxValue;
                    int   increment    = (clampvalue ? panel.AngleIncrement : 1);
                    for (int i = 1; i < panel.MaximumAngle; i += increment)
                    {
                        // Calculate diameter for current angle...
                        float ma = Angle2D.DegToRad(i);
                        float d  = (closestline.Length / (float)Math.Tan(ma / 2f)) / 2;
                        float D  = d / (float)Math.Cos(ma / 2f);
                        float h  = D - d;

                        float curdiff = Math.Abs(h - targetoffset);

                        // This one matches better...
                        if (curdiff < prevdiff)
                        {
                            newangle = i;
                        }
                        prevdiff = curdiff;
                    }

                    // Clamp to 5 deg increments
                    if (clampvalue)
                    {
                        newangle = (newangle / panel.AngleIncrement) * panel.AngleIncrement;
                    }
                }
                else
                {
                    int diff = (int)Math.Round((offset - prevoffset) * renderer.Scale);
                    if (panel.Angle + diff > 0)
                    {
                        if (clampvalue)
                        {
                            newangle = (panel.Angle / panel.AngleIncrement + Math.Sign(diff)) * panel.AngleIncrement;                                    // Clamp to 5 deg increments
                        }
                        else
                        {
                            newangle = panel.Angle + diff;
                        }
                    }
                }

                // Set new angle without triggering the update...
                panel.SetValues(panel.Vertices, panel.Distance, newangle, panel.FixedCurve);

                // Update hint text
                hintlabel.Text = "Angle: " + panel.Angle;
                updaterequired = true;
            }

            // Update UI
            if (updaterequired)
            {
                // Update label position
                float labeldistance;

                if (panel.Angle == 0)
                {
                    labeldistance = 0;                     // Special cases!
                }
                else if (panel.FixedCurve)
                {
                    float ma = Angle2D.DegToRad(panel.Angle);
                    float d  = (closestline.Length / (float)Math.Tan(ma / 2f)) / 2;
                    float D  = d / (float)Math.Cos(ma / 2f);
                    labeldistance = D - d;
                }
                else
                {
                    labeldistance = Math.Abs(panel.Distance);
                }

                labeldistance += 16 / renderer.Scale;
                Vector2D labelpos = radius.GetCoordinatesAt(labeldistance / radius.GetLength());
                hintlabel.Move(labelpos, labelpos);

                // Trigger update
                OnValuesChanged(null, EventArgs.Empty);
            }

            // Store current offset
            prevoffset = offset;
        }
Пример #5
0
        // This generates the vertices to split the line with, from start to end
        private List <Vector2D> GenerateCurve(Linedef line)
        {
            // Fetch settings from the panel
            bool  fixedcurve = panel.FixedCurve;
            int   vertices   = Math.Min(panel.Vertices, (int)Math.Ceiling(line.Length / 4));
            int   distance   = panel.Distance;
            int   angle      = (!fixedcurve && distance == 0 ? Math.Max(5, panel.Angle) : panel.Angle);
            float theta      = Angle2D.DegToRad(angle);

            if (distance < 0)
            {
                theta = -theta;                          //mxd
            }
            // Make list
            List <Vector2D> points = new List <Vector2D>(vertices);

            float    segDelta   = 1.0f / (vertices + 1);        //mxd
            Vector2D linecenter = line.GetCenterPoint();        //mxd

            //mxd. Special cases...
            if (angle == 0)
            {
                for (int v = 1; v <= vertices; v++)
                {
                    float x = (line.Length * segDelta) * (vertices - v + 1) - line.Length * 0.5f;                     // Line segment coord

                    // Rotate and transform to fit original line
                    Vector2D vertex = new Vector2D(x, 0).GetRotated(line.Angle + Angle2D.PIHALF) + linecenter;
                    points.Add(vertex);
                }
            }
            else
            {
                //Added by Anders Åstrand 2008-05-18
                //The formulas used are taken from http://mathworld.wolfram.com/CircularSegment.html
                //c and theta are known (length of line and angle parameter). d, R and h are
                //calculated from those two
                //If the curve is not supposed to be a circular segment it's simply deformed to fit
                //the value set for distance.

                //The vertices are generated to be evenly distributed (by angle) along the curve
                //and lastly they are rotated and moved to fit with the original line

                //calculate some identities of a circle segment (refer to the graph in the url above)
                float c = line.Length;

                float d = (c / (float)Math.Tan(theta / 2)) / 2;
                float R = d / (float)Math.Cos(theta / 2);
                float h = R - d;

                float yDeform = (fixedcurve ? 1 : distance / h);
                float xDelta  = Math.Min(1, yDeform);                //mxd

                for (int v = 1; v <= vertices; v++)
                {
                    //calculate the angle for this vertex
                    //the curve starts at PI/2 - theta/2 and is segmented into vertices+1 segments
                    //this assumes the line is horisontal and on y = 0, the point is rotated and moved later

                    float a = (Angle2D.PI - theta) / 2 + v * (theta / (vertices + 1));

                    //calculate the coordinates of the point, and distort the y coordinate
                    //using the deform factor calculated above
                    float xr = (float)Math.Cos(a) * R;                                             //mxd. Circle segment coord
                    float xl = (line.Length * segDelta) * (vertices - v + 1) - line.Length * 0.5f; // mxd. Line segment coord
                    float x  = InterpolationTools.Linear(xl, xr, xDelta);                          //mxd
                    float y  = ((float)Math.Sin(a) * R - d) * yDeform;

                    //rotate and transform to fit original line
                    Vector2D vertex = new Vector2D(x, y).GetRotated(line.Angle + Angle2D.PIHALF) + linecenter;
                    points.Add(vertex);
                }
            }

            // Done
            return(points);
        }
Пример #6
0
        // This generates the vertices to split the line with, from start to end
        private List <Vector2D> GenerateCurve(Linedef line)
        {
            // Fetch settings from window
            int   vertices   = BuilderPlug.Me.CurveLinedefsForm.Vertices;
            float distance   = BuilderPlug.Me.CurveLinedefsForm.Distance;
            float angle      = BuilderPlug.Me.CurveLinedefsForm.Angle;
            bool  fixedcurve = BuilderPlug.Me.CurveLinedefsForm.FixedCurve;
            bool  backwards  = BuilderPlug.Me.CurveLinedefsForm.Backwards;

            // Make list
            List <Vector2D> points = new List <Vector2D>(vertices);

            //Added by Anders Åstrand 2008-05-18
            //The formulas used are taken from http://mathworld.wolfram.com/CircularSegment.html
            //c and theta are known (length of line and angle parameter). d, R and h are
            //calculated from those two
            //If the curve is not supposed to be a circular segment it's simply deformed to fit
            //the value set for distance.

            //The vertices are generated to be evenly distributed (by angle) along the curve
            //and lastly they are rotated and moved to fit with the original line

            //calculate some identities of a circle segment (refer to the graph in the url above)
            double c     = line.Length;
            double theta = angle;

            double d = (c / Math.Tan(theta / 2)) / 2;
            double R = d / Math.Cos(theta / 2);
            double h = R - d;

            double yDeform = fixedcurve ? 1 : distance / h;

            if (backwards)
            {
                yDeform = -yDeform;
            }

            double   a, x, y;
            Vector2D vertex;

            for (int v = 1; v <= vertices; v++)
            {
                //calculate the angle for this vertex
                //the curve starts at PI/2 - theta/2 and is segmented into vertices+1 segments
                //this assumes the line is horisontal and on y = 0, the point is rotated and moved later

                a = (Math.PI - theta) / 2 + v * (theta / (vertices + 1));

                //calculate the coordinates of the point, and distort the y coordinate
                //using the deform factor calculated above
                x = Math.Cos(a) * R;
                y = (Math.Sin(a) * R - d) * yDeform;

                //rotate and transform to fit original line
                vertex = new Vector2D((float)x, (float)y).GetRotated(line.Angle + Angle2D.PIHALF);
                vertex = vertex.GetTransformed(line.GetCenterPoint().x, line.GetCenterPoint().y, 1, 1);

                points.Add(vertex);
            }


            // Done
            return(points);
        }