2009-04-19 18:07:22 +00:00
#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.Generic ;
2020-04-11 08:42:41 +00:00
using System.Linq ;
2009-04-19 18:07:22 +00:00
using System.Windows.Forms ;
Removed "Paste Properties Options" action.
Added "Paste Properties Special" actions in "Classic" and "Visual" categories. They work the same way as "Paste Special" action.
Added: "Copy Properties", "Paste Properties" and "Paste Properties Special" options are now shown in the Edit menu if current classic mode supports them.
Changed, Paste Properties Special window: only options relevant to current map format are now displayed.
Changed, Paste Properties Special window, UDMF: all UI-managed options are now available.
Fixed: MAPINFO parser was unable to process "include" directives.
Fixed, General interface: selection info was reset to "Nothing selected" after few seconds regardless of current selection.
Fixed, Visual mode: thing bounding boxes were not updated when changing things positions using Randomize mode.
Fixed, Visual mode: event lines were displayed at incorrect height when entering Visual mode for the first time.
Fixed, Texture Browser window: when MixTexturesFlats Game Configuration option is disabled, textures/flats are no longer shown in the Used group when flats/textures with the same names are used in the map.
Fixed(?): probably fixed an exception some users reported when trying to initialize a Classic mode after switching from Visual mode with "Sync cameras" option enabled.
Changed, Game configurations, Thing Categories: a block must have at least one thing category property to be recognized as a thing category.
Changed, Visplane Explorer: the plugin now outputs more info when it fails to initialize vpo.dll.
Cosmetic, Thing Edit window, Doom/Hexen map format: adjusted UI layout so thing flags control no longer displays scrollbars in Hexen map format.
Internal: merged methods from UDMFTools into UniFields, removed UDMFTools.
Updated Inno Setup script (added VC++ 2008 SP1 distributive).
Updated ZDoom_DECORATE.cfg (A_CheckBlock).
Updated documentation (added "System Requirements" page).
2015-10-09 12:38:12 +00:00
using CodeImp.DoomBuilder.BuilderModes.Interface ;
2009-04-19 18:07:22 +00:00
using CodeImp.DoomBuilder.Windows ;
using CodeImp.DoomBuilder.Map ;
using CodeImp.DoomBuilder.Rendering ;
using CodeImp.DoomBuilder.Geometry ;
using CodeImp.DoomBuilder.Editing ;
using CodeImp.DoomBuilder.Actions ;
2014-01-08 09:46:57 +00:00
using System.Drawing ;
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder.BuilderModes
{
[ EditMode ( DisplayName = "Vertices Mode" ,
SwitchAction = "verticesmode" , // Action name used to switch to this mode
2013-09-11 09:47:53 +00:00
ButtonImage = "VerticesMode.png" , // Image resource name for the button
2014-01-09 13:09:43 +00:00
ButtonOrder = int . MinValue , // Position of the button (lower is more to the left)
2009-04-19 18:07:22 +00:00
ButtonGroup = "000_editing" ,
2009-07-09 15:15:49 +00:00
UseByDefault = true ,
SafeStartMode = true ) ]
2009-04-19 18:07:22 +00:00
public class VerticesMode : BaseClassicMode
{
#region = = = = = = = = = = = = = = = = = = Constants
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Highlighted item
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
private Vertex highlighted ;
2015-08-04 23:28:02 +00:00
private Vector2D insertpreview = new Vector2D ( float . NaN , float . NaN ) ; //mxd
2009-04-19 18:07:22 +00:00
// Interface
2016-10-28 21:32:52 +00:00
new private bool editpressed ;
2016-09-27 19:39:46 +00:00
private bool selectionfromhighlight ; //mxd
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
2009-05-17 14:00:36 +00:00
public override object HighlightedObject { get { return highlighted ; } }
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
public override void OnHelp ( )
{
General . ShowHelp ( "e_vertices.html" ) ;
}
// Cancel mode
public override void OnCancel ( )
{
base . OnCancel ( ) ;
// Return to this mode
General . Editing . ChangeMode ( new VerticesMode ( ) ) ;
}
// Mode engages
public override void OnEngage ( )
{
base . OnEngage ( ) ;
renderer . SetPresentation ( Presentation . Standard ) ;
2010-08-15 13:45:43 +00:00
// Add toolbar buttons
2015-12-28 15:01:53 +00:00
if ( General . Map . UDMF )
2014-12-03 23:15:26 +00:00
{
2016-04-04 22:20:49 +00:00
General . Interface . BeginToolbarUpdate ( ) ; //mxd
2014-04-09 10:16:33 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . CopyProperties ) ;
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . PasteProperties ) ;
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . PastePropertiesOptions ) ; //mxd
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . TextureOffsetLock , ToolbarSection . Geometry ) ; //mxd
2020-05-03 15:25:07 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . TextureOffset3DFloorLock , ToolbarSection . Geometry ) ;
2016-04-04 22:20:49 +00:00
General . Interface . EndToolbarUpdate ( ) ; //mxd
2014-04-09 10:16:33 +00:00
}
2009-04-19 18:07:22 +00:00
// Convert geometry selection to vertices only
General . Map . Map . ConvertSelection ( SelectionType . Vertices ) ;
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
// Mode disengages
public override void OnDisengage ( )
{
base . OnDisengage ( ) ;
2010-08-15 13:45:43 +00:00
// Remove toolbar buttons
2016-11-26 00:02:56 +00:00
General . Interface . BeginToolbarUpdate ( ) ;
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . CopyProperties ) ;
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . PasteProperties ) ;
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . PastePropertiesOptions ) ; //mxd
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . TextureOffsetLock ) ; //mxd
2020-05-03 15:25:07 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . TextureOffset3DFloorLock ) ;
2016-11-26 00:02:56 +00:00
General . Interface . EndToolbarUpdate ( ) ;
2014-04-09 10:16:33 +00:00
2009-04-19 18:07:22 +00:00
// Going to EditSelectionMode?
2016-03-18 12:52:12 +00:00
EditSelectionMode mode = General . Editing . NewMode as EditSelectionMode ;
if ( mode ! = null )
2009-04-19 18:07:22 +00:00
{
2009-08-19 11:42:20 +00:00
// Not pasting anything?
2016-03-18 12:52:12 +00:00
if ( ! mode . Pasting )
2009-04-19 18:07:22 +00:00
{
2009-08-19 11:42:20 +00:00
// No selection made? But we have a highlight!
if ( ( General . Map . Map . GetSelectedVertices ( true ) . Count = = 0 ) & & ( highlighted ! = null ) )
{
// Make the highlight the selection
highlighted . Selected = true ;
}
2009-04-19 18:07:22 +00:00
}
}
// Hide highlight info
General . Interface . HideInfo ( ) ;
}
// This redraws the display
public override void OnRedrawDisplay ( )
{
renderer . RedrawSurface ( ) ;
// Render lines and vertices
if ( renderer . StartPlotter ( true ) )
{
renderer . PlotLinedefSet ( General . Map . Map . Linedefs ) ;
renderer . PlotVerticesSet ( General . Map . Map . Vertices ) ;
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
renderer . PlotVertex ( highlighted , ColorCollection . HIGHLIGHT ) ;
renderer . Finish ( ) ;
}
// Render things
if ( renderer . StartThings ( true ) )
{
2016-03-30 11:29:39 +00:00
renderer . RenderThingSet ( General . Map . ThingsFilter . HiddenThings , General . Settings . HiddenThingsAlpha ) ;
2016-04-01 10:49:19 +00:00
renderer . RenderThingSet ( General . Map . ThingsFilter . VisibleThings , General . Settings . ActiveThingsAlpha ) ;
2009-04-19 18:07:22 +00:00
renderer . Finish ( ) ;
}
2014-01-08 09:46:57 +00:00
// Render selection
if ( selecting & & renderer . StartOverlay ( true ) )
2009-04-19 18:07:22 +00:00
{
2014-01-08 09:46:57 +00:00
RenderMultiSelection ( ) ;
renderer . Finish ( ) ;
2009-04-19 18:07:22 +00:00
}
renderer . Present ( ) ;
}
// This highlights a new item
2014-12-03 23:15:26 +00:00
private void Highlight ( Vertex v )
2009-04-19 18:07:22 +00:00
{
// Update display
if ( renderer . StartPlotter ( false ) )
{
// Undraw previous highlight
2013-05-27 12:20:15 +00:00
if ( highlighted ! = null & & ! highlighted . IsDisposed )
2009-04-19 18:07:22 +00:00
renderer . PlotVertex ( highlighted , renderer . DetermineVertexColor ( highlighted ) ) ;
// Set new highlight
highlighted = v ;
// Render highlighted item
2013-05-27 12:20:15 +00:00
if ( highlighted ! = null & & ! highlighted . IsDisposed )
2009-04-19 18:07:22 +00:00
renderer . PlotVertex ( highlighted , ColorCollection . HIGHLIGHT ) ;
// Done
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
// Show highlight info
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
General . Interface . ShowVertexInfo ( highlighted ) ;
else
General . Interface . HideInfo ( ) ;
}
// Selection
protected override void OnSelectBegin ( )
{
// Item highlighted?
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
// Redraw highlight to show selection
if ( renderer . StartPlotter ( false ) )
{
renderer . PlotVertex ( highlighted , renderer . DetermineVertexColor ( highlighted ) ) ;
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
base . OnSelectBegin ( ) ;
}
// End selection
protected override void OnSelectEnd ( )
{
// Not stopping from multiselection?
if ( ! selecting )
{
// Item highlighted?
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
2013-03-18 13:52:27 +00:00
//mxd. Flip selection
highlighted . Selected = ! highlighted . Selected ;
2009-04-19 18:07:22 +00:00
// Render highlighted item
if ( renderer . StartPlotter ( false ) )
{
renderer . PlotVertex ( highlighted , ColorCollection . HIGHLIGHT ) ;
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
2014-12-03 23:15:26 +00:00
}
else if ( BuilderPlug . Me . AutoClearSelection & & General . Map . Map . SelectedVerticessCount > 0 )
{
//mxd
2013-03-28 11:37:08 +00:00
General . Map . Map . ClearSelectedVertices ( ) ;
General . Interface . RedrawDisplay ( ) ;
2009-04-19 18:07:22 +00:00
}
2013-07-09 11:29:10 +00:00
//mxd
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ;
2009-04-19 18:07:22 +00:00
}
base . OnSelectEnd ( ) ;
}
// Start editing
protected override void OnEditBegin ( )
{
bool snaptogrid = General . Interface . ShiftState ^ General . Interface . SnapToGrid ;
bool snaptonearest = General . Interface . CtrlState ^ General . Interface . AutoMerge ;
// Vertex highlighted?
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
// Edit pressed in this mode
editpressed = true ;
// Highlighted item not selected?
2009-07-09 14:03:47 +00:00
if ( ! highlighted . Selected & & ( BuilderPlug . Me . AutoClearSelection | | ( General . Map . Map . SelectedVerticessCount = = 0 ) ) )
2009-04-19 18:07:22 +00:00
{
// Make this the only selection
2016-09-27 19:39:46 +00:00
selectionfromhighlight = true ; //mxd
2009-04-19 18:07:22 +00:00
General . Map . Map . ClearSelectedVertices ( ) ;
highlighted . Selected = true ;
2016-09-27 19:39:46 +00:00
UpdateSelectionInfo ( ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . RedrawDisplay ( ) ;
}
// Update display
if ( renderer . StartPlotter ( false ) )
{
// Redraw highlight to show selection
renderer . PlotVertex ( highlighted , renderer . DetermineVertexColor ( highlighted ) ) ;
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
2013-03-18 13:52:27 +00:00
else if ( ! selecting ) //mxd. We don't want to do this stuff while multiselecting
2009-04-19 18:07:22 +00:00
{
// Find the nearest linedef within highlight range
2009-05-20 15:03:08 +00:00
Linedef l = General . Map . Map . NearestLinedefRange ( mousemappos , BuilderPlug . Me . SplitLinedefsRange / renderer . Scale ) ;
2009-04-19 18:07:22 +00:00
if ( l ! = null )
{
// Create undo
General . Map . UndoRedo . CreateUndo ( "Split linedef" ) ;
Vector2D insertpos ;
// Snip to grid also?
if ( snaptogrid )
{
// Find all points where the grid intersects the line
List < Vector2D > points = l . GetGridIntersections ( ) ;
insertpos = mousemappos ;
2020-05-21 12:20:02 +00:00
double distance = double . MaxValue ;
2009-04-19 18:07:22 +00:00
foreach ( Vector2D p in points )
{
2020-05-21 12:20:02 +00:00
double pdist = Vector2D . DistanceSq ( p , mousemappos ) ;
2009-04-19 18:07:22 +00:00
if ( pdist < distance )
{
insertpos = p ;
distance = pdist ;
}
}
}
else
{
// Just use the nearest point on line
insertpos = l . NearestOnLine ( mousemappos ) ;
}
// Make the vertex
Vertex v = General . Map . Map . CreateVertex ( insertpos ) ;
2010-08-15 19:43:00 +00:00
if ( v = = null )
{
General . Map . UndoRedo . WithdrawUndo ( ) ;
return ;
}
2009-04-19 18:07:22 +00:00
// Snap to map format accuracy
v . SnapToAccuracy ( ) ;
// Split the line with this vertex
2010-08-15 19:43:00 +00:00
Linedef sld = l . Split ( v ) ;
if ( sld = = null )
{
General . Map . UndoRedo . WithdrawUndo ( ) ;
return ;
}
2014-03-19 13:03:47 +00:00
//BuilderPlug.Me.AdjustSplitCoordinates(l, sld);
2009-04-19 18:07:22 +00:00
// Update
General . Map . Map . Update ( ) ;
2010-08-15 19:43:00 +00:00
2009-04-19 18:07:22 +00:00
// Highlight it
Highlight ( v ) ;
// Redraw display
General . Interface . RedrawDisplay ( ) ;
}
2013-12-05 09:24:55 +00:00
else if ( BuilderPlug . Me . AutoDrawOnEdit )
2009-04-19 18:07:22 +00:00
{
// Start drawing mode
DrawGeometryMode drawmode = new DrawGeometryMode ( ) ;
2016-04-21 21:00:58 +00:00
DrawnVertex v = DrawGeometryMode . GetCurrentPosition ( mousemappos , snaptonearest , snaptogrid , false , false , renderer , new List < DrawnVertex > ( ) ) ;
2010-08-13 18:32:21 +00:00
2015-12-28 15:01:53 +00:00
if ( drawmode . DrawPointAt ( v ) )
2010-08-13 18:32:21 +00:00
General . Editing . ChangeMode ( drawmode ) ;
else
General . Interface . DisplayStatus ( StatusType . Warning , "Failed to draw point: outside of map boundaries." ) ;
2009-04-19 18:07:22 +00:00
}
}
base . OnEditBegin ( ) ;
}
// Done editing
protected override void OnEditEnd ( )
{
// Edit pressed in this mode?
if ( editpressed )
{
// Anything selected?
ICollection < Vertex > selected = General . Map . Map . GetSelectedVertices ( true ) ;
if ( selected . Count > 0 )
{
if ( General . Interface . IsActiveWindow )
{
2013-07-08 13:13:28 +00:00
//mxd. Show realtime vertex edit dialog
2014-02-21 14:42:12 +00:00
General . Interface . OnEditFormValuesChanged + = vertexEditForm_OnValuesChanged ;
2013-11-29 12:24:47 +00:00
DialogResult result = General . Interface . ShowEditVertices ( selected ) ;
2013-07-10 09:57:30 +00:00
General . Interface . OnEditFormValuesChanged - = vertexEditForm_OnValuesChanged ;
2009-04-19 18:07:22 +00:00
// When a single vertex was selected, deselect it now
2016-09-27 19:39:46 +00:00
if ( selected . Count = = 1 & & selectionfromhighlight )
2014-12-03 23:15:26 +00:00
{
2013-07-19 15:30:58 +00:00
General . Map . Map . ClearSelectedVertices ( ) ;
2014-12-03 23:15:26 +00:00
}
else if ( result = = DialogResult . Cancel ) //mxd. Restore selection...
{
2015-12-28 15:01:53 +00:00
foreach ( Vertex v in selected ) v . Selected = true ;
2013-07-19 15:30:58 +00:00
}
2016-09-27 19:39:46 +00:00
// Update entire display
UpdateSelectionInfo ( ) ; //mxd
2013-11-29 12:24:47 +00:00
General . Interface . RedrawDisplay ( ) ;
2009-04-19 18:07:22 +00:00
}
}
}
editpressed = false ;
2016-09-27 19:39:46 +00:00
selectionfromhighlight = false ; //mxd
2009-04-19 18:07:22 +00:00
base . OnEditEnd ( ) ;
}
2013-07-08 13:13:28 +00:00
//mxd
2014-12-03 23:15:26 +00:00
private void vertexEditForm_OnValuesChanged ( object sender , EventArgs e )
{
2013-07-08 13:13:28 +00:00
// Update entire display
General . Map . Map . Update ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
2009-04-19 18:07:22 +00:00
// Mouse moves
public override void OnMouseMove ( MouseEventArgs e )
{
base . OnMouseMove ( e ) ;
2014-01-08 09:46:57 +00:00
if ( panning ) return ; //mxd. Skip all this jazz while panning
2009-04-19 18:07:22 +00:00
2013-03-18 13:52:27 +00:00
//mxd
2014-12-03 23:15:26 +00:00
if ( selectpressed & & ! editpressed & & ! selecting )
{
2013-03-18 13:52:27 +00:00
// Check if moved enough pixels for multiselect
Vector2D delta = mousedownpos - mousepos ;
2017-08-24 13:24:03 +00:00
if ( ( Math . Abs ( delta . x ) > BuilderPlug . Me . MouseSelectionThreshold ) | |
( Math . Abs ( delta . y ) > BuilderPlug . Me . MouseSelectionThreshold ) )
2014-12-03 23:15:26 +00:00
{
2013-03-18 13:52:27 +00:00
// Start multiselecting
StartMultiSelection ( ) ;
}
}
2013-03-28 12:31:37 +00:00
else if ( paintselectpressed & & ! editpressed & & ! selecting ) //mxd. Drag-select
2013-03-18 13:52:27 +00:00
{
// Find the nearest thing within highlight range
Vertex v = General . Map . Map . NearestVertexSquareRange ( mousemappos , BuilderPlug . Me . HighlightRange / renderer . Scale ) ;
2014-12-03 23:15:26 +00:00
if ( v ! = null )
{
if ( v ! = highlighted )
{
2013-03-18 13:52:27 +00:00
//toggle selected state
2019-06-20 13:38:41 +00:00
if ( General . Interface . ShiftState ^ BuilderPlug . Me . AdditivePaintSelect )
2013-03-18 13:52:27 +00:00
v . Selected = true ;
else if ( General . Interface . CtrlState )
v . Selected = false ;
else
v . Selected = ! v . Selected ;
highlighted = v ;
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ; //mxd
2013-07-09 11:29:10 +00:00
2013-03-18 13:52:27 +00:00
// Update entire display
General . Interface . RedrawDisplay ( ) ;
}
2014-12-03 23:15:26 +00:00
}
else if ( highlighted ! = null )
{
2013-03-18 13:52:27 +00:00
highlighted = null ;
Highlight ( null ) ;
// Update entire display
General . Interface . RedrawDisplay ( ) ;
}
}
else if ( e . Button = = MouseButtons . None ) // Not holding any buttons?
2009-04-19 18:07:22 +00:00
{
2014-01-08 09:46:57 +00:00
//mxd. Render insert vertex preview
2013-04-16 12:52:40 +00:00
Linedef l = General . Map . Map . NearestLinedefRange ( mousemappos , BuilderPlug . Me . SplitLinedefsRange / renderer . Scale ) ;
2014-12-03 23:15:26 +00:00
if ( l ! = null )
{
2014-01-08 09:46:57 +00:00
// Snip to grid?
2014-12-03 23:15:26 +00:00
if ( General . Interface . ShiftState ^ General . Interface . SnapToGrid )
{
2014-01-08 09:46:57 +00:00
// Find all points where the grid intersects the line
List < Vector2D > points = l . GetGridIntersections ( ) ;
2014-12-03 23:15:26 +00:00
if ( points . Count = = 0 )
{
2015-08-04 23:28:02 +00:00
insertpreview = l . NearestOnLine ( mousemappos ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2015-08-04 23:28:02 +00:00
insertpreview = mousemappos ;
2020-05-21 12:20:02 +00:00
double distance = double . MaxValue ;
2014-12-03 23:15:26 +00:00
foreach ( Vector2D p in points )
{
2020-05-21 12:20:02 +00:00
double pdist = Vector2D . DistanceSq ( p , mousemappos ) ;
2014-12-03 23:15:26 +00:00
if ( pdist < distance )
{
2015-08-04 23:28:02 +00:00
insertpreview = p ;
2014-01-08 09:46:57 +00:00
distance = pdist ;
}
}
}
2014-12-03 23:15:26 +00:00
}
else
{
2014-01-08 09:46:57 +00:00
// Just use the nearest point on line
2015-08-04 23:28:02 +00:00
insertpreview = l . NearestOnLine ( mousemappos ) ;
2014-01-08 09:46:57 +00:00
}
//render preview
2014-12-03 23:15:26 +00:00
if ( renderer . StartOverlay ( true ) )
{
2020-05-21 12:20:02 +00:00
double dist = Math . Min ( Vector2D . Distance ( mousemappos , insertpreview ) , BuilderPlug . Me . SplitLinedefsRange ) ;
2014-01-10 15:08:39 +00:00
byte alpha = ( byte ) ( 255 - ( dist / BuilderPlug . Me . SplitLinedefsRange ) * 128 ) ;
2014-01-08 09:46:57 +00:00
float vsize = ( renderer . VertexSize + 1.0f ) / renderer . Scale ;
2020-05-21 12:20:02 +00:00
renderer . RenderRectangleFilled ( new RectangleF ( ( float ) ( insertpreview . x - vsize ) , ( float ) ( insertpreview . y - vsize ) , vsize * 2.0f , vsize * 2.0f ) , General . Colors . InfoLine . WithAlpha ( alpha ) , true ) ;
2014-01-08 09:46:57 +00:00
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
2014-12-03 23:15:26 +00:00
}
2015-08-04 23:28:02 +00:00
else if ( insertpreview . IsFinite ( ) )
2014-12-03 23:15:26 +00:00
{
2015-08-04 23:28:02 +00:00
insertpreview . x = float . NaN ;
2014-01-08 09:46:57 +00:00
//undraw preveiw
2014-12-03 23:15:26 +00:00
if ( renderer . StartOverlay ( true ) )
{
2014-01-08 09:46:57 +00:00
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
2013-05-27 12:20:15 +00:00
// Find the nearest vertex within highlight range
Vertex v = General . Map . Map . NearestVertexSquareRange ( mousemappos , BuilderPlug . Me . HighlightRange / renderer . Scale ) ;
// Highlight if not the same
if ( v ! = highlighted ) Highlight ( v ) ;
2013-03-18 13:52:27 +00:00
}
2009-04-19 18:07:22 +00:00
}
// Mouse leaves
public override void OnMouseLeave ( EventArgs e )
{
base . OnMouseLeave ( e ) ;
// Highlight nothing
Highlight ( null ) ;
}
2014-01-08 09:46:57 +00:00
//mxd
2014-12-03 23:15:26 +00:00
protected override void BeginViewPan ( )
{
2015-12-28 15:01:53 +00:00
if ( insertpreview . IsFinite ( ) )
2014-12-03 23:15:26 +00:00
{
2015-08-04 23:28:02 +00:00
insertpreview . x = float . NaN ;
2014-01-08 09:46:57 +00:00
//undraw preveiw
2015-12-28 15:01:53 +00:00
if ( renderer . StartOverlay ( true ) )
2014-12-03 23:15:26 +00:00
{
2014-01-08 09:46:57 +00:00
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
base . BeginViewPan ( ) ;
}
2013-03-18 13:52:27 +00:00
//mxd
2014-12-03 23:15:26 +00:00
protected override void OnPaintSelectBegin ( )
{
2013-03-18 13:52:27 +00:00
highlighted = null ;
base . OnPaintSelectBegin ( ) ;
}
2009-04-19 18:07:22 +00:00
// Mouse wants to drag
protected override void OnDragStart ( MouseEventArgs e )
{
base . OnDragStart ( e ) ;
// Edit button used?
if ( General . Actions . CheckActionActive ( null , "classicedit" ) )
{
// Anything highlighted?
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
// Highlighted item not selected?
if ( ! highlighted . Selected )
{
// Select only this vertex for dragging
General . Map . Map . ClearSelectedVertices ( ) ;
highlighted . Selected = true ;
}
// Start dragging the selection
2014-12-03 23:15:26 +00:00
if ( ! BuilderPlug . Me . DontMoveGeometryOutsideMapBoundary | | CanDrag ( ) ) //mxd
2016-04-25 14:48:39 +00:00
General . Editing . ChangeMode ( new DragVerticesMode ( mousedownmappos ) ) ;
2013-03-18 13:52:27 +00:00
}
}
}
//mxd. Check if any selected vertex is outside of map boundary
2014-12-03 23:15:26 +00:00
private static bool CanDrag ( )
2014-05-20 09:09:28 +00:00
{
2013-03-18 13:52:27 +00:00
ICollection < Vertex > selectedverts = General . Map . Map . GetSelectedVertices ( true ) ;
int unaffectedCount = 0 ;
2014-12-03 23:15:26 +00:00
foreach ( Vertex v in selectedverts )
{
2013-03-18 13:52:27 +00:00
// Make sure the vertex is inside the map boundary
if ( v . Position . x < General . Map . Config . LeftBoundary | | v . Position . x > General . Map . Config . RightBoundary
2014-12-03 23:15:26 +00:00
| | v . Position . y > General . Map . Config . TopBoundary | | v . Position . y < General . Map . Config . BottomBoundary )
{
2013-03-18 13:52:27 +00:00
v . Selected = false ;
unaffectedCount + + ;
2009-04-19 18:07:22 +00:00
}
}
2013-03-18 13:52:27 +00:00
2014-12-03 23:15:26 +00:00
if ( unaffectedCount = = selectedverts . Count )
{
2013-03-18 13:52:27 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "Unable to drag selection: " + ( selectedverts . Count = = 1 ? "selected vertex is" : "all of selected vertices are" ) + " outside of map boundary!" ) ;
General . Interface . RedrawDisplay ( ) ;
return false ;
}
if ( unaffectedCount > 0 )
General . Interface . DisplayStatus ( StatusType . Warning , unaffectedCount + " of selected vertices " + ( unaffectedCount = = 1 ? "is" : "are" ) + " outside of map boundary!" ) ;
return true ;
2009-04-19 18:07:22 +00:00
}
// This is called wheh selection ends
protected override void OnEndMultiSelection ( )
{
2013-12-20 09:24:43 +00:00
bool selectionvolume = ( ( Math . Abs ( selectionrect . Width ) > 0.1f ) & & ( Math . Abs ( selectionrect . Height ) > 0.1f ) ) ;
2009-08-19 11:09:10 +00:00
if ( selectionvolume )
2009-04-19 18:07:22 +00:00
{
2013-03-18 13:52:27 +00:00
//mxd
2014-12-03 23:15:26 +00:00
switch ( marqueSelectionMode )
{
2013-12-20 09:24:43 +00:00
case MarqueSelectionMode . SELECT :
foreach ( Vertex v in General . Map . Map . Vertices )
2020-05-21 12:20:02 +00:00
v . Selected = selectionrect . Contains ( ( float ) v . Position . x , ( float ) v . Position . y ) ;
2013-12-20 09:24:43 +00:00
break ;
case MarqueSelectionMode . ADD :
foreach ( Vertex v in General . Map . Map . Vertices )
2020-05-21 12:20:02 +00:00
v . Selected | = selectionrect . Contains ( ( float ) v . Position . x , ( float ) v . Position . y ) ;
2013-12-20 09:24:43 +00:00
break ;
case MarqueSelectionMode . SUBTRACT :
foreach ( Vertex v in General . Map . Map . Vertices )
2020-05-21 12:20:02 +00:00
if ( selectionrect . Contains ( ( float ) v . Position . x , ( float ) v . Position . y ) ) v . Selected = false ;
2013-12-20 09:24:43 +00:00
break ;
default : //should be Intersect
foreach ( Vertex v in General . Map . Map . Vertices )
2020-05-21 12:20:02 +00:00
if ( ! selectionrect . Contains ( ( float ) v . Position . x , ( float ) v . Position . y ) ) v . Selected = false ;
2013-12-20 09:24:43 +00:00
break ;
2009-04-19 18:07:22 +00:00
}
2013-07-09 11:29:10 +00:00
//mxd
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ;
2009-04-19 18:07:22 +00:00
}
base . OnEndMultiSelection ( ) ;
// Clear overlay
if ( renderer . StartOverlay ( true ) ) renderer . Finish ( ) ;
// Redraw
General . Interface . RedrawDisplay ( ) ;
}
// This is called when the selection is updated
protected override void OnUpdateMultiSelection ( )
{
base . OnUpdateMultiSelection ( ) ;
// Render selection
if ( renderer . StartOverlay ( true ) )
{
RenderMultiSelection ( ) ;
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
// When copying
public override bool OnCopyBegin ( )
{
// No selection made? But we have a highlight!
if ( ( General . Map . Map . GetSelectedVertices ( true ) . Count = = 0 ) & & ( highlighted ! = null ) )
{
// Make the highlight the selection
highlighted . Selected = true ;
2015-04-16 13:03:12 +00:00
//mxd. Actually, we want it marked, not selected
bool result = base . OnCopyBegin ( ) ;
highlighted . Selected = false ;
return result ;
2009-04-19 18:07:22 +00:00
}
return base . OnCopyBegin ( ) ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Actions
2010-08-15 13:45:43 +00:00
// This copies the properties
[BeginAction("classiccopyproperties")]
public void CopyProperties ( )
{
// Determine source vertices
ICollection < Vertex > sel = null ;
Removed "Paste Properties Options" action.
Added "Paste Properties Special" actions in "Classic" and "Visual" categories. They work the same way as "Paste Special" action.
Added: "Copy Properties", "Paste Properties" and "Paste Properties Special" options are now shown in the Edit menu if current classic mode supports them.
Changed, Paste Properties Special window: only options relevant to current map format are now displayed.
Changed, Paste Properties Special window, UDMF: all UI-managed options are now available.
Fixed: MAPINFO parser was unable to process "include" directives.
Fixed, General interface: selection info was reset to "Nothing selected" after few seconds regardless of current selection.
Fixed, Visual mode: thing bounding boxes were not updated when changing things positions using Randomize mode.
Fixed, Visual mode: event lines were displayed at incorrect height when entering Visual mode for the first time.
Fixed, Texture Browser window: when MixTexturesFlats Game Configuration option is disabled, textures/flats are no longer shown in the Used group when flats/textures with the same names are used in the map.
Fixed(?): probably fixed an exception some users reported when trying to initialize a Classic mode after switching from Visual mode with "Sync cameras" option enabled.
Changed, Game configurations, Thing Categories: a block must have at least one thing category property to be recognized as a thing category.
Changed, Visplane Explorer: the plugin now outputs more info when it fails to initialize vpo.dll.
Cosmetic, Thing Edit window, Doom/Hexen map format: adjusted UI layout so thing flags control no longer displays scrollbars in Hexen map format.
Internal: merged methods from UDMFTools into UniFields, removed UDMFTools.
Updated Inno Setup script (added VC++ 2008 SP1 distributive).
Updated ZDoom_DECORATE.cfg (A_CheckBlock).
Updated documentation (added "System Requirements" page).
2015-10-09 12:38:12 +00:00
if ( General . Map . Map . SelectedVerticessCount > 0 ) sel = General . Map . Map . GetSelectedVertices ( true ) ;
else if ( highlighted ! = null ) sel = new List < Vertex > { highlighted } ;
2010-08-15 13:45:43 +00:00
if ( sel ! = null )
{
// Copy properties from first source vertex
BuilderPlug . Me . CopiedVertexProps = new VertexProperties ( General . GetByIndex ( sel , 0 ) ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Copied vertex properties." ) ;
}
Removed "Paste Properties Options" action.
Added "Paste Properties Special" actions in "Classic" and "Visual" categories. They work the same way as "Paste Special" action.
Added: "Copy Properties", "Paste Properties" and "Paste Properties Special" options are now shown in the Edit menu if current classic mode supports them.
Changed, Paste Properties Special window: only options relevant to current map format are now displayed.
Changed, Paste Properties Special window, UDMF: all UI-managed options are now available.
Fixed: MAPINFO parser was unable to process "include" directives.
Fixed, General interface: selection info was reset to "Nothing selected" after few seconds regardless of current selection.
Fixed, Visual mode: thing bounding boxes were not updated when changing things positions using Randomize mode.
Fixed, Visual mode: event lines were displayed at incorrect height when entering Visual mode for the first time.
Fixed, Texture Browser window: when MixTexturesFlats Game Configuration option is disabled, textures/flats are no longer shown in the Used group when flats/textures with the same names are used in the map.
Fixed(?): probably fixed an exception some users reported when trying to initialize a Classic mode after switching from Visual mode with "Sync cameras" option enabled.
Changed, Game configurations, Thing Categories: a block must have at least one thing category property to be recognized as a thing category.
Changed, Visplane Explorer: the plugin now outputs more info when it fails to initialize vpo.dll.
Cosmetic, Thing Edit window, Doom/Hexen map format: adjusted UI layout so thing flags control no longer displays scrollbars in Hexen map format.
Internal: merged methods from UDMFTools into UniFields, removed UDMFTools.
Updated Inno Setup script (added VC++ 2008 SP1 distributive).
Updated ZDoom_DECORATE.cfg (A_CheckBlock).
Updated documentation (added "System Requirements" page).
2015-10-09 12:38:12 +00:00
else
{
//mxd
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires highlight or selection!" ) ;
}
2010-08-15 13:45:43 +00:00
}
// This pastes the properties
[BeginAction("classicpasteproperties")]
public void PasteProperties ( )
{
if ( BuilderPlug . Me . CopiedVertexProps ! = null )
{
// Determine target vertices
ICollection < Vertex > sel = null ;
Removed "Paste Properties Options" action.
Added "Paste Properties Special" actions in "Classic" and "Visual" categories. They work the same way as "Paste Special" action.
Added: "Copy Properties", "Paste Properties" and "Paste Properties Special" options are now shown in the Edit menu if current classic mode supports them.
Changed, Paste Properties Special window: only options relevant to current map format are now displayed.
Changed, Paste Properties Special window, UDMF: all UI-managed options are now available.
Fixed: MAPINFO parser was unable to process "include" directives.
Fixed, General interface: selection info was reset to "Nothing selected" after few seconds regardless of current selection.
Fixed, Visual mode: thing bounding boxes were not updated when changing things positions using Randomize mode.
Fixed, Visual mode: event lines were displayed at incorrect height when entering Visual mode for the first time.
Fixed, Texture Browser window: when MixTexturesFlats Game Configuration option is disabled, textures/flats are no longer shown in the Used group when flats/textures with the same names are used in the map.
Fixed(?): probably fixed an exception some users reported when trying to initialize a Classic mode after switching from Visual mode with "Sync cameras" option enabled.
Changed, Game configurations, Thing Categories: a block must have at least one thing category property to be recognized as a thing category.
Changed, Visplane Explorer: the plugin now outputs more info when it fails to initialize vpo.dll.
Cosmetic, Thing Edit window, Doom/Hexen map format: adjusted UI layout so thing flags control no longer displays scrollbars in Hexen map format.
Internal: merged methods from UDMFTools into UniFields, removed UDMFTools.
Updated Inno Setup script (added VC++ 2008 SP1 distributive).
Updated ZDoom_DECORATE.cfg (A_CheckBlock).
Updated documentation (added "System Requirements" page).
2015-10-09 12:38:12 +00:00
if ( General . Map . Map . SelectedVerticessCount > 0 ) sel = General . Map . Map . GetSelectedVertices ( true ) ;
else if ( highlighted ! = null ) sel = new List < Vertex > { highlighted } ;
2010-08-15 13:45:43 +00:00
if ( sel ! = null )
{
// Apply properties to selection
Removed "Paste Properties Options" action.
Added "Paste Properties Special" actions in "Classic" and "Visual" categories. They work the same way as "Paste Special" action.
Added: "Copy Properties", "Paste Properties" and "Paste Properties Special" options are now shown in the Edit menu if current classic mode supports them.
Changed, Paste Properties Special window: only options relevant to current map format are now displayed.
Changed, Paste Properties Special window, UDMF: all UI-managed options are now available.
Fixed: MAPINFO parser was unable to process "include" directives.
Fixed, General interface: selection info was reset to "Nothing selected" after few seconds regardless of current selection.
Fixed, Visual mode: thing bounding boxes were not updated when changing things positions using Randomize mode.
Fixed, Visual mode: event lines were displayed at incorrect height when entering Visual mode for the first time.
Fixed, Texture Browser window: when MixTexturesFlats Game Configuration option is disabled, textures/flats are no longer shown in the Used group when flats/textures with the same names are used in the map.
Fixed(?): probably fixed an exception some users reported when trying to initialize a Classic mode after switching from Visual mode with "Sync cameras" option enabled.
Changed, Game configurations, Thing Categories: a block must have at least one thing category property to be recognized as a thing category.
Changed, Visplane Explorer: the plugin now outputs more info when it fails to initialize vpo.dll.
Cosmetic, Thing Edit window, Doom/Hexen map format: adjusted UI layout so thing flags control no longer displays scrollbars in Hexen map format.
Internal: merged methods from UDMFTools into UniFields, removed UDMFTools.
Updated Inno Setup script (added VC++ 2008 SP1 distributive).
Updated ZDoom_DECORATE.cfg (A_CheckBlock).
Updated documentation (added "System Requirements" page).
2015-10-09 12:38:12 +00:00
string rest = ( sel . Count = = 1 ? "a single vertex" : sel . Count + " vertices" ) ; //mxd
General . Map . UndoRedo . CreateUndo ( "Paste properties to " + rest ) ;
2016-10-11 12:58:35 +00:00
BuilderPlug . Me . CopiedVertexProps . Apply ( sel , false ) ;
Removed "Paste Properties Options" action.
Added "Paste Properties Special" actions in "Classic" and "Visual" categories. They work the same way as "Paste Special" action.
Added: "Copy Properties", "Paste Properties" and "Paste Properties Special" options are now shown in the Edit menu if current classic mode supports them.
Changed, Paste Properties Special window: only options relevant to current map format are now displayed.
Changed, Paste Properties Special window, UDMF: all UI-managed options are now available.
Fixed: MAPINFO parser was unable to process "include" directives.
Fixed, General interface: selection info was reset to "Nothing selected" after few seconds regardless of current selection.
Fixed, Visual mode: thing bounding boxes were not updated when changing things positions using Randomize mode.
Fixed, Visual mode: event lines were displayed at incorrect height when entering Visual mode for the first time.
Fixed, Texture Browser window: when MixTexturesFlats Game Configuration option is disabled, textures/flats are no longer shown in the Used group when flats/textures with the same names are used in the map.
Fixed(?): probably fixed an exception some users reported when trying to initialize a Classic mode after switching from Visual mode with "Sync cameras" option enabled.
Changed, Game configurations, Thing Categories: a block must have at least one thing category property to be recognized as a thing category.
Changed, Visplane Explorer: the plugin now outputs more info when it fails to initialize vpo.dll.
Cosmetic, Thing Edit window, Doom/Hexen map format: adjusted UI layout so thing flags control no longer displays scrollbars in Hexen map format.
Internal: merged methods from UDMFTools into UniFields, removed UDMFTools.
Updated Inno Setup script (added VC++ 2008 SP1 distributive).
Updated ZDoom_DECORATE.cfg (A_CheckBlock).
Updated documentation (added "System Requirements" page).
2015-10-09 12:38:12 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Pasted properties to " + rest + "." ) ;
2010-08-15 13:45:43 +00:00
// Update and redraw
General . Map . IsChanged = true ;
General . Interface . RefreshInfo ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
Removed "Paste Properties Options" action.
Added "Paste Properties Special" actions in "Classic" and "Visual" categories. They work the same way as "Paste Special" action.
Added: "Copy Properties", "Paste Properties" and "Paste Properties Special" options are now shown in the Edit menu if current classic mode supports them.
Changed, Paste Properties Special window: only options relevant to current map format are now displayed.
Changed, Paste Properties Special window, UDMF: all UI-managed options are now available.
Fixed: MAPINFO parser was unable to process "include" directives.
Fixed, General interface: selection info was reset to "Nothing selected" after few seconds regardless of current selection.
Fixed, Visual mode: thing bounding boxes were not updated when changing things positions using Randomize mode.
Fixed, Visual mode: event lines were displayed at incorrect height when entering Visual mode for the first time.
Fixed, Texture Browser window: when MixTexturesFlats Game Configuration option is disabled, textures/flats are no longer shown in the Used group when flats/textures with the same names are used in the map.
Fixed(?): probably fixed an exception some users reported when trying to initialize a Classic mode after switching from Visual mode with "Sync cameras" option enabled.
Changed, Game configurations, Thing Categories: a block must have at least one thing category property to be recognized as a thing category.
Changed, Visplane Explorer: the plugin now outputs more info when it fails to initialize vpo.dll.
Cosmetic, Thing Edit window, Doom/Hexen map format: adjusted UI layout so thing flags control no longer displays scrollbars in Hexen map format.
Internal: merged methods from UDMFTools into UniFields, removed UDMFTools.
Updated Inno Setup script (added VC++ 2008 SP1 distributive).
Updated ZDoom_DECORATE.cfg (A_CheckBlock).
Updated documentation (added "System Requirements" page).
2015-10-09 12:38:12 +00:00
else
{
//mxd
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires highlight or selection!" ) ;
}
}
else
{
//mxd
General . Interface . DisplayStatus ( StatusType . Warning , "Copy vertex properties first!" ) ;
}
}
//mxd. This pastes the properties with options
[BeginAction("classicpastepropertieswithoptions")]
public void PastePropertiesWithOptions ( )
{
if ( BuilderPlug . Me . CopiedVertexProps ! = null )
{
// Determine target vertices
ICollection < Vertex > sel = null ;
if ( General . Map . Map . SelectedVerticessCount > 0 ) sel = General . Map . Map . GetSelectedVertices ( true ) ;
else if ( highlighted ! = null ) sel = new List < Vertex > { highlighted } ;
if ( sel ! = null )
{
PastePropertiesOptionsForm form = new PastePropertiesOptionsForm ( ) ;
Game Configurations: added Vanilla Strife, Vanilla Heretic and Vanilla Hexen game configurations.
Added "makedoorceil" game configuration property. Works the same way as "makedoortrack" and "makedoordoor", but for ceilings of door sectors.
Changed, Game configurations: the editor no longer tries to load DECORATE/MODELDEF/VOXELDEF/GLDEFS/REVERBS lumps when "decorategames" setting is not specified / is set to empty string.
Changed, General interface: "Tools -> Reload MODELDEF/VOXELDEF" and "Tools -> Reload GLDEFS" menu items are no longer shown when current game configuration doesn't support DECORATE.
Fixed a crash when pasting linedef/thing properties in Hexen map format.
Fixed, Visual mode: Visual Thing resources were not fully unloaded when resetting D3D device leading to crash when switching to the editor from a DX-using game engine (like ZDoom) running in fullscreen.
Fixed: in some cases, when current game configuration supported multiple script compilers, it was possible to open/create a map or change map options without selecting any script compiler.
Fixed, New Map Options window: default map name was not updated when switching game configurations.
Fixed: copied map element properties were not reset after switching to another map.
Fixed: stored textures for "Make Door" action were not reset after switching to another map.
Fixed, Game Configurations window: currently selected test engine name was not updated when pasting test engines from another configuration.
Fixed, Game Configurations: all "Heretic in Doom map format" configurations were using Doom sector effects list.
Fixed, Game Configurations: all "Strife in Doom map format" configurations were using Doom sector effects list.
2015-10-21 13:35:42 +00:00
if ( form . Setup ( MapElementType . VERTEX ) & & form . ShowDialog ( General . Interface ) = = DialogResult . OK )
Removed "Paste Properties Options" action.
Added "Paste Properties Special" actions in "Classic" and "Visual" categories. They work the same way as "Paste Special" action.
Added: "Copy Properties", "Paste Properties" and "Paste Properties Special" options are now shown in the Edit menu if current classic mode supports them.
Changed, Paste Properties Special window: only options relevant to current map format are now displayed.
Changed, Paste Properties Special window, UDMF: all UI-managed options are now available.
Fixed: MAPINFO parser was unable to process "include" directives.
Fixed, General interface: selection info was reset to "Nothing selected" after few seconds regardless of current selection.
Fixed, Visual mode: thing bounding boxes were not updated when changing things positions using Randomize mode.
Fixed, Visual mode: event lines were displayed at incorrect height when entering Visual mode for the first time.
Fixed, Texture Browser window: when MixTexturesFlats Game Configuration option is disabled, textures/flats are no longer shown in the Used group when flats/textures with the same names are used in the map.
Fixed(?): probably fixed an exception some users reported when trying to initialize a Classic mode after switching from Visual mode with "Sync cameras" option enabled.
Changed, Game configurations, Thing Categories: a block must have at least one thing category property to be recognized as a thing category.
Changed, Visplane Explorer: the plugin now outputs more info when it fails to initialize vpo.dll.
Cosmetic, Thing Edit window, Doom/Hexen map format: adjusted UI layout so thing flags control no longer displays scrollbars in Hexen map format.
Internal: merged methods from UDMFTools into UniFields, removed UDMFTools.
Updated Inno Setup script (added VC++ 2008 SP1 distributive).
Updated ZDoom_DECORATE.cfg (A_CheckBlock).
Updated documentation (added "System Requirements" page).
2015-10-09 12:38:12 +00:00
{
// Apply properties to selection
string rest = ( sel . Count = = 1 ? "a single vertex" : sel . Count + " vertices" ) ;
General . Map . UndoRedo . CreateUndo ( "Paste properties with options to " + rest ) ;
2016-10-11 12:58:35 +00:00
BuilderPlug . Me . CopiedVertexProps . Apply ( sel , true ) ;
Removed "Paste Properties Options" action.
Added "Paste Properties Special" actions in "Classic" and "Visual" categories. They work the same way as "Paste Special" action.
Added: "Copy Properties", "Paste Properties" and "Paste Properties Special" options are now shown in the Edit menu if current classic mode supports them.
Changed, Paste Properties Special window: only options relevant to current map format are now displayed.
Changed, Paste Properties Special window, UDMF: all UI-managed options are now available.
Fixed: MAPINFO parser was unable to process "include" directives.
Fixed, General interface: selection info was reset to "Nothing selected" after few seconds regardless of current selection.
Fixed, Visual mode: thing bounding boxes were not updated when changing things positions using Randomize mode.
Fixed, Visual mode: event lines were displayed at incorrect height when entering Visual mode for the first time.
Fixed, Texture Browser window: when MixTexturesFlats Game Configuration option is disabled, textures/flats are no longer shown in the Used group when flats/textures with the same names are used in the map.
Fixed(?): probably fixed an exception some users reported when trying to initialize a Classic mode after switching from Visual mode with "Sync cameras" option enabled.
Changed, Game configurations, Thing Categories: a block must have at least one thing category property to be recognized as a thing category.
Changed, Visplane Explorer: the plugin now outputs more info when it fails to initialize vpo.dll.
Cosmetic, Thing Edit window, Doom/Hexen map format: adjusted UI layout so thing flags control no longer displays scrollbars in Hexen map format.
Internal: merged methods from UDMFTools into UniFields, removed UDMFTools.
Updated Inno Setup script (added VC++ 2008 SP1 distributive).
Updated ZDoom_DECORATE.cfg (A_CheckBlock).
Updated documentation (added "System Requirements" page).
2015-10-09 12:38:12 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Pasted properties with options to " + rest + "." ) ;
// Update and redraw
General . Map . IsChanged = true ;
General . Interface . RefreshInfo ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
}
else
{
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires highlight or selection!" ) ;
}
}
else
{
General . Interface . DisplayStatus ( StatusType . Warning , "Copy vertex properties first!" ) ;
2010-08-15 13:45:43 +00:00
}
}
2009-04-19 18:07:22 +00:00
// This clears the selection
[BeginAction("clearselection", BaseAction = true)]
public void ClearSelection ( )
{
// Clear selection
General . Map . Map . ClearAllSelected ( ) ;
2013-12-12 09:07:30 +00:00
//mxd. Clear selection info
2013-07-09 11:29:10 +00:00
General . Interface . DisplayStatus ( StatusType . Selection , string . Empty ) ;
2009-04-19 18:07:22 +00:00
// Redraw
General . Interface . RedrawDisplay ( ) ;
}
// This creates a new vertex at the mouse position
[BeginAction("insertitem", BaseAction = true)]
2016-03-30 11:29:39 +00:00
private void InsertVertex ( )
2009-04-19 18:07:22 +00:00
{
bool snaptogrid = General . Interface . ShiftState ^ General . Interface . SnapToGrid ;
bool snaptonearest = General . Interface . CtrlState ^ General . Interface . AutoMerge ;
// Mouse in window?
if ( General . Interface . MouseInDisplay )
{
Vector2D insertpos ;
2014-02-21 14:42:12 +00:00
2009-04-19 18:07:22 +00:00
// Create undo
General . Map . UndoRedo . CreateUndo ( "Insert vertex" ) ;
// Snap to geometry?
2016-03-30 11:29:39 +00:00
Linedef l = General . Map . Map . NearestLinedefRange ( mousemappos , BuilderPlug . Me . SplitLinedefsRange / renderer . Scale ) ;
2009-04-19 18:07:22 +00:00
if ( snaptonearest & & ( l ! = null ) )
{
// Snip to grid also?
if ( snaptogrid )
{
// Find all points where the grid intersects the line
List < Vector2D > points = l . GetGridIntersections ( ) ;
2014-12-03 23:15:26 +00:00
if ( points . Count = = 0 )
{
2014-01-08 09:46:57 +00:00
//mxd. Just use the nearest point on line
insertpos = l . NearestOnLine ( mousemappos ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2014-01-08 09:46:57 +00:00
insertpos = mousemappos ;
2020-05-21 12:20:02 +00:00
double distance = double . MaxValue ;
2014-01-08 09:46:57 +00:00
foreach ( Vector2D p in points )
2009-04-19 18:07:22 +00:00
{
2020-05-21 12:20:02 +00:00
double pdist = Vector2D . DistanceSq ( p , mousemappos ) ;
2014-01-08 09:46:57 +00:00
if ( pdist < distance )
{
insertpos = p ;
distance = pdist ;
}
2009-04-19 18:07:22 +00:00
}
}
}
else
{
// Just use the nearest point on line
insertpos = l . NearestOnLine ( mousemappos ) ;
}
}
// Snap to grid?
else if ( snaptogrid )
{
// Snap to grid
insertpos = General . Map . Grid . SnappedToGrid ( mousemappos ) ;
}
else
{
// Just insert here, don't snap to anything
insertpos = mousemappos ;
}
2010-08-15 19:43:00 +00:00
2009-04-19 18:07:22 +00:00
// Make the vertex
Vertex v = General . Map . Map . CreateVertex ( insertpos ) ;
2010-08-15 19:43:00 +00:00
if ( v = = null )
{
General . Map . UndoRedo . WithdrawUndo ( ) ;
return ;
}
2009-04-19 18:07:22 +00:00
// Snap to map format accuracy
v . SnapToAccuracy ( ) ;
// Split the line with this vertex
2013-03-18 13:52:27 +00:00
if ( snaptonearest )
2009-04-19 18:07:22 +00:00
{
2014-01-13 08:06:56 +00:00
//mxd. Check if snapped vertex is still on top of a linedef
2016-03-30 11:29:39 +00:00
l = General . Map . Map . NearestLinedefRange ( v . Position , BuilderPlug . Me . SplitLinedefsRange / renderer . Scale ) ;
2013-03-18 13:52:27 +00:00
2014-12-03 23:15:26 +00:00
if ( l ! = null )
{
2014-01-13 08:06:56 +00:00
//mxd
2014-12-03 23:15:26 +00:00
if ( v . Position = = l . Start . Position | | v . Position = = l . End . Position )
{
2014-01-13 08:06:56 +00:00
General . Interface . DisplayStatus ( StatusType . Info , "There's already a vertex here." ) ;
General . Map . UndoRedo . WithdrawUndo ( ) ;
return ;
}
2013-03-18 13:52:27 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Split a linedef." ) ;
Linedef sld = l . Split ( v ) ;
2014-12-03 23:15:26 +00:00
if ( sld = = null )
{
2014-01-13 08:06:56 +00:00
General . Map . UndoRedo . WithdrawUndo ( ) ;
2013-03-18 13:52:27 +00:00
return ;
}
2014-03-19 13:03:47 +00:00
//BuilderPlug.Me.AdjustSplitCoordinates(l, sld);
2012-03-19 21:31:10 +00:00
}
2009-04-19 18:07:22 +00:00
}
else
{
General . Interface . DisplayStatus ( StatusType . Action , "Inserted a vertex." ) ;
}
// Update
General . Map . Map . Update ( ) ;
2010-08-15 19:43:00 +00:00
2009-04-19 18:07:22 +00:00
// Redraw screen
General . Interface . RedrawDisplay ( ) ;
}
}
2014-01-08 09:46:57 +00:00
[BeginAction("deleteitem", BaseAction = true)]
2014-05-20 09:09:28 +00:00
public void DeleteItem ( )
{
2009-04-19 18:07:22 +00:00
// Make list of selected vertices
ICollection < Vertex > selected = General . Map . Map . GetSelectedVertices ( true ) ;
2014-01-08 09:46:57 +00:00
if ( ( selected . Count = = 0 ) & & ( highlighted ! = null ) & & ! highlighted . IsDisposed ) selected . Add ( highlighted ) ;
if ( selected . Count = = 0 ) return ;
2009-04-19 18:07:22 +00:00
2013-07-05 09:07:49 +00:00
// Make undo
2014-12-03 23:15:26 +00:00
if ( selected . Count > 1 )
{
2013-07-05 09:07:49 +00:00
General . Map . UndoRedo . CreateUndo ( "Delete " + selected . Count + " vertices" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Deleted " + selected . Count + " vertices." ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2013-07-05 09:07:49 +00:00
General . Map . UndoRedo . CreateUndo ( "Delete vertex" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Deleted a vertex." ) ;
}
2009-04-19 18:07:22 +00:00
2014-01-08 09:46:57 +00:00
// Go for all vertices that need to be removed
2014-12-03 23:15:26 +00:00
foreach ( Vertex v in selected )
{
2014-01-08 09:46:57 +00:00
// Not already removed automatically?
2014-12-03 23:15:26 +00:00
if ( ! v . IsDisposed )
{
2014-01-08 09:46:57 +00:00
// If the vertex only has 2 linedefs attached, then merge the linedefs
2014-12-03 23:15:26 +00:00
if ( v . Linedefs . Count = = 2 )
{
2014-01-08 09:46:57 +00:00
Linedef ld1 = General . GetByIndex ( v . Linedefs , 0 ) ;
Linedef ld2 = General . GetByIndex ( v . Linedefs , 1 ) ;
Vertex v2 = ( ld2 . Start = = v ) ? ld2 . End : ld2 . Start ;
if ( ld1 . Start = = v ) ld1 . SetStartVertex ( v2 ) ; else ld1 . SetEndVertex ( v2 ) ;
ld2 . Dispose ( ) ;
}
// Trash vertex
v . Dispose ( ) ;
}
}
// Update cache values
General . Map . IsChanged = true ;
General . Map . Map . Update ( ) ;
// Invoke a new mousemove so that the highlighted item updates
MouseEventArgs e = new MouseEventArgs ( MouseButtons . None , 0 , ( int ) mousepos . x , ( int ) mousepos . y , 0 ) ;
OnMouseMove ( e ) ;
// Redraw screen
2015-06-30 18:34:08 +00:00
UpdateSelectionInfo ( ) ; //mxd
2015-04-06 19:33:57 +00:00
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ; //mxd
2014-01-08 09:46:57 +00:00
General . Interface . RedrawDisplay ( ) ;
}
[BeginAction("dissolveitem", BaseAction = true)] //mxd
2014-05-20 09:09:28 +00:00
public void DissolveItem ( )
{
2014-01-08 09:46:57 +00:00
// Make list of selected vertices
ICollection < Vertex > selected = General . Map . Map . GetSelectedVertices ( true ) ;
2014-12-03 23:15:26 +00:00
if ( selected . Count = = 0 )
{
2014-01-08 09:46:57 +00:00
if ( highlighted = = null | | highlighted . IsDisposed ) return ;
selected . Add ( highlighted ) ;
}
// Make undo
2014-12-03 23:15:26 +00:00
if ( selected . Count > 1 )
{
2014-01-08 09:46:57 +00:00
General . Map . UndoRedo . CreateUndo ( "Dissolve " + selected . Count + " vertices" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Dissolved " + selected . Count + " vertices." ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2014-01-08 09:46:57 +00:00
General . Map . UndoRedo . CreateUndo ( "Dissolve vertex" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Dissolved a vertex." ) ;
}
2013-07-05 09:07:49 +00:00
//collect linedefs count per vertex
Dictionary < Vertex , int > linesPerVertex = new Dictionary < Vertex , int > ( ) ;
2014-12-03 23:15:26 +00:00
foreach ( Vertex v in selected )
{
2013-07-05 09:07:49 +00:00
linesPerVertex . Add ( v , v . Linedefs . Count ) ;
}
2013-03-25 14:49:03 +00:00
2013-07-05 09:07:49 +00:00
// Go for all vertices that need to be removed
2014-12-03 23:15:26 +00:00
foreach ( Vertex v in selected )
{
2013-07-05 09:07:49 +00:00
// Not already removed automatically?
2014-12-03 23:15:26 +00:00
if ( ! v . IsDisposed )
{
2013-07-05 09:07:49 +00:00
// If the vertex only had 2 linedefs attached, then merge the linedefs
2014-12-03 23:15:26 +00:00
if ( linesPerVertex [ v ] = = 2 )
{
2013-07-05 09:07:49 +00:00
Linedef ld1 = General . GetByIndex ( v . Linedefs , 0 ) ;
Linedef ld2 = General . GetByIndex ( v . Linedefs , 1 ) ;
Vertex v1 = ( ld1 . Start = = v ) ? ld1 . End : ld1 . Start ;
Vertex v2 = ( ld2 . Start = = v ) ? ld2 . End : ld2 . Start ;
//don't merge if it will collapse 3-sided sector
bool dontMerge = false ;
2014-12-03 23:15:26 +00:00
foreach ( Linedef l in v1 . Linedefs )
{
2013-07-05 09:07:49 +00:00
if ( l = = ld2 ) continue ;
2014-12-03 23:15:26 +00:00
if ( l . Start = = v2 | | l . End = = v2 )
{
TryJoinSectors ( l ) ;
2013-07-05 09:07:49 +00:00
dontMerge = true ;
break ;
}
2013-03-25 14:49:03 +00:00
}
2014-12-03 23:15:26 +00:00
if ( ! dontMerge ) MergeLines ( selected , ld1 , ld2 , v ) ;
2013-03-22 12:53:34 +00:00
}
2013-07-05 09:07:49 +00:00
// Trash vertex
v . Dispose ( ) ;
2013-03-22 12:53:34 +00:00
}
2013-07-05 09:07:49 +00:00
}
2013-03-22 12:53:34 +00:00
2013-07-05 09:07:49 +00:00
// Update cache values
General . Map . Map . Update ( ) ;
General . Map . IsChanged = true ;
2013-03-25 14:49:03 +00:00
2013-07-05 09:07:49 +00:00
// Invoke a new mousemove so that the highlighted item updates
MouseEventArgs e = new MouseEventArgs ( MouseButtons . None , 0 , ( int ) mousepos . x , ( int ) mousepos . y , 0 ) ;
OnMouseMove ( e ) ;
// Redraw screen
2015-06-30 18:34:08 +00:00
UpdateSelectionInfo ( ) ; //mxd
2013-07-29 08:50:50 +00:00
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ; //mxd
2013-07-05 09:07:49 +00:00
General . Interface . RedrawDisplay ( ) ;
}
2013-09-11 13:14:45 +00:00
[BeginAction("placethings")] //mxd
2014-05-20 09:09:28 +00:00
public void PlaceThings ( )
{
2013-09-11 13:14:45 +00:00
// Make list of selected vertices
ICollection < Vertex > selected = General . Map . Map . GetSelectedVertices ( true ) ;
2015-12-28 15:01:53 +00:00
if ( selected . Count = = 0 )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
if ( highlighted ! = null & & ! highlighted . IsDisposed )
2014-12-03 23:15:26 +00:00
{
2013-09-11 13:14:45 +00:00
selected . Add ( highlighted ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2013-09-11 13:14:45 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires selection of some description!" ) ;
return ;
}
}
List < Vector2D > positions = new List < Vector2D > ( selected . Count ) ;
2015-12-28 15:01:53 +00:00
foreach ( Vertex v in selected )
if ( ! positions . Contains ( v . Position ) ) positions . Add ( v . Position ) ;
2014-12-03 23:15:26 +00:00
PlaceThingsAtPositions ( positions ) ;
2013-09-11 13:14:45 +00:00
}
2014-05-08 09:24:32 +00:00
//mxd
[BeginAction("selectsimilar")]
2014-05-20 09:09:28 +00:00
public void SelectSimilar ( )
{
2014-05-08 09:24:32 +00:00
ICollection < Vertex > selection = General . Map . Map . GetSelectedVertices ( true ) ;
2014-12-03 23:15:26 +00:00
if ( selection . Count = = 0 )
{
2014-05-08 09:24:32 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
var form = new SelectSimilarElementOptionsPanel ( ) ;
2016-06-20 13:36:10 +00:00
if ( form . Setup ( this ) ) form . ShowDialog ( General . Interface ) ;
2014-05-08 09:24:32 +00:00
}
2020-04-11 08:42:41 +00:00
[BeginAction("smartgridtransform", BaseAction = true)]
protected void SmartGridTransform ( )
{
if ( General . Map . Map . SelectedVerticessCount > 1 )
{
General . Interface . DisplayStatus ( StatusType . Warning , "Either nothing or exactly one vertex must be selected" ) ;
General . Interface . MessageBeep ( MessageBeepType . Warning ) ;
return ;
}
Vertex vertex = null ;
if ( General . Map . Map . SelectedVerticessCount = = 1 )
vertex = General . Map . Map . GetSelectedVertices ( true ) . First ( ) ;
else if ( highlighted ! = null )
vertex = highlighted ;
if ( vertex ! = null )
{
General . Map . Grid . SetGridOrigin ( vertex . Position . x , vertex . Position . y ) ;
General . Map . GridVisibilityChanged ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
else
{
General . Map . Grid . SetGridRotation ( 0.0f ) ;
General . Map . Grid . SetGridOrigin ( 0 , 0 ) ;
General . Map . GridVisibilityChanged ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
}
2013-09-11 13:14:45 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Action assist ( mxd )
2020-04-11 08:42:41 +00:00
//mxd
2014-12-03 23:15:26 +00:00
private static void MergeLines ( ICollection < Vertex > selected , Linedef ld1 , Linedef ld2 , Vertex v )
2014-05-20 09:09:28 +00:00
{
2013-07-08 13:13:28 +00:00
Vertex v1 = ( ld1 . Start = = v ) ? ld1 . End : ld1 . Start ;
Vertex v2 = ( ld2 . Start = = v ) ? ld2 . End : ld2 . Start ;
if ( ld1 . Start = = v ) ld1 . SetStartVertex ( v2 ) ;
else ld1 . SetEndVertex ( v2 ) ;
ld2 . Dispose ( ) ;
bool redraw = true ;
2014-12-03 23:15:26 +00:00
if ( ! v2 . IsDisposed & & selected . Contains ( v2 ) & & v2 . Linedefs . Count = = 2 )
{
2013-07-08 13:13:28 +00:00
Linedef [ ] lines = new Linedef [ 2 ] ;
v2 . Linedefs . CopyTo ( lines , 0 ) ;
Linedef other = lines [ 0 ] = = ld2 ? lines [ 1 ] : lines [ 0 ] ;
2014-12-03 23:15:26 +00:00
MergeLines ( selected , ld1 , other , v2 ) ;
2013-07-08 13:13:28 +00:00
v2 . Dispose ( ) ;
redraw = false ;
}
2014-12-03 23:15:26 +00:00
if ( ! v1 . IsDisposed & & selected . Contains ( v1 ) & & v1 . Linedefs . Count = = 2 )
{
2013-07-08 13:13:28 +00:00
Linedef [ ] lines = new Linedef [ 2 ] ;
v1 . Linedefs . CopyTo ( lines , 0 ) ;
Linedef other = lines [ 0 ] = = ld1 ? lines [ 1 ] : lines [ 0 ] ;
2014-12-03 23:15:26 +00:00
MergeLines ( selected , other , ld1 , v1 ) ;
2013-07-08 13:13:28 +00:00
v1 . Dispose ( ) ;
redraw = false ;
}
2014-12-03 23:15:26 +00:00
if ( redraw & & ld1 . Start ! = null & & ld1 . End ! = null )
{
2013-07-08 13:13:28 +00:00
Vector2D start = ld1 . Start . Position ;
Vector2D end = ld1 . End . Position ;
ld1 . Dispose ( ) ;
2014-12-03 23:15:26 +00:00
DrawLine ( start , end ) ;
}
else
{
2013-09-03 09:34:28 +00:00
ld1 . Dispose ( ) ;
2013-07-08 13:13:28 +00:00
}
}
//mxd
2014-12-03 23:15:26 +00:00
private static void DrawLine ( Vector2D start , Vector2D end )
2014-05-20 09:09:28 +00:00
{
2013-07-05 09:07:49 +00:00
DrawnVertex dv1 = new DrawnVertex ( ) ;
DrawnVertex dv2 = new DrawnVertex ( ) ;
dv1 . stitchline = true ;
dv2 . stitchline = true ;
dv1 . stitch = true ;
dv2 . stitch = true ;
dv1 . pos = start ;
dv2 . pos = end ;
2016-03-30 11:29:39 +00:00
Tools . DrawLines ( new List < DrawnVertex > { dv1 , dv2 } , false , false ) ;
2013-07-05 09:07:49 +00:00
// Update cache values
General . Map . Map . Update ( ) ;
General . Map . IsChanged = true ;
2009-04-19 18:07:22 +00:00
}
2013-03-26 12:31:07 +00:00
//mxd. If there are different sectors on both sides of given linedef, join them
2014-12-03 23:15:26 +00:00
private static void TryJoinSectors ( Linedef ld )
2014-05-20 09:09:28 +00:00
{
2013-03-26 12:31:07 +00:00
if ( ld . IsDisposed ) return ;
2014-12-03 23:15:26 +00:00
if ( ld . Front ! = null & & ld . Front . Sector ! = null & & ld . Back ! = null
& & ld . Back . Sector ! = null & & ld . Front . Sector . Index ! = ld . Back . Sector . Index )
{
2013-03-26 12:31:07 +00:00
if ( ld . Front . Sector . BBox . Width * ld . Front . Sector . BBox . Height > ld . Back . Sector . BBox . Width * ld . Back . Sector . BBox . Height )
ld . Back . Sector . Join ( ld . Front . Sector ) ;
else
ld . Front . Sector . Join ( ld . Back . Sector ) ;
}
}
2009-04-19 18:07:22 +00:00
#endregion
}
}