2014-02-10 09:26:13 +00:00
|
|
|
|
#region ================== Namespaces
|
|
|
|
|
|
|
|
|
|
using System;
|
2013-04-08 13:28:04 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using CodeImp.DoomBuilder.Actions;
|
2014-12-03 23:15:26 +00:00
|
|
|
|
using CodeImp.DoomBuilder.Config;
|
2013-04-08 13:28:04 +00:00
|
|
|
|
using CodeImp.DoomBuilder.Editing;
|
|
|
|
|
using CodeImp.DoomBuilder.Geometry;
|
|
|
|
|
using CodeImp.DoomBuilder.Map;
|
|
|
|
|
using CodeImp.DoomBuilder.Rendering;
|
|
|
|
|
using CodeImp.DoomBuilder.Windows;
|
|
|
|
|
|
2014-02-10 09:26:13 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
2014-01-16 09:32:05 +00:00
|
|
|
|
namespace CodeImp.DoomBuilder.BuilderModes
|
2013-04-08 13:28:04 +00:00
|
|
|
|
{
|
|
|
|
|
[EditMode(DisplayName = "Draw Curve Mode",
|
|
|
|
|
SwitchAction = "drawcurvemode",
|
2014-02-26 14:11:06 +00:00
|
|
|
|
ButtonImage = "DrawCurveMode.png", //mxd
|
|
|
|
|
ButtonOrder = int.MinValue + 2, //mxd
|
|
|
|
|
ButtonGroup = "000_drawing", //mxd
|
2013-04-08 13:28:04 +00:00
|
|
|
|
AllowCopyPaste = false,
|
|
|
|
|
Volatile = true,
|
|
|
|
|
Optional = false)]
|
|
|
|
|
|
|
|
|
|
public class DrawCurveMode : DrawGeometryMode
|
|
|
|
|
{
|
2014-02-10 09:26:13 +00:00
|
|
|
|
#region ================== Variables
|
|
|
|
|
|
2014-02-28 14:32:20 +00:00
|
|
|
|
private readonly HintLabel hintLabel;
|
2013-04-08 13:28:04 +00:00
|
|
|
|
private Curve curve;
|
|
|
|
|
private static int segmentLength = 32;
|
2014-02-28 14:32:20 +00:00
|
|
|
|
private const int minSegmentLength = 16;
|
|
|
|
|
private const int maxSegmentLength = 4096; //just some arbitrary number
|
2013-04-08 13:28:04 +00:00
|
|
|
|
|
2014-02-26 14:11:06 +00:00
|
|
|
|
//interface
|
2014-02-28 14:32:20 +00:00
|
|
|
|
private readonly DrawCurveOptionsPanel panel;
|
2014-02-26 14:11:06 +00:00
|
|
|
|
|
2014-02-10 09:26:13 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Constructor/Disposer
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
public DrawCurveMode()
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
hintLabel = new HintLabel();
|
2014-02-26 14:11:06 +00:00
|
|
|
|
|
|
|
|
|
//Options docker
|
|
|
|
|
panel = new DrawCurveOptionsPanel(minSegmentLength, maxSegmentLength);
|
|
|
|
|
panel.OnValueChanged += OptionsPanelOnValueChanged;
|
2013-04-08 13:28:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
public override void Dispose()
|
|
|
|
|
{
|
|
|
|
|
if(!isdisposed && hintLabel != null) hintLabel.Dispose();
|
2013-04-08 13:28:04 +00:00
|
|
|
|
base.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-10 09:26:13 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Methods
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
protected override void Update()
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
PixelColor stitchcolor = General.Colors.Highlight;
|
|
|
|
|
PixelColor losecolor = General.Colors.Selection;
|
|
|
|
|
PixelColor color;
|
|
|
|
|
|
|
|
|
|
snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
|
|
|
|
|
snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;
|
|
|
|
|
|
|
|
|
|
DrawnVertex curp = GetCurrentPosition();
|
2014-02-10 09:26:13 +00:00
|
|
|
|
float vsize = (renderer.VertexSize + 1.0f) / renderer.Scale;
|
2013-04-08 13:28:04 +00:00
|
|
|
|
|
2014-11-12 11:22:14 +00:00
|
|
|
|
// Update active label position (mxd)
|
|
|
|
|
if(labels.Count > 0)
|
|
|
|
|
SetLabelPosition(labels[labels.Count - 1], points[points.Count - 1].pos, curp.pos);
|
2013-04-08 13:28:04 +00:00
|
|
|
|
|
|
|
|
|
// Render drawing lines
|
2014-12-03 23:15:26 +00:00
|
|
|
|
if(renderer.StartOverlay(true))
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
// Go for all points to draw lines
|
2014-12-03 23:15:26 +00:00
|
|
|
|
if(points.Count > 0)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
//update curve
|
|
|
|
|
List<Vector2D> verts = new List<Vector2D>();
|
2014-12-03 23:15:26 +00:00
|
|
|
|
for(int i = 0; i < points.Count; i++) verts.Add(points[i].pos);
|
|
|
|
|
if(curp.pos != verts[verts.Count-1]) verts.Add(curp.pos);
|
2013-04-08 13:28:04 +00:00
|
|
|
|
curve = CurveTools.CurveThroughPoints(verts, 0.5f, 0.75f, segmentLength);
|
|
|
|
|
|
|
|
|
|
// Render lines
|
2014-12-03 23:15:26 +00:00
|
|
|
|
for(int i = 1; i < curve.Shape.Count; i++)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
// Determine line color
|
|
|
|
|
color = snaptonearest ? stitchcolor : losecolor;
|
|
|
|
|
|
|
|
|
|
// Render line
|
|
|
|
|
renderer.RenderLine(curve.Shape[i - 1], curve.Shape[i], LINE_THICKNESS, color, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//render "inactive" vertices
|
2014-12-03 23:15:26 +00:00
|
|
|
|
for(int i = 1; i < curve.Shape.Count - 1; i++)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
// Determine vertex color
|
|
|
|
|
color = !snaptonearest ? stitchcolor : losecolor;
|
|
|
|
|
|
|
|
|
|
// Render vertex
|
|
|
|
|
renderer.RenderRectangleFilled(new RectangleF(curve.Shape[i].x - vsize, curve.Shape[i].y - vsize, vsize * 2.0f, vsize * 2.0f), color, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
if(points.Count > 0)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
// Render vertices
|
2014-12-03 23:15:26 +00:00
|
|
|
|
for(int i = 0; i < points.Count; i++)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
// Determine vertex color
|
|
|
|
|
color = points[i].stitch ? stitchcolor : losecolor;
|
|
|
|
|
|
|
|
|
|
// Render vertex
|
|
|
|
|
renderer.RenderRectangleFilled(new RectangleF(points[i].pos.x - vsize, points[i].pos.y - vsize, vsize * 2.0f, vsize * 2.0f), color, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Determine point color
|
|
|
|
|
color = snaptonearest ? stitchcolor : losecolor;
|
|
|
|
|
|
|
|
|
|
// Render vertex at cursor
|
|
|
|
|
renderer.RenderRectangleFilled(new RectangleF(curp.pos.x - vsize, curp.pos.y - vsize, vsize * 2.0f, vsize * 2.0f), color, true);
|
|
|
|
|
|
|
|
|
|
// Go for all labels
|
2014-12-03 23:15:26 +00:00
|
|
|
|
foreach(LineLengthLabel l in labels) renderer.RenderText(l.TextLabel);
|
2013-04-08 13:28:04 +00:00
|
|
|
|
|
|
|
|
|
//Render info label
|
|
|
|
|
hintLabel.Start = new Vector2D(mousemappos.x + (32 / renderer.Scale), mousemappos.y - (16 / renderer.Scale));
|
|
|
|
|
hintLabel.End = new Vector2D(mousemappos.x + (96 / renderer.Scale), mousemappos.y);
|
|
|
|
|
hintLabel.Text = "SEG LEN: " + segmentLength;
|
|
|
|
|
renderer.RenderText(hintLabel.TextLabel);
|
|
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
renderer.Finish();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
renderer.Present();
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-10 09:26:13 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Events
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
public override void OnEngage()
|
|
|
|
|
{
|
2014-02-26 14:11:06 +00:00
|
|
|
|
base.OnEngage();
|
|
|
|
|
|
|
|
|
|
//setup settings panel
|
|
|
|
|
panel.SegmentLength = segmentLength;
|
2014-02-28 14:32:20 +00:00
|
|
|
|
panel.Register();
|
2014-02-26 14:11:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
public override void OnAccept()
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
Cursor.Current = Cursors.AppStarting;
|
|
|
|
|
General.Settings.FindDefaultDrawSettings();
|
|
|
|
|
|
|
|
|
|
// When points have been drawn
|
2014-12-03 23:15:26 +00:00
|
|
|
|
if(points.Count > 0)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
// Make undo for the draw
|
|
|
|
|
General.Map.UndoRedo.CreateUndo("Curve draw");
|
|
|
|
|
|
|
|
|
|
// Make an analysis and show info
|
2014-12-03 23:15:26 +00:00
|
|
|
|
string[] adjectives = new[]
|
|
|
|
|
{
|
2014-02-28 14:32:20 +00:00
|
|
|
|
"beautiful", "lovely", "romantic", "stylish", "cheerful", "comical",
|
2013-04-08 13:28:04 +00:00
|
|
|
|
"awesome", "accurate", "adorable", "adventurous", "attractive", "cute",
|
|
|
|
|
"elegant", "glamorous", "gorgeous", "handsome", "magnificent", "unusual",
|
2014-02-28 14:32:20 +00:00
|
|
|
|
"outstanding", "mysterious", "amusing", "charming", "fantastic", "jolly"
|
|
|
|
|
};
|
2013-04-08 13:28:04 +00:00
|
|
|
|
string word = adjectives[points.Count % adjectives.Length];
|
|
|
|
|
word = (points.Count > adjectives.Length) ? "very " + word : word;
|
2013-04-15 10:54:55 +00:00
|
|
|
|
string a = ((word[0] == 'a') || (word[0] == 'e') || (word[0] == 'o') || (word[0] == 'u')) ? "an " : "a ";
|
2013-04-12 11:06:57 +00:00
|
|
|
|
General.Interface.DisplayStatus(StatusType.Action, "Created " + a + word + " curve.");
|
2013-04-08 13:28:04 +00:00
|
|
|
|
|
|
|
|
|
List<DrawnVertex> verts = new List<DrawnVertex>();
|
|
|
|
|
|
|
|
|
|
//if we have a curve...
|
2014-12-03 23:15:26 +00:00
|
|
|
|
if(points.Count > 2)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
//is it a closed curve?
|
2014-02-21 14:42:12 +00:00
|
|
|
|
int lastPoint;
|
2014-12-03 23:15:26 +00:00
|
|
|
|
if(points[0].pos == points[points.Count - 1].pos)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
lastPoint = curve.Segments.Count;
|
2014-12-03 23:15:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
lastPoint = curve.Segments.Count - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
for(int i = 0; i < lastPoint; i++)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
int next = (i == curve.Segments.Count - 1 ? 0 : i + 1);
|
|
|
|
|
bool stitch = points[i].stitch && points[next].stitch;
|
|
|
|
|
bool stitchline = points[i].stitchline && points[next].stitchline;
|
|
|
|
|
|
|
|
|
|
//add segment points except the last one
|
2014-12-03 23:15:26 +00:00
|
|
|
|
for(int c = 0; c < curve.Segments[i].Points.Length - 1; c++)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
DrawnVertex dv = new DrawnVertex();
|
|
|
|
|
dv.pos = curve.Segments[i].Points[c];
|
|
|
|
|
dv.stitch = stitch;
|
|
|
|
|
dv.stitchline = stitchline;
|
|
|
|
|
verts.Add(dv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//add last point
|
|
|
|
|
DrawnVertex end = new DrawnVertex();
|
|
|
|
|
end.pos = curve.Segments[lastPoint - 1].End;
|
|
|
|
|
end.stitch = verts[verts.Count - 1].stitch;
|
|
|
|
|
end.stitchline = verts[verts.Count - 1].stitchline;
|
|
|
|
|
verts.Add(end);
|
2014-12-03 23:15:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
verts = points;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make the drawing
|
2013-11-21 10:53:11 +00:00
|
|
|
|
if(!Tools.DrawLines(verts, true, BuilderPlug.Me.AutoAlignTextureOffsetsOnCreate)) //mxd
|
2013-04-08 13:28:04 +00:00
|
|
|
|
{
|
|
|
|
|
// 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();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Snap to map format accuracy
|
|
|
|
|
General.Map.Map.SnapAllToAccuracy();
|
|
|
|
|
|
|
|
|
|
// Clear selection
|
|
|
|
|
General.Map.Map.ClearAllSelected();
|
|
|
|
|
|
|
|
|
|
// Update cached values
|
|
|
|
|
General.Map.Map.Update();
|
|
|
|
|
|
|
|
|
|
// Edit new sectors?
|
|
|
|
|
List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true);
|
|
|
|
|
if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0))
|
|
|
|
|
General.Interface.ShowEditSectors(newsectors);
|
|
|
|
|
|
|
|
|
|
// Update the used textures
|
|
|
|
|
General.Map.Data.UpdateUsedTextures();
|
|
|
|
|
|
|
|
|
|
// Map is changed
|
|
|
|
|
General.Map.IsChanged = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
Cursor.Current = Cursors.Default;
|
|
|
|
|
|
|
|
|
|
// Return to original mode
|
|
|
|
|
General.Editing.ChangeMode(General.Editing.PreviousStableMode.Name);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
public override void OnDisengage()
|
|
|
|
|
{
|
2014-02-26 14:11:06 +00:00
|
|
|
|
base.OnDisengage();
|
2014-02-28 14:32:20 +00:00
|
|
|
|
panel.Unregister();
|
2014-02-26 14:11:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
private void OptionsPanelOnValueChanged(object sender, EventArgs eventArgs)
|
|
|
|
|
{
|
2014-02-26 14:11:06 +00:00
|
|
|
|
segmentLength = panel.SegmentLength;
|
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
|
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_drawcurve.html");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Actions
|
|
|
|
|
|
2013-04-08 13:28:04 +00:00
|
|
|
|
[BeginAction("increasesubdivlevel")]
|
2014-12-03 23:15:26 +00:00
|
|
|
|
protected virtual void IncreaseSubdivLevel()
|
|
|
|
|
{
|
|
|
|
|
if(segmentLength < maxSegmentLength)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
int increment = Math.Max(minSegmentLength, segmentLength / 32 * 16);
|
|
|
|
|
segmentLength += increment;
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
if(segmentLength > maxSegmentLength) segmentLength = maxSegmentLength;
|
2014-02-26 14:11:06 +00:00
|
|
|
|
panel.SegmentLength = segmentLength;
|
2013-04-08 13:28:04 +00:00
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[BeginAction("decreasesubdivlevel")]
|
2014-12-03 23:15:26 +00:00
|
|
|
|
protected virtual void DecreaseSubdivLevel()
|
|
|
|
|
{
|
|
|
|
|
if(segmentLength > minSegmentLength)
|
|
|
|
|
{
|
2013-04-08 13:28:04 +00:00
|
|
|
|
int increment = Math.Max(minSegmentLength, segmentLength / 32 * 16);
|
|
|
|
|
segmentLength -= increment;
|
|
|
|
|
|
2014-12-03 23:15:26 +00:00
|
|
|
|
if(segmentLength < minSegmentLength) segmentLength = minSegmentLength;
|
2014-02-26 14:11:06 +00:00
|
|
|
|
panel.SegmentLength = segmentLength;
|
2013-04-08 13:28:04 +00:00
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-02-10 09:26:13 +00:00
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
2013-04-08 13:28:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|