UltimateZoneBuilder/Source/Core/Controls/AngleControlEx.cs
MaxED 59c4a75b11 Added "Split Joined Sectors" Edit menu item and toolbar button. When enabled, joined sectors adjacent to drawn lines will be split.
Added "doomthingrotationangles" Game Configuration property. When enabled, editor actions related to changing thing angle will snap the resulting angle to 45 degree increments. This property is set to true for vanilla game configurations.
Fixed a crash when changing game configuration from one without Thing actions support to one with them while in Things mode.
Fixed, cosmetic, DB2 bug: current editing mode button was deselected after reloading resources.
Updated documentation ("Game Configuration - Basic Settings" page).
2016-06-15 22:02:51 +00:00

212 lines
5.6 KiB
C#

#region Namespaces
//Downloaded from
//Visual C# Kicks - http://vckicks.110mb.com
//The Code Project - http://www.codeproject.com
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Geometry;
#endregion
namespace CodeImp.DoomBuilder.Controls
{
public partial class AngleControlEx : UserControl
{
#region Variables
private int angle;
private int angleoffset;
private Rectangle drawRegion;
private const int drawOffset = 2;
private const int markScaler = 5;
private Point origin;
private bool doomangleclamping;
//UI colors
private readonly Color fillColor = SystemColors.Window;
private readonly Color fillInactiveColor = SystemColors.Control;
private readonly Color outlineColor = SystemColors.WindowFrame;
private readonly Color outlineInactiveColor = SystemColors.ControlDarkDark;
private readonly Color needleColor = SystemColors.ControlText;
private readonly Color needleInactiveColor = SystemColors.ControlDarkDark;
private readonly Color marksColor = SystemColors.ActiveBorder;
private readonly Color marksInactiveColor = SystemColors.ControlDark;
#endregion
#region Properties
public event EventHandler AngleChanged;
public int Angle { get { return (angle == NO_ANGLE ? NO_ANGLE : angle - angleoffset); } set { angle = (value == NO_ANGLE ? NO_ANGLE : value + angleoffset); this.Refresh(); } }
public int AngleOffset { get { return angleoffset; } set { angleoffset = value; this.Refresh(); } }
public bool DoomAngleClamping { get { return doomangleclamping; } set { doomangleclamping = value; } }
public const int NO_ANGLE = int.MinValue;
#endregion
public AngleControlEx()
{
InitializeComponent();
this.DoubleBuffered = true;
}
#region Methods
private void SetDrawRegion()
{
drawRegion = new Rectangle(0, 0, this.Width, this.Height);
drawRegion.X += 2;
drawRegion.Y += 2;
drawRegion.Width -= 4;
drawRegion.Height -= 4;
origin = new Point(drawRegion.Width / 2 + drawOffset, drawRegion.Height / 2 + drawOffset);
this.Refresh();
}
private static PointF DegreesToXY(float degrees, float radius, Point origin)
{
PointF xy = new PointF();
float radians = degrees * Angle2D.PI / 180.0f;
xy.X = (float)Math.Cos(radians) * radius + origin.X;
xy.Y = (float)Math.Sin(-radians) * radius + origin.Y;
return xy;
}
private static int XYToDegrees(Point xy, Point origin)
{
float xDiff = xy.X - origin.X;
float yDiff = xy.Y - origin.Y;
return ((int)Math.Round(Math.Atan2(-yDiff, xDiff) * 180.0 / Angle2D.PI) + 360) % 360;
}
#endregion
#region Events
private void AngleSelector_Load(object sender, EventArgs e)
{
SetDrawRegion();
}
private void AngleSelector_SizeChanged(object sender, EventArgs e)
{
this.Height = this.Width; // Keep it there and keep it square!
SetDrawRegion();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen outline;
Pen needle;
Pen marks;
SolidBrush fill;
Brush center;
if(this.Enabled)
{
outline = new Pen(outlineColor, 2.0f);
fill = new SolidBrush(fillColor);
needle = new Pen(needleColor);
center = new SolidBrush(needleColor);
marks = new Pen(marksColor);
}
else
{
outline = new Pen(outlineInactiveColor, 2.0f);
fill = new SolidBrush(fillInactiveColor);
needle = new Pen(needleInactiveColor);
center = new SolidBrush(needleInactiveColor);
marks = new Pen(marksInactiveColor);
}
Rectangle originSquare = new Rectangle(origin.X - 1, origin.Y - 1, 3, 3);
//Draw circle
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawEllipse(outline, drawRegion);
g.FillEllipse(fill, drawRegion);
// Draw angle marks
int offset = this.Height / markScaler;
for(int i = 0; i < 360; i += 45)
{
PointF p1 = DegreesToXY(i, origin.X - 6, origin);
PointF p2 = DegreesToXY(i, origin.X - offset, origin);
g.DrawLine(marks, p1, p2);
}
// Draw needle
if(angle != NO_ANGLE)
{
PointF anglePoint = DegreesToXY(angle, origin.X - 4, origin);
g.DrawLine(needle, origin, anglePoint);
}
g.SmoothingMode = SmoothingMode.HighSpeed; //Make the square edges sharp
g.FillRectangle(center, originSquare);
//mxd. Dispose brushes
fill.Dispose();
center.Dispose();
outline.Dispose();
marks.Dispose();
needle.Dispose();
base.OnPaint(e);
}
private void AngleSelector_MouseDown(object sender, MouseEventArgs e)
{
int thisAngle = XYToDegrees(new Point(e.X, e.Y), origin);
if(e.Button == MouseButtons.Left)
{
thisAngle = (int)Math.Round(thisAngle / 45f) * 45;
if(thisAngle == 360) thisAngle = 0;
}
if(thisAngle != angle)
{
angle = thisAngle;
if(!this.DesignMode && AngleChanged != null) AngleChanged(this, EventArgs.Empty); //Raise event
this.Refresh();
}
}
private void AngleSelector_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left || e.Button == MouseButtons.Right)
{
int thisAngle = XYToDegrees(new Point(e.X, e.Y), origin);
if(e.Button == MouseButtons.Left || doomangleclamping)
{
thisAngle = (int)Math.Round(thisAngle / 45f) * 45;
if(thisAngle == 360) thisAngle = 0;
}
if(thisAngle != angle)
{
angle = thisAngle;
if(!this.DesignMode && AngleChanged != null) AngleChanged(this, EventArgs.Empty); //Raise event
this.Refresh();
}
}
}
#endregion
}
}