mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 14:31:50 +00:00
begun working on EditSelectionMode (unfinished)
This commit is contained in:
parent
8a94d9431f
commit
eb08197d56
24 changed files with 974 additions and 153 deletions
BIN
Resources/Icons/Warning.png
Normal file
BIN
Resources/Icons/Warning.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 725 B |
BIN
Resources/Icons/WarningOff.png
Normal file
BIN
Resources/Icons/WarningOff.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 250 B |
|
@ -107,11 +107,12 @@
|
|||
<Compile Include="Geometry\Angle2D.cs" />
|
||||
<Compile Include="Geometry\LinedefsTracePath.cs" />
|
||||
<Compile Include="Geometry\LinedefAngleSorter.cs" />
|
||||
<Compile Include="Geometry\Polygon.cs" />
|
||||
<Compile Include="Geometry\SectorTools.cs" />
|
||||
<Compile Include="Geometry\Triangulator.cs" />
|
||||
<Compile Include="Geometry\EarClipVertex.cs" />
|
||||
<Compile Include="Geometry\Line2D.cs" />
|
||||
<Compile Include="Geometry\Polygon.cs" />
|
||||
<Compile Include="Geometry\EarClipPolygon.cs" />
|
||||
<Compile Include="Geometry\SidedefAngleSorter.cs" />
|
||||
<Compile Include="Geometry\SidedefsTracePath.cs" />
|
||||
<Compile Include="Geometry\TriangleList.cs" />
|
||||
|
@ -275,6 +276,7 @@
|
|||
<Compile Include="Controls\NumericTextbox.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Windows\MessageBeepType.cs" />
|
||||
<Compile Include="Windows\OpenMapOptionsForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
@ -587,6 +589,8 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\DB2.ico" />
|
||||
<None Include="Resources\Warning.png" />
|
||||
<None Include="Resources\WarningOff.png" />
|
||||
<None Include="Resources\Test.png" />
|
||||
<None Include="Resources\SlimDX_small.png" />
|
||||
<None Include="Resources\Splash3_trans.png" />
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ClassicModes\BrightnessMode.cs" />
|
||||
<Compile Include="ClassicModes\EditSelectionMode.cs" />
|
||||
<Compile Include="ClassicModes\CurveLinedefsMode.cs" />
|
||||
<Compile Include="ClassicModes\DragLinedefsMode.cs" />
|
||||
<Compile Include="ClassicModes\DragSectorsMode.cs" />
|
||||
|
|
|
@ -395,7 +395,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
{
|
||||
// Make polygon
|
||||
LinedefTracePath tracepath = new LinedefTracePath(pathlines);
|
||||
Polygon pathpoly = tracepath.MakePolygon();
|
||||
EarClipPolygon pathpoly = tracepath.MakePolygon();
|
||||
|
||||
// Check if the front of the line is outside the polygon
|
||||
if(!pathpoly.Intersect(ld.GetSidePoint(true)))
|
||||
|
|
555
Source/BuilderModes/ClassicModes/EditSelectionMode.cs
Normal file
555
Source/BuilderModes/ClassicModes/EditSelectionMode.cs
Normal file
|
@ -0,0 +1,555 @@
|
|||
|
||||
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
||||
* This program is released under GNU General Public License
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using CodeImp.DoomBuilder.Windows;
|
||||
using CodeImp.DoomBuilder.IO;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using CodeImp.DoomBuilder.Editing;
|
||||
using CodeImp.DoomBuilder.Actions;
|
||||
using CodeImp.DoomBuilder.Types;
|
||||
using CodeImp.DoomBuilder.Config;
|
||||
using System.Drawing;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.BuilderModes
|
||||
{
|
||||
[EditMode(DisplayName = "Edit Selection",
|
||||
SwitchAction = "editselectionmode", // Action name used to switch to this mode
|
||||
ButtonDesc = "Edit Selection Mode", // Description on the button in toolbar/menu
|
||||
ButtonImage = "LinesMode.png", // Image resource name for the button
|
||||
Volatile = true,
|
||||
ButtonOrder = int.MinValue + 210)] // Position of the button (lower is more to the left)
|
||||
|
||||
public class EditSelectionMode : ClassicMode
|
||||
{
|
||||
#region ================== Enums
|
||||
|
||||
private enum ModifyMode : int
|
||||
{
|
||||
None,
|
||||
Dragging,
|
||||
Resizing
|
||||
}
|
||||
|
||||
private enum Grip : int
|
||||
{
|
||||
None,
|
||||
Main,
|
||||
SizeN,
|
||||
SizeS,
|
||||
SizeE,
|
||||
SizeW,
|
||||
RotateLT,
|
||||
RotateRT,
|
||||
RotateRB,
|
||||
RotateLB
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constants
|
||||
|
||||
private const float GRIP_SIZE = 11.0f;
|
||||
private const float BORDER_PADDING = 5.0f;
|
||||
private readonly Cursor[] RESIZE_CURSORS = { Cursors.SizeNS, Cursors.SizeNESW, Cursors.SizeWE, Cursors.SizeNWSE };
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Variables
|
||||
|
||||
// Selection
|
||||
private ICollection<Vertex> selectedvertices;
|
||||
private ICollection<Thing> selectedthings;
|
||||
private List<Vector2D> vertexpos;
|
||||
private List<Vector2D> thingpos;
|
||||
|
||||
// Modification
|
||||
private float rotation;
|
||||
private Vector2D offset;
|
||||
private Vector2D size;
|
||||
private Vector2D baseoffset;
|
||||
private Vector2D basesize;
|
||||
|
||||
// Modifying Modes
|
||||
private ModifyMode mode;
|
||||
private Vector2D dragposition;
|
||||
private Vector2D resizefilter;
|
||||
private Vector2D resizevector;
|
||||
private Line2D resizeaxis;
|
||||
private bool adjustoffset;
|
||||
|
||||
// Rectangle components
|
||||
private Vector2D[] corners;
|
||||
private RectangleF[] resizegrips; // top, right, bottom, left
|
||||
private RectangleF[] rotategrips; // lefttop, righttop, rightbottom, leftbottom
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public EditSelectionMode()
|
||||
{
|
||||
// Initialize
|
||||
mode = ModifyMode.None;
|
||||
|
||||
// TEST:
|
||||
rotation = Angle2D.PI2 * 0.01f;
|
||||
}
|
||||
|
||||
// Disposer
|
||||
public override void Dispose()
|
||||
{
|
||||
// Not already disposed?
|
||||
if(!isdisposed)
|
||||
{
|
||||
// Clean up
|
||||
|
||||
// Dispose base
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Events
|
||||
|
||||
// Cancel mode
|
||||
public override void OnCancel()
|
||||
{
|
||||
base.OnCancel();
|
||||
|
||||
// Return to this mode
|
||||
General.Map.ChangeMode(new LinedefsMode());
|
||||
}
|
||||
|
||||
// Mode engages
|
||||
public override void OnEngage()
|
||||
{
|
||||
base.OnEngage();
|
||||
|
||||
// Convert geometry selection into marked vertices
|
||||
General.Map.Map.ClearAllMarks();
|
||||
General.Map.Map.MarkSelectedVertices(true, true);
|
||||
General.Map.Map.MarkSelectedThings(true, true);
|
||||
General.Map.Map.MarkSelectedLinedefs(true, true);
|
||||
ICollection<Vertex> verts = General.Map.Map.GetVerticesFromLinesMarks(true);
|
||||
foreach(Vertex v in verts) v.Marked = true;
|
||||
selectedvertices = General.Map.Map.GetMarkedVertices(true);
|
||||
selectedthings = General.Map.Map.GetMarkedThings(true);
|
||||
|
||||
// Make sure everything is selected so that it turns up red
|
||||
foreach(Vertex v in selectedvertices) v.Selected = true;
|
||||
ICollection<Linedef> markedlines = General.Map.Map.LinedefsFromMarkedVertices(false, true, false);
|
||||
foreach(Linedef l in markedlines) l.Selected = true;
|
||||
|
||||
// Array to keep original coordinates
|
||||
vertexpos = new List<Vector2D>(selectedvertices.Count);
|
||||
thingpos = new List<Vector2D>(selectedthings.Count);
|
||||
|
||||
// A selection must be made!
|
||||
if((selectedvertices.Count > 0) || (selectedthings.Count > 0))
|
||||
{
|
||||
// Initialize offset and size
|
||||
offset.x = float.MaxValue;
|
||||
offset.y = float.MaxValue;
|
||||
Vector2D right;
|
||||
right.x = float.MinValue;
|
||||
right.y = float.MinValue;
|
||||
|
||||
foreach(Vertex v in selectedvertices)
|
||||
{
|
||||
// Calculate offset and size
|
||||
if(v.Position.x < offset.x) offset.x = v.Position.x;
|
||||
if(v.Position.y < offset.y) offset.y = v.Position.y;
|
||||
if(v.Position.x > right.x) right.x = v.Position.x;
|
||||
if(v.Position.y > right.y) right.y = v.Position.y;
|
||||
|
||||
// Keep original coordinates
|
||||
vertexpos.Add(v.Position);
|
||||
}
|
||||
|
||||
foreach(Thing t in selectedthings)
|
||||
{
|
||||
// Calculate offset and size
|
||||
if(t.Position.x < offset.x) offset.x = t.Position.x;
|
||||
if(t.Position.y < offset.y) offset.y = t.Position.y;
|
||||
if(t.Position.x > right.x) right.x = t.Position.x;
|
||||
if(t.Position.y > right.y) right.y = t.Position.y;
|
||||
|
||||
// Keep original coordinates
|
||||
thingpos.Add(t.Position);
|
||||
}
|
||||
|
||||
size = right - offset;
|
||||
basesize = size;
|
||||
baseoffset = offset;
|
||||
|
||||
// Set presentation
|
||||
if(selectedthings.Count > 0)
|
||||
renderer.SetPresentation(Presentation.Things);
|
||||
else
|
||||
renderer.SetPresentation(Presentation.Standard);
|
||||
|
||||
// Update
|
||||
UpdateRectangleComponents();
|
||||
}
|
||||
else
|
||||
{
|
||||
General.Interface.DisplayWarning("Please make a selection first!");
|
||||
|
||||
// Cancel now
|
||||
General.Map.CancelMode();
|
||||
}
|
||||
}
|
||||
|
||||
// Mode disengages
|
||||
public override void OnDisengage()
|
||||
{
|
||||
base.OnDisengage();
|
||||
|
||||
// Hide highlight info
|
||||
General.Interface.HideInfo();
|
||||
General.Interface.SetCursor(Cursors.Default);
|
||||
}
|
||||
|
||||
// This redraws the display
|
||||
public override void OnRedrawDisplay()
|
||||
{
|
||||
UpdateRectangleComponents();
|
||||
|
||||
// Render lines
|
||||
if(renderer.StartPlotter(true))
|
||||
{
|
||||
renderer.PlotLinedefSet(General.Map.Map.Linedefs);
|
||||
renderer.PlotVerticesSet(General.Map.Map.Vertices);
|
||||
renderer.Finish();
|
||||
}
|
||||
|
||||
// Render things
|
||||
if(renderer.StartThings(true))
|
||||
{
|
||||
renderer.RenderThingSet(General.Map.ThingsFilter.HiddenThings, Presentation.THINGS_HIDDEN_ALPHA);
|
||||
renderer.RenderThingSet(General.Map.ThingsFilter.VisibleThings, 1.0f);
|
||||
renderer.Finish();
|
||||
}
|
||||
|
||||
// Render selection
|
||||
if(renderer.StartOverlay(true))
|
||||
{
|
||||
renderer.RenderLine(corners[0], corners[1], 1, General.Colors.Vertices, true);
|
||||
renderer.RenderLine(corners[1], corners[2], 1, General.Colors.Highlight, true);
|
||||
renderer.RenderLine(corners[2], corners[3], 1, General.Colors.Highlight, true);
|
||||
renderer.RenderLine(corners[3], corners[0], 1, General.Colors.Highlight, true);
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
renderer.RenderRectangleFilled(resizegrips[i], General.Colors.Background, true);
|
||||
renderer.RenderRectangle(resizegrips[i], 2, General.Colors.Highlight, true);
|
||||
renderer.RenderRectangleFilled(rotategrips[i], General.Colors.Background, true);
|
||||
renderer.RenderRectangle(rotategrips[i], 2, General.Colors.Indication, true);
|
||||
}
|
||||
renderer.RenderRectangle(rotategrips[0], 2, General.Colors.Vertices, true);
|
||||
renderer.Finish();
|
||||
}
|
||||
|
||||
renderer.Present();
|
||||
}
|
||||
|
||||
// Mouse moves
|
||||
public override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
|
||||
// Not in any modifying mode?
|
||||
if(mode == ModifyMode.None)
|
||||
{
|
||||
// Check what grip the mouse is over
|
||||
// and change cursor accordingly
|
||||
Grip mousegrip = CheckMouseGrip();
|
||||
switch(mousegrip)
|
||||
{
|
||||
case Grip.Main:
|
||||
General.Interface.SetCursor(Cursors.Hand);
|
||||
break;
|
||||
|
||||
case Grip.RotateLB:
|
||||
case Grip.RotateLT:
|
||||
case Grip.RotateRB:
|
||||
case Grip.RotateRT:
|
||||
General.Interface.SetCursor(Cursors.Cross);
|
||||
break;
|
||||
|
||||
case Grip.SizeE:
|
||||
case Grip.SizeS:
|
||||
case Grip.SizeW:
|
||||
case Grip.SizeN:
|
||||
|
||||
// Pick the best matching cursor depending on rotation and side
|
||||
float resizeangle = rotation;
|
||||
if((mousegrip == Grip.SizeE) || (mousegrip == Grip.SizeW)) resizeangle += Angle2D.PIHALF;
|
||||
resizeangle = Angle2D.Normalized(resizeangle);
|
||||
if(resizeangle > Angle2D.PI) resizeangle -= Angle2D.PI;
|
||||
resizeangle = Math.Abs(resizeangle + Angle2D.PI / 8.000001f);
|
||||
int cursorindex = (int)Math.Floor((resizeangle / Angle2D.PI) * 4.0f) % 4;
|
||||
General.Interface.SetCursor(RESIZE_CURSORS[cursorindex]);
|
||||
break;
|
||||
|
||||
default:
|
||||
General.Interface.SetCursor(Cursors.Default);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check what modifying mode we are in
|
||||
switch(mode)
|
||||
{
|
||||
// Dragging
|
||||
case ModifyMode.Dragging:
|
||||
|
||||
// Change offset
|
||||
offset += mousemappos - dragposition;
|
||||
dragposition = mousemappos;
|
||||
|
||||
// Update
|
||||
UpdateGeometry();
|
||||
UpdateRectangleComponents();
|
||||
General.Interface.RedrawDisplay();
|
||||
break;
|
||||
|
||||
// Resizing
|
||||
case ModifyMode.Resizing:
|
||||
|
||||
// Adjust offset if needed
|
||||
Vector2D oldsize = size;
|
||||
|
||||
// Change size
|
||||
float scale = resizeaxis.GetNearestOnLine(mousemappos);
|
||||
size = (basesize * resizefilter) * scale + (1.0f - resizefilter) * basesize;
|
||||
|
||||
// Adjust offset if needed
|
||||
if(adjustoffset) offset -= (size - oldsize) * resizevector / basesize.y;
|
||||
|
||||
// Update
|
||||
UpdateGeometry();
|
||||
UpdateRectangleComponents();
|
||||
General.Interface.RedrawDisplay();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse leaves the display
|
||||
public override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
|
||||
// Reset cursor
|
||||
General.Interface.SetCursor(Cursors.Default);
|
||||
}
|
||||
|
||||
// When select button is pressed
|
||||
protected override void OnSelect()
|
||||
{
|
||||
base.OnSelect();
|
||||
|
||||
// Check what grip the mouse is over
|
||||
switch(CheckMouseGrip())
|
||||
{
|
||||
// Drag main rectangle
|
||||
case Grip.Main:
|
||||
dragposition = mousemappos;
|
||||
mode = ModifyMode.Dragging;
|
||||
break;
|
||||
|
||||
// Resize
|
||||
case Grip.SizeN:
|
||||
|
||||
// Make the resize axis. This is a line with the length and direction
|
||||
// of basesize used to calculate the resize percentage.
|
||||
resizevector = corners[2] - corners[1];
|
||||
resizevector = resizevector.GetNormal() * basesize.y;
|
||||
resizeaxis = new Line2D(corners[2], corners[2] + resizevector);
|
||||
resizefilter = new Vector2D(0.0f, 1.0f);
|
||||
adjustoffset = true;
|
||||
mode = ModifyMode.Resizing;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// When selected button is released
|
||||
protected override void OnEndSelect()
|
||||
{
|
||||
base.OnEndSelect();
|
||||
|
||||
// Check what modifying mode we are in
|
||||
switch(mode)
|
||||
{
|
||||
case ModifyMode.Dragging:
|
||||
General.Interface.RedrawDisplay();
|
||||
break;
|
||||
}
|
||||
|
||||
mode = ModifyMode.None;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
// This checks and returns the grip the mouse pointer is in
|
||||
private Grip CheckMouseGrip()
|
||||
{
|
||||
// Make polygon from corners
|
||||
Polygon rectpoly = new Polygon();
|
||||
rectpoly.AddRange(corners);
|
||||
|
||||
if(PointInRectF(resizegrips[0], mousemappos))
|
||||
return Grip.SizeN;
|
||||
else if(PointInRectF(resizegrips[2], mousemappos))
|
||||
return Grip.SizeS;
|
||||
else if(PointInRectF(resizegrips[1], mousemappos))
|
||||
return Grip.SizeE;
|
||||
else if(PointInRectF(resizegrips[3], mousemappos))
|
||||
return Grip.SizeW;
|
||||
else if(PointInRectF(rotategrips[0], mousemappos))
|
||||
return Grip.RotateLT;
|
||||
else if(PointInRectF(rotategrips[1], mousemappos))
|
||||
return Grip.RotateRT;
|
||||
else if(PointInRectF(rotategrips[2], mousemappos))
|
||||
return Grip.RotateRB;
|
||||
else if(PointInRectF(rotategrips[3], mousemappos))
|
||||
return Grip.RotateLB;
|
||||
else if(rectpoly.Intersect(mousemappos))
|
||||
return Grip.Main;
|
||||
else
|
||||
return Grip.None;
|
||||
}
|
||||
|
||||
// This applies the current rotation and resize to a point
|
||||
private Vector2D TransformedPoint(Vector2D p)
|
||||
{
|
||||
// Resize
|
||||
p = (p - baseoffset) * (size / basesize) + baseoffset;
|
||||
|
||||
// Rotate around center
|
||||
Vector2D center = baseoffset + basesize * 0.5f;
|
||||
Vector2D po = p - center;
|
||||
p.x = (float)Math.Cos(rotation) * po.x + (float)Math.Sin(rotation) * po.y;
|
||||
p.y = (float)Math.Sin(rotation) * -po.x + (float)Math.Cos(rotation) * po.y;
|
||||
p += center;
|
||||
|
||||
// Move
|
||||
p += offset - baseoffset;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// This checks if a point is in a rect
|
||||
private bool PointInRectF(RectangleF rect, Vector2D point)
|
||||
{
|
||||
return (point.x >= rect.Left) && (point.x <= rect.Right) && (point.y >= rect.Top) && (point.y <= rect.Bottom);
|
||||
}
|
||||
|
||||
// This moves all things and vertices to match the current transformation
|
||||
private void UpdateGeometry()
|
||||
{
|
||||
int index = 0;
|
||||
foreach(Vertex v in selectedvertices)
|
||||
{
|
||||
v.Move(TransformedPoint(vertexpos[index++]));
|
||||
}
|
||||
|
||||
index = 0;
|
||||
foreach(Thing t in selectedthings)
|
||||
{
|
||||
t.Move(TransformedPoint(thingpos[index++]));
|
||||
}
|
||||
|
||||
General.Map.Map.Update(true, false);
|
||||
}
|
||||
|
||||
// This updates the selection rectangle components
|
||||
private void UpdateRectangleComponents()
|
||||
{
|
||||
float border = BORDER_PADDING / renderer.Scale;
|
||||
float gripsize = GRIP_SIZE / renderer.Scale;
|
||||
|
||||
// Corners
|
||||
corners = new Vector2D[4];
|
||||
corners[0] = TransformedPoint(new Vector2D(baseoffset.x - border, baseoffset.y - border));
|
||||
corners[1] = TransformedPoint(new Vector2D(baseoffset.x - border + basesize.x + border * 2, baseoffset.y - border));
|
||||
corners[2] = TransformedPoint(new Vector2D(baseoffset.x - border + basesize.x + border * 2, baseoffset.y - border + basesize.y + border * 2));
|
||||
corners[3] = TransformedPoint(new Vector2D(baseoffset.x - border, baseoffset.y - border + basesize.y + border * 2));
|
||||
|
||||
// Middle points between corners
|
||||
Vector2D middle01 = corners[0] + (corners[1] - corners[0]) * 0.5f;
|
||||
Vector2D middle12 = corners[1] + (corners[2] - corners[1]) * 0.5f;
|
||||
Vector2D middle23 = corners[2] + (corners[3] - corners[2]) * 0.5f;
|
||||
Vector2D middle30 = corners[3] + (corners[0] - corners[3]) * 0.5f;
|
||||
|
||||
// Resize grips
|
||||
resizegrips = new RectangleF[4];
|
||||
resizegrips[0] = new RectangleF(middle01.x - gripsize * 0.5f,
|
||||
middle01.y - gripsize * 0.5f,
|
||||
gripsize, gripsize);
|
||||
resizegrips[1] = new RectangleF(middle12.x - gripsize * 0.5f,
|
||||
middle12.y - gripsize * 0.5f,
|
||||
gripsize, gripsize);
|
||||
resizegrips[2] = new RectangleF(middle23.x - gripsize * 0.5f,
|
||||
middle23.y - gripsize * 0.5f,
|
||||
gripsize, gripsize);
|
||||
resizegrips[3] = new RectangleF(middle30.x - gripsize * 0.5f,
|
||||
middle30.y - gripsize * 0.5f,
|
||||
gripsize, gripsize);
|
||||
|
||||
// Rotate grips
|
||||
rotategrips = new RectangleF[4];
|
||||
rotategrips[0] = new RectangleF(corners[0].x - gripsize * 0.5f,
|
||||
corners[0].y - gripsize * 0.5f,
|
||||
gripsize, gripsize);
|
||||
rotategrips[1] = new RectangleF(corners[1].x - gripsize * 0.5f,
|
||||
corners[1].y - gripsize * 0.5f,
|
||||
gripsize, gripsize);
|
||||
rotategrips[2] = new RectangleF(corners[2].x - gripsize * 0.5f,
|
||||
corners[2].y - gripsize * 0.5f,
|
||||
gripsize, gripsize);
|
||||
rotategrips[3] = new RectangleF(corners[3].x - gripsize * 0.5f,
|
||||
corners[3].y - gripsize * 0.5f,
|
||||
gripsize, gripsize);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -199,3 +199,12 @@ findmode
|
|||
allowmouse = true;
|
||||
allowscroll = true;
|
||||
}
|
||||
|
||||
editselectionmode
|
||||
{
|
||||
title = "Edit: Edit Selection Mode";
|
||||
description = "Allows rotating, resizing and moving a selection.";
|
||||
allowkeys = true;
|
||||
allowmouse = true;
|
||||
allowscroll = true;
|
||||
}
|
||||
|
|
|
@ -411,7 +411,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
}
|
||||
|
||||
// This shows a polygon
|
||||
private void ShowPolygon(Polygon p, PixelColor c)
|
||||
private void ShowPolygon(EarClipPolygon p, PixelColor c)
|
||||
{
|
||||
LinkedListNode<EarClipVertex> v;
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
|
||||
internal static extern int SendMessage(IntPtr hwnd, uint Msg, int wParam, int lParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool MessageBeep(MessageBeepType type);
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
165
Source/Geometry/EarClipPolygon.cs
Normal file
165
Source/Geometry/EarClipPolygon.cs
Normal file
|
@ -0,0 +1,165 @@
|
|||
|
||||
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
||||
* This program is released under GNU General Public License
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
using SlimDX.Direct3D9;
|
||||
using System.Drawing;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.Geometry
|
||||
{
|
||||
public class EarClipPolygon : LinkedList<EarClipVertex>
|
||||
{
|
||||
#region ================== Variables
|
||||
|
||||
// Tree variables
|
||||
private List<EarClipPolygon> children;
|
||||
private bool inner;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public List<EarClipPolygon> Children { get { return children; } }
|
||||
public bool Inner { get { return inner; } set { inner = value; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructors
|
||||
|
||||
// Constructor
|
||||
internal EarClipPolygon()
|
||||
{
|
||||
// Initialize
|
||||
children = new List<EarClipPolygon>();
|
||||
}
|
||||
|
||||
// Constructor
|
||||
internal EarClipPolygon(EarClipPolygon p, EarClipVertex add) : base(p)
|
||||
{
|
||||
// Initialize
|
||||
base.AddLast(add);
|
||||
children = new List<EarClipPolygon>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
// This merges a polygon into this one
|
||||
public void Add(EarClipPolygon p)
|
||||
{
|
||||
// Initialize
|
||||
foreach(EarClipVertex v in p) base.AddLast(v);
|
||||
}
|
||||
|
||||
// Point inside the polygon?
|
||||
// See: http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/
|
||||
public bool Intersect(Vector2D p)
|
||||
{
|
||||
float miny, maxy, maxx, xint;
|
||||
Vector2D v1 = base.Last.Value.Position;
|
||||
Vector2D v2;
|
||||
LinkedListNode<EarClipVertex> n = base.First;
|
||||
uint c = 0;
|
||||
|
||||
// Go for all vertices
|
||||
while(n != null)
|
||||
{
|
||||
// Get next vertex
|
||||
v2 = n.Value.Position;
|
||||
|
||||
// Determine min/max values
|
||||
miny = Math.Min(v1.y, v2.y);
|
||||
maxy = Math.Max(v1.y, v2.y);
|
||||
maxx = Math.Max(v1.x, v2.x);
|
||||
|
||||
// Check for intersection
|
||||
if((p.y > miny) && (p.y <= maxy))
|
||||
{
|
||||
if(p.x <= maxx)
|
||||
{
|
||||
if(v1.y != v2.y)
|
||||
{
|
||||
xint = (p.y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y) + v1.x;
|
||||
if((v1.x == v2.x) || (p.x <= xint)) c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move to next
|
||||
v1 = v2;
|
||||
n = n.Next;
|
||||
}
|
||||
|
||||
// Inside this polygon?
|
||||
if((c & 0x00000001UL) != 0)
|
||||
{
|
||||
// Check if not inside the children
|
||||
foreach(EarClipPolygon child in children)
|
||||
{
|
||||
// Inside this child? Then it is not inside this polygon.
|
||||
if(child.Intersect(p)) return false;
|
||||
}
|
||||
|
||||
// Inside polygon!
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not inside the polygon
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This inserts a polygon if it is a child of this one
|
||||
public bool InsertChild(EarClipPolygon p)
|
||||
{
|
||||
// Polygon must have at least 1 vertex
|
||||
if(p.Count == 0) return false;
|
||||
|
||||
// Check if it can be inserted at a lower level
|
||||
foreach(EarClipPolygon child in children)
|
||||
{
|
||||
if(child.InsertChild(p)) return true;
|
||||
}
|
||||
|
||||
// Check if it can be inserted here
|
||||
if(this.Intersect(p.First.Value.Position))
|
||||
{
|
||||
// Make the polygon the inverse of this one
|
||||
p.Inner = !inner;
|
||||
children.Add(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can't insert it as a child
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -97,9 +97,9 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
// This makes a polygon from the path
|
||||
public Polygon MakePolygon()
|
||||
public EarClipPolygon MakePolygon()
|
||||
{
|
||||
Polygon p = new Polygon();
|
||||
EarClipPolygon p = new EarClipPolygon();
|
||||
bool forward = true;
|
||||
|
||||
// Any sides at all?
|
||||
|
|
|
@ -31,66 +31,43 @@ using CodeImp.DoomBuilder.Map;
|
|||
|
||||
namespace CodeImp.DoomBuilder.Geometry
|
||||
{
|
||||
public class Polygon : LinkedList<EarClipVertex>
|
||||
public class Polygon : List<Vector2D>
|
||||
{
|
||||
#region ================== Variables
|
||||
|
||||
// Tree variables
|
||||
private List<Polygon> children;
|
||||
private bool inner;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public List<Polygon> Children { get { return children; } }
|
||||
public bool Inner { get { return inner; } set { inner = value; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructors
|
||||
|
||||
// Constructor
|
||||
internal Polygon()
|
||||
public Polygon()
|
||||
{
|
||||
// Initialize
|
||||
children = new List<Polygon>();
|
||||
}
|
||||
|
||||
// Constructor
|
||||
internal Polygon(Polygon p, EarClipVertex add) : base(p)
|
||||
{
|
||||
// Initialize
|
||||
base.AddLast(add);
|
||||
children = new List<Polygon>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
// This merges a polygon into this one
|
||||
public void Add(Polygon p)
|
||||
{
|
||||
// Initialize
|
||||
foreach(EarClipVertex v in p) base.AddLast(v);
|
||||
}
|
||||
|
||||
// Point inside the polygon?
|
||||
// See: http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/
|
||||
public bool Intersect(Vector2D p)
|
||||
{
|
||||
float miny, maxy, maxx, xint;
|
||||
Vector2D v1 = base.Last.Value.Position;
|
||||
Vector2D v1 = base[base.Count - 1];
|
||||
Vector2D v2;
|
||||
LinkedListNode<EarClipVertex> n = base.First;
|
||||
int index = 0;
|
||||
uint c = 0;
|
||||
|
||||
|
||||
// Go for all vertices
|
||||
while(n != null)
|
||||
while(index < base.Count)
|
||||
{
|
||||
// Get next vertex
|
||||
v2 = n.Value.Position;
|
||||
v2 = base[index];
|
||||
|
||||
// Determine min/max values
|
||||
miny = Math.Min(v1.y, v2.y);
|
||||
|
@ -109,57 +86,16 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Move to next
|
||||
v1 = v2;
|
||||
n = n.Next;
|
||||
index++;
|
||||
}
|
||||
|
||||
// Inside this polygon?
|
||||
if((c & 0x00000001UL) != 0)
|
||||
{
|
||||
// Check if not inside the children
|
||||
foreach(Polygon child in children)
|
||||
{
|
||||
// Inside this child? Then it is not inside this polygon.
|
||||
if(child.Intersect(p)) return false;
|
||||
}
|
||||
|
||||
// Inside polygon!
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not inside the polygon
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This inserts a polygon if it is a child of this one
|
||||
public bool InsertChild(Polygon p)
|
||||
{
|
||||
// Polygon must have at least 1 vertex
|
||||
if(p.Count == 0) return false;
|
||||
|
||||
// Check if it can be inserted at a lower level
|
||||
foreach(Polygon child in children)
|
||||
{
|
||||
if(child.InsertChild(p)) return true;
|
||||
}
|
||||
|
||||
// Check if it can be inserted here
|
||||
if(this.Intersect(p.First.Value.Position))
|
||||
{
|
||||
// Make the polygon the inverse of this one
|
||||
p.Inner = !inner;
|
||||
children.Add(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can't insert it as a child
|
||||
return false;
|
||||
// Inside this polygon?
|
||||
return (c & 0x00000001UL) != 0;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
List<LinedefSide> alllines = new List<LinedefSide>();
|
||||
|
||||
// Find the outer lines
|
||||
Polygon p = FindOuterLines(line, front, alllines);
|
||||
EarClipPolygon p = FindOuterLines(line, front, alllines);
|
||||
if(p != null)
|
||||
{
|
||||
// Find the inner lines
|
||||
|
@ -87,7 +87,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
// This finds the inner lines of the sector and adds them to the sector polygon
|
||||
private static void FindInnerLines(Polygon p, List<LinedefSide> alllines)
|
||||
private static void FindInnerLines(EarClipPolygon p, List<LinedefSide> alllines)
|
||||
{
|
||||
Vertex foundv;
|
||||
bool vvalid, findmore;
|
||||
|
@ -169,7 +169,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
{
|
||||
// Make polygon
|
||||
LinedefTracePath tracepath = new LinedefTracePath(innerlines);
|
||||
Polygon innerpoly = tracepath.MakePolygon();
|
||||
EarClipPolygon innerpoly = tracepath.MakePolygon();
|
||||
|
||||
// Check if the front of the line is outside the polygon
|
||||
if(!innerpoly.Intersect(foundline.GetSidePoint(foundlinefront)))
|
||||
|
@ -188,7 +188,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
|
||||
// This finds the outer lines of the sector as a polygon
|
||||
// Returns null when no valid outer polygon can be found
|
||||
private static Polygon FindOuterLines(Linedef line, bool front, List<LinedefSide> alllines)
|
||||
private static EarClipPolygon FindOuterLines(Linedef line, bool front, List<LinedefSide> alllines)
|
||||
{
|
||||
Linedef scanline = line;
|
||||
bool scanfront = front;
|
||||
|
@ -201,7 +201,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
{
|
||||
// Make polygon
|
||||
LinedefTracePath tracepath = new LinedefTracePath(pathlines);
|
||||
Polygon poly = tracepath.MakePolygon();
|
||||
EarClipPolygon poly = tracepath.MakePolygon();
|
||||
|
||||
// Check if the front of the line is inside the polygon
|
||||
if(poly.Intersect(line.GetSidePoint(front)))
|
||||
|
|
|
@ -84,9 +84,9 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
// This makes a polygon from the path
|
||||
public Polygon MakePolygon()
|
||||
public EarClipPolygon MakePolygon()
|
||||
{
|
||||
Polygon p = new Polygon();
|
||||
EarClipPolygon p = new EarClipPolygon();
|
||||
|
||||
// Any sides at all?
|
||||
if(base.Count > 0)
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
// For debugging purpose only!
|
||||
// These are not called in a release build
|
||||
public delegate void ShowLine(Vector2D v1, Vector2D v2, PixelColor c);
|
||||
public delegate void ShowPolygon(Polygon p, PixelColor c);
|
||||
public delegate void ShowPolygon(EarClipPolygon p, PixelColor c);
|
||||
public delegate void ShowPoint(Vector2D v, int c);
|
||||
public delegate void ShowEarClip(EarClipVertex[] found, LinkedList<EarClipVertex> remaining);
|
||||
|
||||
|
@ -87,7 +87,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
public TriangleList PerformTriangulation(Sector sector)
|
||||
{
|
||||
TriangleList triangles = new TriangleList();
|
||||
List<Polygon> polys;
|
||||
List<EarClipPolygon> polys;
|
||||
|
||||
/*
|
||||
* This process is divided into several steps:
|
||||
|
@ -110,7 +110,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
DoCutting(polys);
|
||||
|
||||
// EAR-CLIPPING
|
||||
foreach(Polygon p in polys) triangles.AddRange(DoEarClip(p));
|
||||
foreach(EarClipPolygon p in polys) triangles.AddRange(DoEarClip(p));
|
||||
|
||||
// Return result
|
||||
return triangles;
|
||||
|
@ -121,13 +121,13 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
#region ================== Tracing
|
||||
|
||||
// This traces sector lines to create a polygon tree
|
||||
private List<Polygon> DoTrace(Sector s)
|
||||
private List<EarClipPolygon> DoTrace(Sector s)
|
||||
{
|
||||
Dictionary<Sidedef, bool> todosides = new Dictionary<Sidedef, bool>(s.Sidedefs.Count);
|
||||
Dictionary<Vertex, Vertex> ignores = new Dictionary<Vertex,Vertex>();
|
||||
List<Polygon> root = new List<Polygon>();
|
||||
List<EarClipPolygon> root = new List<EarClipPolygon>();
|
||||
SidedefsTracePath path;
|
||||
Polygon newpoly;
|
||||
EarClipPolygon newpoly;
|
||||
Vertex start;
|
||||
|
||||
// Fill the dictionary
|
||||
|
@ -174,7 +174,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
#endif
|
||||
|
||||
// Determine where this polygon goes in our tree
|
||||
foreach(Polygon p in root)
|
||||
foreach(EarClipPolygon p in root)
|
||||
{
|
||||
// Insert if it belongs as a child
|
||||
if(p.InsertChild(newpoly))
|
||||
|
@ -333,26 +333,26 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
#region ================== Cutting
|
||||
|
||||
// This cuts into outer polygons to solve inner polygons and make the polygon tree flat
|
||||
private void DoCutting(List<Polygon> polys)
|
||||
private void DoCutting(List<EarClipPolygon> polys)
|
||||
{
|
||||
Queue<Polygon> todo = new Queue<Polygon>(polys);
|
||||
Queue<EarClipPolygon> todo = new Queue<EarClipPolygon>(polys);
|
||||
|
||||
// Begin processing outer polygons
|
||||
while(todo.Count > 0)
|
||||
{
|
||||
// Get outer polygon to process
|
||||
Polygon p = todo.Dequeue();
|
||||
EarClipPolygon p = todo.Dequeue();
|
||||
|
||||
// Any inner polygons to work with?
|
||||
if(p.Children.Count > 0)
|
||||
{
|
||||
// Go for all the children
|
||||
foreach(Polygon c in p.Children)
|
||||
foreach(EarClipPolygon c in p.Children)
|
||||
{
|
||||
// The children of the children are outer polygons again,
|
||||
// so move them to the root and add for processing
|
||||
polys.AddRange(c.Children);
|
||||
foreach(Polygon sc in c.Children) todo.Enqueue(sc);
|
||||
foreach(EarClipPolygon sc in c.Children) todo.Enqueue(sc);
|
||||
|
||||
// Remove from inner polygon
|
||||
c.Children.Clear();
|
||||
|
@ -365,12 +365,12 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
// This takes an outer polygon and a set of inner polygons to start cutting on
|
||||
private void MergeInnerPolys(Polygon p)
|
||||
private void MergeInnerPolys(EarClipPolygon p)
|
||||
{
|
||||
LinkedList<Polygon> todo = new LinkedList<Polygon>(p.Children);
|
||||
LinkedList<EarClipPolygon> todo = new LinkedList<EarClipPolygon>(p.Children);
|
||||
LinkedListNode<EarClipVertex> start;
|
||||
LinkedListNode<Polygon> ip;
|
||||
LinkedListNode<Polygon> found;
|
||||
LinkedListNode<EarClipPolygon> ip;
|
||||
LinkedListNode<EarClipPolygon> found;
|
||||
LinkedListNode<EarClipVertex> foundstart;
|
||||
|
||||
// Continue until no more inner polygons to process
|
||||
|
@ -406,7 +406,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
// This finds the right-most vertex in an inner polygon to use for cut startpoint.
|
||||
private static LinkedListNode<EarClipVertex> FindRightMostVertex(Polygon p)
|
||||
private static LinkedListNode<EarClipVertex> FindRightMostVertex(EarClipPolygon p)
|
||||
{
|
||||
LinkedListNode<EarClipVertex> found = p.First;
|
||||
LinkedListNode<EarClipVertex> v = found.Next;
|
||||
|
@ -423,7 +423,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
// This finds the cut coordinates and splits the other poly with inner vertices
|
||||
private static void SplitOuterWithInner(LinkedListNode<EarClipVertex> start, Polygon p, Polygon inner)
|
||||
private static void SplitOuterWithInner(LinkedListNode<EarClipVertex> start, EarClipPolygon p, EarClipPolygon inner)
|
||||
{
|
||||
Line2D starttoright = new Line2D(start.Value.Position, start.Value.Position + new Vector2D(1000.0f, 0.0f));
|
||||
LinkedListNode<EarClipVertex> v1, v2;
|
||||
|
@ -516,7 +516,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
|
||||
// This clips a polygon and returns the triangles
|
||||
// The polygon may not have any holes or islands
|
||||
private TriangleList DoEarClip(Polygon poly)
|
||||
private TriangleList DoEarClip(EarClipPolygon poly)
|
||||
{
|
||||
LinkedList<EarClipVertex> verts = new LinkedList<EarClipVertex>();
|
||||
List<EarClipVertex> convexes = new List<EarClipVertex>(poly.Count);
|
||||
|
|
16
Source/Properties/Resources.Designer.cs
generated
16
Source/Properties/Resources.Designer.cs
generated
|
@ -1,7 +1,7 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.1433
|
||||
// Runtime Version:2.0.50727.832
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
|
@ -235,6 +235,20 @@ namespace CodeImp.DoomBuilder.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
internal static System.Drawing.Bitmap Warning {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("Warning", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
internal static System.Drawing.Bitmap WarningOff {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("WarningOff", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
internal static System.Drawing.Bitmap Zoom {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("Zoom", resourceCulture);
|
||||
|
|
|
@ -196,4 +196,10 @@
|
|||
<data name="Test" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Test.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Warning" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Warning.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="WarningOff" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\WarningOff.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
BIN
Source/Resources/Warning.png
Normal file
BIN
Source/Resources/Warning.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 725 B |
BIN
Source/Resources/WarningOff.png
Normal file
BIN
Source/Resources/WarningOff.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 250 B |
|
@ -70,7 +70,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
void ResumeExclusiveMouseInput();
|
||||
bool CheckActionActive(Assembly assembly, string actionname);
|
||||
void SetCursor(Cursor cursor);
|
||||
|
||||
void DisplayWarning(string warning);
|
||||
void HideWarning();
|
||||
void MessageBeep(MessageBeepType type);
|
||||
|
||||
/// <summary>
|
||||
/// This browses the lindef types
|
||||
/// </summary>
|
||||
|
|
47
Source/Windows/MainForm.Designer.cs
generated
47
Source/Windows/MainForm.Designer.cs
generated
|
@ -91,6 +91,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.statusbar = new System.Windows.Forms.StatusStrip();
|
||||
this.statuslabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.warninglabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.gridlabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.buttongrid = new System.Windows.Forms.ToolStripDropDownButton();
|
||||
this.itemgrid1024 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
|
@ -123,6 +124,8 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.redrawtimer = new System.Windows.Forms.Timer(this.components);
|
||||
this.display = new CodeImp.DoomBuilder.Controls.RenderTargetControl();
|
||||
this.processor = new System.Windows.Forms.Timer(this.components);
|
||||
this.warningtimer = new System.Windows.Forms.Timer(this.components);
|
||||
this.warningflasher = new System.Windows.Forms.Timer(this.components);
|
||||
toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
|
||||
|
@ -239,7 +242,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.menuhelp});
|
||||
this.menumain.Location = new System.Drawing.Point(0, 0);
|
||||
this.menumain.Name = "menumain";
|
||||
this.menumain.Size = new System.Drawing.Size(823, 24);
|
||||
this.menumain.Size = new System.Drawing.Size(961, 24);
|
||||
this.menumain.TabIndex = 0;
|
||||
//
|
||||
// menufile
|
||||
|
@ -514,7 +517,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.toolStripSeparator6});
|
||||
this.toolbar.Location = new System.Drawing.Point(0, 24);
|
||||
this.toolbar.Name = "toolbar";
|
||||
this.toolbar.Size = new System.Drawing.Size(823, 25);
|
||||
this.toolbar.Size = new System.Drawing.Size(961, 25);
|
||||
this.toolbar.TabIndex = 1;
|
||||
//
|
||||
// buttonnewmap
|
||||
|
@ -669,6 +672,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.statusbar.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.statusbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.statuslabel,
|
||||
this.warninglabel,
|
||||
this.gridlabel,
|
||||
this.buttongrid,
|
||||
toolStripSeparator1,
|
||||
|
@ -678,10 +682,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.xposlabel,
|
||||
this.poscommalabel,
|
||||
this.yposlabel});
|
||||
this.statusbar.Location = new System.Drawing.Point(0, 522);
|
||||
this.statusbar.Location = new System.Drawing.Point(0, 611);
|
||||
this.statusbar.Name = "statusbar";
|
||||
this.statusbar.ShowItemToolTips = true;
|
||||
this.statusbar.Size = new System.Drawing.Size(823, 23);
|
||||
this.statusbar.Size = new System.Drawing.Size(961, 23);
|
||||
this.statusbar.TabIndex = 2;
|
||||
//
|
||||
// statuslabel
|
||||
|
@ -690,17 +694,29 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.statuslabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.statuslabel.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
|
||||
this.statuslabel.Name = "statuslabel";
|
||||
this.statuslabel.Size = new System.Drawing.Size(497, 18);
|
||||
this.statuslabel.Size = new System.Drawing.Size(571, 18);
|
||||
this.statuslabel.Spring = true;
|
||||
this.statuslabel.Text = "Initializing user interface...";
|
||||
this.statuslabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// warninglabel
|
||||
//
|
||||
this.warninglabel.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.warninglabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.Warning;
|
||||
this.warninglabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.warninglabel.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
|
||||
this.warninglabel.Name = "warninglabel";
|
||||
this.warninglabel.Size = new System.Drawing.Size(167, 18);
|
||||
this.warninglabel.Text = "Make a selection first!";
|
||||
this.warninglabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.warninglabel.Visible = false;
|
||||
//
|
||||
// gridlabel
|
||||
//
|
||||
this.gridlabel.AutoSize = false;
|
||||
this.gridlabel.AutoToolTip = true;
|
||||
this.gridlabel.Name = "gridlabel";
|
||||
this.gridlabel.Size = new System.Drawing.Size(64, 18);
|
||||
this.gridlabel.Size = new System.Drawing.Size(128, 18);
|
||||
this.gridlabel.Text = "32 mp";
|
||||
this.gridlabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.gridlabel.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay;
|
||||
|
@ -916,9 +932,9 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.panelinfo.Controls.Add(this.sectorinfo);
|
||||
this.panelinfo.Controls.Add(this.linedefinfo);
|
||||
this.panelinfo.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.panelinfo.Location = new System.Drawing.Point(0, 416);
|
||||
this.panelinfo.Location = new System.Drawing.Point(0, 505);
|
||||
this.panelinfo.Name = "panelinfo";
|
||||
this.panelinfo.Size = new System.Drawing.Size(823, 106);
|
||||
this.panelinfo.Size = new System.Drawing.Size(961, 106);
|
||||
this.panelinfo.TabIndex = 4;
|
||||
//
|
||||
// modename
|
||||
|
@ -993,7 +1009,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.display.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.display.Location = new System.Drawing.Point(0, 49);
|
||||
this.display.Name = "display";
|
||||
this.display.Size = new System.Drawing.Size(823, 367);
|
||||
this.display.Size = new System.Drawing.Size(961, 456);
|
||||
this.display.TabIndex = 5;
|
||||
this.display.MouseLeave += new System.EventHandler(this.display_MouseLeave);
|
||||
this.display.MouseDown += new System.Windows.Forms.MouseEventHandler(this.display_MouseDown);
|
||||
|
@ -1010,10 +1026,18 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
this.processor.Interval = 10;
|
||||
this.processor.Tick += new System.EventHandler(this.processor_Tick);
|
||||
//
|
||||
// warningtimer
|
||||
//
|
||||
this.warningtimer.Tick += new System.EventHandler(this.warningtimer_Tick);
|
||||
//
|
||||
// warningflasher
|
||||
//
|
||||
this.warningflasher.Tick += new System.EventHandler(this.warningflasher_Tick);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||
this.ClientSize = new System.Drawing.Size(823, 545);
|
||||
this.ClientSize = new System.Drawing.Size(961, 634);
|
||||
this.Controls.Add(this.display);
|
||||
this.Controls.Add(this.panelinfo);
|
||||
this.Controls.Add(this.statusbar);
|
||||
|
@ -1131,5 +1155,8 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
private System.Windows.Forms.ToolStripMenuItem itemgriddec;
|
||||
private System.Windows.Forms.ToolStripMenuItem itemgridsetup;
|
||||
private System.Windows.Forms.Label modename;
|
||||
private System.Windows.Forms.ToolStripStatusLabel warninglabel;
|
||||
private System.Windows.Forms.Timer warningtimer;
|
||||
private System.Windows.Forms.Timer warningflasher;
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ using System.Reflection;
|
|||
using CodeImp.DoomBuilder.Plugins;
|
||||
using CodeImp.DoomBuilder.Controls;
|
||||
using CodeImp.DoomBuilder.IO;
|
||||
using CodeImp.DoomBuilder.Properties;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -46,7 +47,8 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
private const string STATUS_READY_TEXT = "Ready.";
|
||||
private const int MAX_RECENT_FILES = 8;
|
||||
private const int MAX_RECENT_FILES_PIXELS = 250;
|
||||
|
||||
private const int WARNING_FLASH_COUNT = 5;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Delegates
|
||||
|
@ -82,6 +84,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
private EventHandler buttonvisiblechangedhandler;
|
||||
private bool updatingfilters;
|
||||
|
||||
// Statusbar
|
||||
private int warningflashcount;
|
||||
private bool warningsignon;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
@ -136,6 +142,12 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
|
||||
#region ================== General
|
||||
|
||||
// This makes a beep sound
|
||||
public void MessageBeep(MessageBeepType type)
|
||||
{
|
||||
General.MessageBeep(type);
|
||||
}
|
||||
|
||||
// This updates all menus for the current status
|
||||
internal void UpdateInterface()
|
||||
{
|
||||
|
@ -306,6 +318,9 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
if(General.CloseMap())
|
||||
{
|
||||
General.WriteLogLine("Closing main interface window...");
|
||||
|
||||
// Hide warning to stop timers
|
||||
HideWarning();
|
||||
|
||||
// Stop exclusive mode, if any is active
|
||||
StopExclusiveMouseInput();
|
||||
|
@ -380,10 +395,70 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
{
|
||||
return statuslabel.Text;
|
||||
}
|
||||
|
||||
// This shows a warning
|
||||
public void DisplayWarning(string warning)
|
||||
{
|
||||
MessageBeep(MessageBeepType.Warning);
|
||||
warninglabel.Spring = true;
|
||||
warninglabel.Text = warning;
|
||||
warninglabel.Image = Resources.Warning;
|
||||
warninglabel.Visible = true;
|
||||
warningflashcount = 0;
|
||||
warningsignon = true;
|
||||
warningtimer.Stop();
|
||||
warningtimer.Interval = 3000;
|
||||
warningtimer.Start();
|
||||
warningflasher.Start();
|
||||
}
|
||||
|
||||
// This hides any warning
|
||||
public void HideWarning()
|
||||
{
|
||||
warningtimer.Stop();
|
||||
warninglabel.Visible = false;
|
||||
warninglabel.Spring = false;
|
||||
warningflasher.Stop();
|
||||
}
|
||||
|
||||
// This flashes the warning sign
|
||||
private void warningflasher_Tick(object sender, EventArgs e)
|
||||
{
|
||||
// Warning sign on?
|
||||
if(warningsignon)
|
||||
{
|
||||
// Turn it off or should we stop?
|
||||
if(warningflashcount < WARNING_FLASH_COUNT)
|
||||
{
|
||||
warninglabel.Image = Resources.WarningOff;
|
||||
warningsignon = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
warningflasher.Stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Turn it on and count the flash
|
||||
warninglabel.Image = Resources.Warning;
|
||||
warningsignon = true;
|
||||
warningflashcount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Warning timed out
|
||||
private void warningtimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
HideWarning();
|
||||
}
|
||||
|
||||
// This changes status text
|
||||
public void DisplayStatus(string status)
|
||||
{
|
||||
// Hide any warning
|
||||
HideWarning();
|
||||
|
||||
// Update status description
|
||||
if(statuslabel.Text != status)
|
||||
statuslabel.Text = status;
|
||||
|
|
|
@ -156,53 +156,26 @@
|
|||
<metadata name="toolStripSeparator2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="menumain.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="menumain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="toolbar.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="toolbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>121, 17</value>
|
||||
</metadata>
|
||||
<metadata name="statusbar.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="statusbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>207, 17</value>
|
||||
</metadata>
|
||||
<metadata name="panelinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="modename.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="vertexinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="thinginfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="sectorinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="linedefinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="redrawtimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>304, 17</value>
|
||||
</metadata>
|
||||
<metadata name="display.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="processor.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>416, 17</value>
|
||||
</metadata>
|
||||
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
<metadata name="warningtimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>515, 17</value>
|
||||
</metadata>
|
||||
<metadata name="warningflasher.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>632, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
|
|
50
Source/Windows/MessageBeepType.cs
Normal file
50
Source/Windows/MessageBeepType.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
|
||||
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
||||
* This program is released under GNU General Public License
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Drawing;
|
||||
using System.ComponentModel;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
using SlimDX.Direct3D9;
|
||||
using SlimDX;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using System.Drawing.Imaging;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
using CodeImp.DoomBuilder.Editing;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.Windows
|
||||
{
|
||||
public enum MessageBeepType : int
|
||||
{
|
||||
Default = -1,
|
||||
Ok = 0x00000000,
|
||||
Error = 0x00000010,
|
||||
Question = 0x00000020,
|
||||
Warning = 0x00000030,
|
||||
Information = 0x00000040,
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue