2014-01-16 09:32:05 +00:00
|
|
|
|
#region ================== Namespaces
|
|
|
|
|
|
|
|
|
|
using System;
|
2012-06-04 23:42:13 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Windows.Forms;
|
2014-12-03 23:15:26 +00:00
|
|
|
|
using CodeImp.DoomBuilder.Config;
|
2012-06-04 23:42:13 +00:00
|
|
|
|
using CodeImp.DoomBuilder.Editing;
|
|
|
|
|
using CodeImp.DoomBuilder.Rendering;
|
|
|
|
|
using CodeImp.DoomBuilder.Geometry;
|
|
|
|
|
using CodeImp.DoomBuilder.Actions;
|
|
|
|
|
using CodeImp.DoomBuilder.Windows;
|
|
|
|
|
using CodeImp.DoomBuilder.Map;
|
|
|
|
|
|
2014-01-16 09:32:05 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
namespace CodeImp.DoomBuilder.BuilderModes
|
2012-06-04 23:42:13 +00:00
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
[EditMode(DisplayName = "Draw Rectangle Mode",
|
|
|
|
|
SwitchAction = "drawrectanglemode",
|
2014-02-28 14:32:20 +00:00
|
|
|
|
ButtonImage = "DrawRectangleMode.png", //mxd
|
2014-02-26 14:11:06 +00:00
|
|
|
|
ButtonOrder = int.MinValue + 3, //mxd
|
|
|
|
|
ButtonGroup = "000_drawing", //mxd
|
2013-09-11 09:47:53 +00:00
|
|
|
|
AllowCopyPaste = false,
|
|
|
|
|
Volatile = true,
|
|
|
|
|
Optional = false)]
|
|
|
|
|
|
|
|
|
|
public class DrawRectangleMode : DrawGeometryMode
|
|
|
|
|
{
|
2014-01-16 09:32:05 +00:00
|
|
|
|
#region ================== Variables
|
|
|
|
|
|
Fixed, Draw Lines/Rectangle/Circle/Curve modes: line length labels displayed incorrect length.
Changed, Drag Linedefs/Vertices/Sectors/Things modes: line length labels are now displayed the same way as in Draw modes.
Changed, Drag Linedefs/Vertices/Sectors/Things modes: "lock movement to cardinal directions" mode (Alt-Shift-Drag) now locks movement in 4 directions instead of 8 and doesn't snap map elements to nearest grid intersections when they are not aligned to it.
Added, Visual mode, GZDoom, DECORATE: FORCEXYBILLBOARD flag is now supported.
Added, Visual mode, GLOOME, DECORATE: FLOORSPRITE, CEILSPRITE, WALLSPRITE, ROLLSPRITE and STICKTOPLANE flags are now supported (implementation is somewhat broken ATM and probably doesn't work the same way as in GLOOME, because Windows build with most these features is nowhere to be found...).
Fixed, Visual mode: in some cases Thing brightness was calculated incorrectly.
Updated ZDoom_DECORATE.cfg.
2015-08-25 22:05:14 +00:00
|
|
|
|
protected HintLabel hintlabel;
|
2016-02-17 22:23:18 +00:00
|
|
|
|
protected int bevelwidth;
|
|
|
|
|
protected int currentbevelwidth;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
protected int subdivisions;
|
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
protected int maxsubdivisions;
|
|
|
|
|
protected int minsubdivisions;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
protected string undoname = "Rectangle draw";
|
|
|
|
|
protected string shapename = "rectangle";
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
|
|
|
|
protected Vector2D start;
|
|
|
|
|
protected Vector2D end;
|
|
|
|
|
protected int width;
|
|
|
|
|
protected int height;
|
2016-03-06 20:52:19 +00:00
|
|
|
|
protected int minpointscount;
|
|
|
|
|
protected bool alwaysrendershapehints;
|
2022-01-16 19:42:45 +00:00
|
|
|
|
protected bool radialdrawing;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
2016-11-18 17:34:49 +00:00
|
|
|
|
private bool blockupdate;
|
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
// Interface
|
2014-01-16 09:32:05 +00:00
|
|
|
|
private DrawRectangleOptionsPanel panel;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Constructor/Disposer
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
public DrawRectangleMode()
|
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
snaptogrid = true;
|
2015-07-09 22:32:12 +00:00
|
|
|
|
usefourcardinaldirections = true;
|
2016-03-14 10:25:27 +00:00
|
|
|
|
autoclosedrawing = false;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
public override void Dispose()
|
|
|
|
|
{
|
2015-09-16 12:10:43 +00:00
|
|
|
|
// Not already disposed?
|
|
|
|
|
if(!isdisposed)
|
|
|
|
|
{
|
|
|
|
|
// Clean up
|
|
|
|
|
if(hintlabel != null) hintlabel.Dispose();
|
|
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
base.Dispose();
|
|
|
|
|
}
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
2014-01-16 09:32:05 +00:00
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Settings panel
|
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
protected override void SetupInterface()
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2017-07-25 17:16:15 +00:00
|
|
|
|
minsubdivisions = 0;
|
2016-02-17 22:23:18 +00:00
|
|
|
|
maxsubdivisions = 16;
|
2016-03-06 20:52:19 +00:00
|
|
|
|
minpointscount = 4;
|
2014-01-16 09:32:05 +00:00
|
|
|
|
|
2016-03-04 13:41:55 +00:00
|
|
|
|
// Load stored settings
|
|
|
|
|
subdivisions = General.Clamp(General.Settings.ReadPluginSetting("drawrectanglemode.subdivisions", 0), minsubdivisions, maxsubdivisions);
|
|
|
|
|
bevelwidth = General.Settings.ReadPluginSetting("drawrectanglemode.bevelwidth", 0);
|
|
|
|
|
currentbevelwidth = bevelwidth;
|
|
|
|
|
|
2014-01-16 09:32:05 +00:00
|
|
|
|
//Add options docker
|
|
|
|
|
panel = new DrawRectangleOptionsPanel();
|
2016-02-17 22:23:18 +00:00
|
|
|
|
panel.MaxSubdivisions = maxsubdivisions;
|
|
|
|
|
panel.MinSubdivisions = minsubdivisions;
|
2014-02-28 14:32:20 +00:00
|
|
|
|
panel.MaxBevelWidth = (int)General.Map.FormatInterface.MaxCoordinate;
|
|
|
|
|
panel.MinBevelWidth = (int)General.Map.FormatInterface.MinCoordinate;
|
2016-03-04 13:41:55 +00:00
|
|
|
|
panel.BevelWidth = bevelwidth;
|
|
|
|
|
panel.Subdivisions = subdivisions;
|
2014-01-16 09:32:05 +00:00
|
|
|
|
panel.OnValueChanged += OptionsPanelOnValueChanged;
|
2016-02-17 22:23:18 +00:00
|
|
|
|
panel.OnContinuousDrawingChanged += OnContinuousDrawingChanged;
|
2016-09-26 12:53:50 +00:00
|
|
|
|
panel.OnShowGuidelinesChanged += OnShowGuidelinesChanged;
|
2022-01-16 19:42:45 +00:00
|
|
|
|
panel.OnRadialDrawingChanged += OnRadialDrawingChanged;
|
2023-09-11 00:05:46 +00:00
|
|
|
|
panel.OnPlaceThingsAtVerticesChanged += OnPlaceThingsAtVerticesChanged;
|
2016-03-04 13:41:55 +00:00
|
|
|
|
|
|
|
|
|
// Needs to be set after adding the OnContinuousDrawingChanged event...
|
|
|
|
|
panel.ContinuousDrawing = General.Settings.ReadPluginSetting("drawrectanglemode.continuousdrawing", false);
|
2016-09-26 12:53:50 +00:00
|
|
|
|
panel.ShowGuidelines = General.Settings.ReadPluginSetting("drawrectanglemode.showguidelines", false);
|
2022-01-16 19:42:45 +00:00
|
|
|
|
panel.RadialDrawing = General.Settings.ReadPluginSetting("drawrectanglemode.radialdrawing", false);
|
2023-09-11 00:05:46 +00:00
|
|
|
|
panel.PlaceThingsAtVertices = General.Settings.ReadPluginSetting("drawrectanglemode.placethingsatvertices", false);
|
2014-01-16 09:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
protected override void AddInterface()
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2014-02-28 14:32:20 +00:00
|
|
|
|
panel.Register();
|
2014-01-16 09:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
protected override void RemoveInterface()
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2016-03-04 13:41:55 +00:00
|
|
|
|
// Store settings
|
|
|
|
|
General.Settings.WritePluginSetting("drawrectanglemode.subdivisions", subdivisions);
|
|
|
|
|
General.Settings.WritePluginSetting("drawrectanglemode.bevelwidth", bevelwidth);
|
|
|
|
|
General.Settings.WritePluginSetting("drawrectanglemode.continuousdrawing", panel.ContinuousDrawing);
|
2016-09-26 12:53:50 +00:00
|
|
|
|
General.Settings.WritePluginSetting("drawrectanglemode.showguidelines", panel.ShowGuidelines);
|
2022-01-16 19:42:45 +00:00
|
|
|
|
General.Settings.WritePluginSetting("drawrectanglemode.radialdrawing", panel.RadialDrawing);
|
2023-09-11 00:05:46 +00:00
|
|
|
|
General.Settings.WritePluginSetting("drawrectanglemode.placethingsatvertices", panel.PlaceThingsAtVertices);
|
2016-03-04 13:41:55 +00:00
|
|
|
|
|
|
|
|
|
// Remove the buttons
|
2014-02-28 14:32:20 +00:00
|
|
|
|
panel.Unregister();
|
2014-01-16 09:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Methods
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
override protected void Update()
|
|
|
|
|
{
|
2016-11-18 17:34:49 +00:00
|
|
|
|
if(blockupdate) return;
|
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
PixelColor stitchcolor = General.Colors.Highlight;
|
|
|
|
|
PixelColor losecolor = General.Colors.Selection;
|
|
|
|
|
|
2015-07-09 22:32:12 +00:00
|
|
|
|
snaptocardinaldirection = General.Interface.ShiftState && General.Interface.AltState; //mxd
|
|
|
|
|
snaptogrid = (snaptocardinaldirection || General.Interface.ShiftState ^ General.Interface.SnapToGrid);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;
|
|
|
|
|
|
|
|
|
|
DrawnVertex curp = GetCurrentPosition();
|
2020-06-14 20:37:37 +00:00
|
|
|
|
Vector2D curvertexpos = curp.pos;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
float vsize = (renderer.VertexSize + 1.0f) / renderer.Scale;
|
|
|
|
|
|
2020-06-14 20:37:37 +00:00
|
|
|
|
curp.pos = curp.pos.GetRotated(-General.Map.Grid.GridRotate);
|
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
// Render drawing lines
|
2015-12-28 15:01:53 +00:00
|
|
|
|
if(renderer.StartOverlay(true))
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
PixelColor color = snaptonearest ? stitchcolor : losecolor;
|
2020-06-14 20:37:37 +00:00
|
|
|
|
|
|
|
|
|
if (points.Count == 1)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
|
|
|
|
UpdateReferencePoints(points[0], curp);
|
2020-06-14 20:37:37 +00:00
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
Vector2D[] shape = GetShape(start, end);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
2020-06-15 20:13:54 +00:00
|
|
|
|
Vector2D startrotated = start.GetRotated(General.Map.Grid.GridRotate);
|
|
|
|
|
Vector2D endrotated = end.GetRotated(General.Map.Grid.GridRotate);
|
|
|
|
|
|
2020-06-14 20:37:37 +00:00
|
|
|
|
// Rotate the shape to fit the grid rotation
|
|
|
|
|
for (int i = 0; i < shape.Length; i++)
|
|
|
|
|
shape[i] = shape[i].GetRotated(General.Map.Grid.GridRotate);
|
|
|
|
|
|
2016-09-26 12:53:50 +00:00
|
|
|
|
// Render guidelines
|
|
|
|
|
if(showguidelines)
|
2020-06-14 20:37:37 +00:00
|
|
|
|
RenderGuidelines(startrotated, endrotated, General.Colors.Guideline.WithAlpha(80), -General.Map.Grid.GridRotate);
|
2016-09-26 12:53:50 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
//render shape
|
2023-09-11 00:05:46 +00:00
|
|
|
|
if (!placethingsatvertices)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 1; i < shape.Length; i++)
|
|
|
|
|
renderer.RenderLine(shape[i - 1], shape[i], LINE_THICKNESS, color, true);
|
|
|
|
|
}
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
|
|
|
|
//vertices
|
2015-12-28 15:01:53 +00:00
|
|
|
|
for(int i = 0; i < shape.Length; i++)
|
2020-05-21 12:20:02 +00:00
|
|
|
|
renderer.RenderRectangleFilled(new RectangleF((float)(shape[i].x - vsize), (float)(shape[i].y - vsize), vsize * 2.0f, vsize * 2.0f), color, true);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
|
|
|
|
//and labels
|
2016-09-26 12:53:50 +00:00
|
|
|
|
if(shape.Length == 2)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2016-09-26 12:53:50 +00:00
|
|
|
|
// Render label for line
|
2020-06-14 20:37:37 +00:00
|
|
|
|
labels[0].Move(startrotated, endrotated);
|
2016-09-26 12:53:50 +00:00
|
|
|
|
renderer.RenderText(labels[0].TextLabel);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
2016-09-26 12:53:50 +00:00
|
|
|
|
else if(shape.Length > 3)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2016-09-26 12:53:50 +00:00
|
|
|
|
// Render labels for rectangle
|
2020-06-14 20:37:37 +00:00
|
|
|
|
Vector2D[] labelCoords = { startrotated, new Vector2D(end.x, start.y).GetRotated(General.Map.Grid.GridRotate), endrotated, new Vector2D(start.x, end.y).GetRotated(General.Map.Grid.GridRotate), startrotated };
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i < 5; i++)
|
2016-09-26 12:53:50 +00:00
|
|
|
|
{
|
|
|
|
|
labels[i - 1].Move(labelCoords[i], labelCoords[i - 1]);
|
|
|
|
|
renderer.RenderText(labels[i - 1].TextLabel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//got beveled corners?
|
|
|
|
|
if(alwaysrendershapehints || shape.Length > minpointscount + 1)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2016-09-26 12:53:50 +00:00
|
|
|
|
//render hint
|
|
|
|
|
if(width > 64 * vsize && height > 16 * vsize)
|
|
|
|
|
{
|
2020-06-14 20:37:37 +00:00
|
|
|
|
hintlabel.Move(startrotated, endrotated);
|
2016-09-26 12:53:50 +00:00
|
|
|
|
hintlabel.Text = GetHintText();
|
|
|
|
|
renderer.RenderText(hintlabel.TextLabel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//and shape corners
|
|
|
|
|
for(int i = 0; i < 4; i++)
|
2020-05-21 12:20:02 +00:00
|
|
|
|
renderer.RenderRectangleFilled(new RectangleF((float)(labelCoords[i].x - vsize), (float)(labelCoords[i].y - vsize), vsize * 2.0f, vsize * 2.0f), General.Colors.InfoLine, true);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-18 17:34:49 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Render vertex at points[0]
|
2020-05-21 12:20:02 +00:00
|
|
|
|
renderer.RenderRectangleFilled(new RectangleF((float)(start.x - vsize), (float)(start.y - vsize), vsize * 2.0f, vsize * 2.0f), General.Colors.InfoLine, true);
|
2016-11-18 17:34:49 +00:00
|
|
|
|
}
|
2014-12-03 23:15:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
// Render vertex at cursor
|
2020-06-14 20:37:37 +00:00
|
|
|
|
renderer.RenderRectangleFilled(new RectangleF((float)(curvertexpos.x - vsize), (float)(curvertexpos.y - vsize), vsize * 2.0f, vsize * 2.0f), color, true);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
renderer.Finish();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
renderer.Present();
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
protected virtual Vector2D[] GetShape(Vector2D pStart, Vector2D pEnd)
|
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
//no shape
|
2015-12-28 15:01:53 +00:00
|
|
|
|
if(pStart == pEnd)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
currentbevelwidth = 0;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
return new Vector2D[0];
|
|
|
|
|
}
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2013-03-18 13:52:27 +00:00
|
|
|
|
//line
|
2014-12-03 23:15:26 +00:00
|
|
|
|
if(pEnd.x == pStart.x || pEnd.y == pStart.y)
|
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
currentbevelwidth = 0;
|
2013-09-09 14:03:02 +00:00
|
|
|
|
return new[] { pStart, pEnd };
|
2013-03-18 13:52:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
//no corners
|
2016-02-17 22:23:18 +00:00
|
|
|
|
if(bevelwidth == 0)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
currentbevelwidth = 0;
|
2017-02-12 16:35:11 +00:00
|
|
|
|
return new[] { pStart, new Vector2D(pStart.x, pEnd.y), pEnd, new Vector2D(pEnd.x, pStart.y), pStart };
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2014-02-03 11:19:12 +00:00
|
|
|
|
//got corners. TODO: check point order
|
2013-09-11 09:47:53 +00:00
|
|
|
|
bool reverse = false;
|
2016-02-17 22:23:18 +00:00
|
|
|
|
currentbevelwidth = Math.Min(Math.Abs(bevelwidth), Math.Min(width, height) / 2);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
if(bevelwidth < 0)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
currentbevelwidth *= -1;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
reverse = true;
|
|
|
|
|
}
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2014-01-16 09:32:05 +00:00
|
|
|
|
List<Vector2D> shape = new List<Vector2D>();
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
//top-left corner
|
2016-02-17 22:23:18 +00:00
|
|
|
|
shape.AddRange(GetCornerPoints(pStart, currentbevelwidth, currentbevelwidth, !reverse));
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
//top-right corner
|
2016-02-17 22:23:18 +00:00
|
|
|
|
shape.AddRange(GetCornerPoints(new Vector2D(pEnd.x, pStart.y), -currentbevelwidth, currentbevelwidth, reverse));
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
//bottom-right corner
|
2016-02-17 22:23:18 +00:00
|
|
|
|
shape.AddRange(GetCornerPoints(pEnd, -currentbevelwidth, -currentbevelwidth, !reverse));
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
//bottom-left corner
|
2016-02-17 22:23:18 +00:00
|
|
|
|
shape.AddRange(GetCornerPoints(new Vector2D(pStart.x, pEnd.y), currentbevelwidth, -currentbevelwidth, reverse));
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
//closing point
|
2014-01-16 09:32:05 +00:00
|
|
|
|
shape.Add(shape[0]);
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2014-01-16 09:32:05 +00:00
|
|
|
|
return shape.ToArray();
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
private Vector2D[] GetCornerPoints(Vector2D startPoint, int bevel_width, int bevel_height, bool reverse)
|
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
Vector2D[] points;
|
2016-02-17 22:23:18 +00:00
|
|
|
|
Vector2D center = (bevelwidth > 0 ? new Vector2D(startPoint.x + bevel_width, startPoint.y + bevel_height) : startPoint);
|
2020-05-21 12:20:02 +00:00
|
|
|
|
double curAngle = Angle2D.PI;
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
int steps = subdivisions + 2;
|
|
|
|
|
points = new Vector2D[steps];
|
2020-05-21 12:20:02 +00:00
|
|
|
|
double stepAngle = Angle2D.PIHALF / (subdivisions + 1);
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2015-12-28 15:01:53 +00:00
|
|
|
|
for(int i = 0; i < steps; i++)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2020-05-21 12:20:02 +00:00
|
|
|
|
points[i] = new Vector2D(center.x + Math.Sin(curAngle) * bevel_width, center.y + Math.Cos(curAngle) * bevel_height);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
curAngle += stepAngle;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-28 15:01:53 +00:00
|
|
|
|
if(reverse) Array.Reverse(points);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
return points;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-14 10:25:27 +00:00
|
|
|
|
protected virtual string GetHintText()
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2016-03-14 10:25:27 +00:00
|
|
|
|
List<string> result = new List<string>();
|
|
|
|
|
if(bevelwidth != 0) result.Add("BVL: " + bevelwidth);
|
|
|
|
|
if(subdivisions != 0) result.Add("SUB: " + subdivisions);
|
|
|
|
|
|
|
|
|
|
return string.Join("; ", result.ToArray());
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-06 20:52:19 +00:00
|
|
|
|
// Update top-left and bottom-right points, which define drawing shape
|
2014-12-03 23:15:26 +00:00
|
|
|
|
private void UpdateReferencePoints(DrawnVertex p1, DrawnVertex p2)
|
|
|
|
|
{
|
2014-01-17 09:44:08 +00:00
|
|
|
|
if(!p1.pos.IsFinite() || !p2.pos.IsFinite()) return;
|
|
|
|
|
|
2022-01-16 19:42:45 +00:00
|
|
|
|
if (radialdrawing)
|
|
|
|
|
{
|
|
|
|
|
Vector2D delta = p2.pos - p1.pos;
|
|
|
|
|
p1.pos -= delta;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-06 20:52:19 +00:00
|
|
|
|
// Make sure start always stays at left and up from the end
|
2020-06-14 20:37:37 +00:00
|
|
|
|
if (p1.pos.x < p2.pos.x)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
start.x = p1.pos.x;
|
|
|
|
|
end.x = p2.pos.x;
|
2014-12-03 23:15:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
start.x = p2.pos.x;
|
|
|
|
|
end.x = p1.pos.x;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-28 15:01:53 +00:00
|
|
|
|
if(p1.pos.y < p2.pos.y)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
start.y = p1.pos.y;
|
|
|
|
|
end.y = p2.pos.y;
|
2014-12-03 23:15:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
start.y = p2.pos.y;
|
|
|
|
|
end.y = p1.pos.y;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-06 20:52:19 +00:00
|
|
|
|
// Update size
|
2020-06-16 08:42:28 +00:00
|
|
|
|
width = (int)Math.Round(end.x - start.x);
|
|
|
|
|
height = (int)Math.Round(end.y - start.y);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This draws a point at a specific location
|
2014-12-03 23:15:26 +00:00
|
|
|
|
override public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
|
|
|
|
|
{
|
2015-12-28 15:01:53 +00:00
|
|
|
|
if(pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
|
2013-09-11 09:47:53 +00:00
|
|
|
|
pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
DrawnVertex newpoint = new DrawnVertex();
|
2020-06-14 20:37:37 +00:00
|
|
|
|
newpoint.pos = pos.GetRotated(-General.Map.Grid.GridRotate);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
newpoint.stitch = true; //stitch
|
|
|
|
|
newpoint.stitchline = stitchline;
|
|
|
|
|
points.Add(newpoint);
|
|
|
|
|
|
2020-06-14 20:37:37 +00:00
|
|
|
|
if (points.Count == 1) //add point and labels
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
Fixed, Draw Lines/Rectangle/Circle/Curve modes: line length labels displayed incorrect length.
Changed, Drag Linedefs/Vertices/Sectors/Things modes: line length labels are now displayed the same way as in Draw modes.
Changed, Drag Linedefs/Vertices/Sectors/Things modes: "lock movement to cardinal directions" mode (Alt-Shift-Drag) now locks movement in 4 directions instead of 8 and doesn't snap map elements to nearest grid intersections when they are not aligned to it.
Added, Visual mode, GZDoom, DECORATE: FORCEXYBILLBOARD flag is now supported.
Added, Visual mode, GLOOME, DECORATE: FLOORSPRITE, CEILSPRITE, WALLSPRITE, ROLLSPRITE and STICKTOPLANE flags are now supported (implementation is somewhat broken ATM and probably doesn't work the same way as in GLOOME, because Windows build with most these features is nowhere to be found...).
Fixed, Visual mode: in some cases Thing brightness was calculated incorrectly.
Updated ZDoom_DECORATE.cfg.
2015-08-25 22:05:14 +00:00
|
|
|
|
labels.AddRange(new[] { new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true) });
|
|
|
|
|
hintlabel = new HintLabel(General.Colors.InfoLine);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
Update();
|
2014-12-03 23:15:26 +00:00
|
|
|
|
}
|
2015-12-28 15:01:53 +00:00
|
|
|
|
else if(points[0].pos == points[1].pos) //nothing is drawn
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
points = new List<DrawnVertex>();
|
|
|
|
|
FinishDraw();
|
2014-12-03 23:15:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
//create vertices for final shape.
|
2014-12-03 23:15:26 +00:00
|
|
|
|
UpdateReferencePoints(points[0], newpoint);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
points = new List<DrawnVertex>(); //clear points
|
2014-12-03 23:15:26 +00:00
|
|
|
|
Vector2D[] shape = GetShape(start, end);
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
2020-06-14 20:37:37 +00:00
|
|
|
|
// Rotate the shape to fit the grid rotation
|
|
|
|
|
for (int i = 0; i < shape.Length; i++)
|
|
|
|
|
shape[i] = shape[i].GetRotated(General.Map.Grid.GridRotate);
|
|
|
|
|
|
2016-11-18 17:34:49 +00:00
|
|
|
|
// We don't want base.DrawPointAt to call Update() here, because it will mess labels[]
|
|
|
|
|
// and trigger shape.Count number of display redraws...
|
|
|
|
|
blockupdate = true;
|
2015-12-28 15:01:53 +00:00
|
|
|
|
foreach(Vector2D t in shape) base.DrawPointAt(t, true, true);
|
2016-11-18 17:34:49 +00:00
|
|
|
|
blockupdate = false;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
|
|
|
|
|
FinishDraw();
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
override public void RemovePoint()
|
|
|
|
|
{
|
2015-12-28 15:01:53 +00:00
|
|
|
|
if(points.Count > 0) points.RemoveAt(points.Count - 1);
|
|
|
|
|
if(labels.Count > 0) labels = new List<LineLengthLabel>();
|
2013-09-11 09:47:53 +00:00
|
|
|
|
Update();
|
|
|
|
|
}
|
2012-06-06 00:38:28 +00:00
|
|
|
|
|
2016-12-16 21:23:37 +00:00
|
|
|
|
public override void RemoveFirstPoint()
|
|
|
|
|
{
|
|
|
|
|
RemovePoint();
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-16 09:32:05 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Events
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
override public void OnAccept()
|
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
Cursor.Current = Cursors.AppStarting;
|
|
|
|
|
General.Settings.FindDefaultDrawSettings();
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
// When we have a rectangle or a line
|
2016-03-06 20:52:19 +00:00
|
|
|
|
if(points.Count > minpointscount || points.Count == 2)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
// Make undo for the draw
|
2016-02-17 22:23:18 +00:00
|
|
|
|
General.Map.UndoRedo.CreateUndo(undoname);
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
// Make an analysis and show info
|
2020-11-01 17:49:15 +00:00
|
|
|
|
string[] adjectives = new[]
|
|
|
|
|
{ "beautiful", "lovely", "romantic", "stylish", "cheerful", "comical",
|
|
|
|
|
"awesome", "accurate", "adorable", "adventurous", "attractive", "cute",
|
|
|
|
|
"elegant", "glamorous", "gorgeous", "handsome", "magnificent", "unusual",
|
|
|
|
|
"outstanding", "mysterious", "amusing", "charming", "fantastic", "jolly" };
|
2013-09-11 09:47:53 +00:00
|
|
|
|
string word = adjectives[new Random().Next(adjectives.Length - 1)];
|
2020-11-01 17:49:15 +00:00
|
|
|
|
string a = ((word[0] == 'a') || (word[0] == 'e') || (word[0] == 'o') || (word[0] == 'u')) ? "an " : "a ";
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
General.Interface.DisplayStatus(StatusType.Action, "Created " + a + word + " " + shapename + ".");
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
// Make the drawing
|
2023-09-11 00:05:46 +00:00
|
|
|
|
if (placethingsatvertices)
|
2023-09-08 00:57:22 +00:00
|
|
|
|
{
|
|
|
|
|
List<Vector2D> verts = new List<Vector2D>();
|
|
|
|
|
for (int i = 0; i < points.Count; i++)
|
|
|
|
|
if (!verts.Contains(new Vector2D(points[i].pos.x, points[i].pos.y))) verts.Add(new Vector2D(points[i].pos.x, points[i].pos.y));
|
|
|
|
|
|
|
|
|
|
PlaceThingsAtPositions(verts);
|
|
|
|
|
|
|
|
|
|
// Snap to map format accuracy
|
|
|
|
|
General.Map.Map.SnapAllToAccuracy();
|
|
|
|
|
|
|
|
|
|
// Clear selection
|
|
|
|
|
General.Map.Map.ClearAllSelected();
|
|
|
|
|
|
|
|
|
|
// Update cached values
|
|
|
|
|
General.Map.Map.Update();
|
|
|
|
|
|
|
|
|
|
// Map is changed
|
|
|
|
|
General.Map.IsChanged = true;
|
|
|
|
|
}
|
|
|
|
|
else if (Tools.DrawLines(points, true, BuilderPlug.Me.AutoAlignTextureOffsetsOnCreate))
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
// Snap to map format accuracy
|
|
|
|
|
General.Map.Map.SnapAllToAccuracy();
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
// Clear selection
|
|
|
|
|
General.Map.Map.ClearAllSelected();
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
// Update cached values
|
|
|
|
|
General.Map.Map.Update();
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2016-05-18 20:31:40 +00:00
|
|
|
|
//mxd. Outer sectors may require some splittin...
|
2016-06-15 22:02:51 +00:00
|
|
|
|
if(General.Settings.SplitJoinedSectors) Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
|
2016-05-18 20:31:40 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
// Edit new sectors?
|
|
|
|
|
List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true);
|
|
|
|
|
if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0))
|
|
|
|
|
General.Interface.ShowEditSectors(newsectors);
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
// Update the used textures
|
|
|
|
|
General.Map.Data.UpdateUsedTextures();
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
//mxd
|
|
|
|
|
General.Map.Renderer2D.UpdateExtraFloorFlag();
|
2015-11-09 12:20:08 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
// Map is changed
|
|
|
|
|
General.Map.IsChanged = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Drawing failed
|
|
|
|
|
// NOTE: I have to call this twice, because the first time only cancels this volatile mode
|
|
|
|
|
General.Map.UndoRedo.WithdrawUndo();
|
|
|
|
|
General.Map.UndoRedo.WithdrawUndo();
|
|
|
|
|
}
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
// Done
|
|
|
|
|
Cursor.Current = Cursors.Default;
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2016-02-17 22:23:18 +00:00
|
|
|
|
if(continuousdrawing)
|
|
|
|
|
{
|
|
|
|
|
// Reset settings
|
|
|
|
|
points.Clear();
|
|
|
|
|
labels.Clear();
|
2016-03-14 10:25:27 +00:00
|
|
|
|
drawingautoclosed = false;
|
2016-02-17 22:23:18 +00:00
|
|
|
|
|
|
|
|
|
// Redraw display
|
|
|
|
|
General.Interface.RedrawDisplay();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Return to original mode
|
|
|
|
|
General.Editing.ChangeMode(General.Editing.PreviousStableMode.Name);
|
|
|
|
|
}
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
2012-06-04 23:42:13 +00:00
|
|
|
|
|
2016-03-18 12:52:12 +00:00
|
|
|
|
public override void OnDisengage()
|
|
|
|
|
{
|
|
|
|
|
if(hintlabel != null) hintlabel.Dispose();
|
|
|
|
|
base.OnDisengage();
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
public override void OnHelp()
|
|
|
|
|
{
|
2014-02-10 09:26:13 +00:00
|
|
|
|
General.ShowHelp("/gzdb/features/classic_modes/mode_drawrect.html");
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
private void OptionsPanelOnValueChanged(object sender, EventArgs eventArgs)
|
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
bevelwidth = panel.BevelWidth;
|
2014-01-16 09:32:05 +00:00
|
|
|
|
subdivisions = panel.Subdivisions;
|
|
|
|
|
Update();
|
|
|
|
|
}
|
2022-01-16 19:42:45 +00:00
|
|
|
|
|
|
|
|
|
protected void OnRadialDrawingChanged(object value, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
radialdrawing = (bool)value;
|
|
|
|
|
}
|
2014-01-16 09:32:05 +00:00
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Actions
|
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
[BeginAction("increasesubdivlevel")]
|
2014-12-03 23:15:26 +00:00
|
|
|
|
protected virtual void IncreaseSubdivLevel()
|
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
if(subdivisions < maxsubdivisions)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
subdivisions++;
|
2014-01-16 09:32:05 +00:00
|
|
|
|
panel.Subdivisions = subdivisions;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[BeginAction("decreasesubdivlevel")]
|
2014-12-03 23:15:26 +00:00
|
|
|
|
protected virtual void DecreaseSubdivLevel()
|
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
if(subdivisions > minsubdivisions)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2013-09-11 09:47:53 +00:00
|
|
|
|
subdivisions--;
|
2014-01-16 09:32:05 +00:00
|
|
|
|
panel.Subdivisions = subdivisions;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[BeginAction("increasebevel")]
|
2014-12-03 23:15:26 +00:00
|
|
|
|
protected virtual void IncreaseBevel()
|
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
if(points.Count < 2 || currentbevelwidth == bevelwidth || bevelwidth < 0)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2017-01-06 10:01:59 +00:00
|
|
|
|
bevelwidth = Math.Min(bevelwidth + General.Map.Grid.GridSize, panel.MaxBevelWidth);
|
2016-02-17 22:23:18 +00:00
|
|
|
|
panel.BevelWidth = bevelwidth;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[BeginAction("decreasebevel")]
|
2014-12-03 23:15:26 +00:00
|
|
|
|
protected virtual void DecreaseBevel()
|
|
|
|
|
{
|
2016-02-17 22:23:18 +00:00
|
|
|
|
if(currentbevelwidth == bevelwidth || bevelwidth > 0)
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{
|
2017-01-06 10:01:59 +00:00
|
|
|
|
bevelwidth = Math.Max(bevelwidth - General.Map.Grid.GridSize, panel.MinBevelWidth);
|
2016-02-17 22:23:18 +00:00
|
|
|
|
panel.BevelWidth = bevelwidth;
|
2013-09-11 09:47:53 +00:00
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-01-16 09:32:05 +00:00
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
2013-09-11 09:47:53 +00:00
|
|
|
|
}
|
2012-06-04 23:42:13 +00:00
|
|
|
|
}
|