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 ;
using System.Drawing ;
2021-04-17 18:06:58 +00:00
using System.Diagnostics ;
2023-06-09 09:17:01 +00:00
using System.Linq ;
2021-04-17 18:06:58 +00:00
using System.Threading.Tasks ;
2015-06-24 21:21:19 +00:00
using System.Windows.Forms ;
2021-04-17 18:06:58 +00:00
using System.Collections.Concurrent ;
2009-04-19 18:07:22 +00:00
using CodeImp.DoomBuilder.Actions ;
using CodeImp.DoomBuilder.BuilderModes.Interface ;
2013-09-12 15:02:08 +00:00
using CodeImp.DoomBuilder.Config ;
2015-06-24 21:21:19 +00:00
using CodeImp.DoomBuilder.Editing ;
using CodeImp.DoomBuilder.Geometry ;
using CodeImp.DoomBuilder.Map ;
using CodeImp.DoomBuilder.Rendering ;
using CodeImp.DoomBuilder.Types ;
using CodeImp.DoomBuilder.Windows ;
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder.BuilderModes
{
[ EditMode ( DisplayName = "Sectors Mode" ,
SwitchAction = "sectorsmode" , // Action name used to switch to this mode
2013-09-11 09:47:53 +00:00
ButtonImage = "SectorsMode.png" , // Image resource name for the button
2009-04-19 18:07:22 +00:00
ButtonOrder = int . MinValue + 200 , // Position of the button (lower is more to the left)
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 SectorsMode : BaseClassicMode
{
#region = = = = = = = = = = = = = = = = = = Constants
2016-04-04 22:20:49 +00:00
private const int MAX_SECTOR_LABELS = 256 ; //mxd
2009-04-19 18:07:22 +00:00
#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 Sector highlighted ;
2020-07-16 20:01:37 +00:00
private readonly Association highlightasso ;
2009-04-19 18:07:22 +00:00
// Interface
2016-10-28 21:32:52 +00:00
new private bool editpressed ;
2009-04-19 18:07:22 +00:00
// Labels
private Dictionary < Sector , TextLabel [ ] > labels ;
2020-11-15 23:45:57 +00:00
private List < ITextLabel > torenderlabels ;
2013-09-12 15:02:08 +00:00
//mxd. Effects
2014-09-12 12:19:58 +00:00
private readonly Dictionary < int , string [ ] > effects ;
2009-04-19 18:07:22 +00:00
2013-12-10 12:19:27 +00:00
//mxd. Cached overlays stuff
private FlatVertex [ ] overlayGeometry ;
private Dictionary < Sector , string [ ] > selectedEffectLabels ;
2020-06-21 10:52:36 +00:00
private Dictionary < Sector , string [ ] > unselectedEffectLabels ;
// The blockmap makes synchronized editing faster
BlockMap < BlockEntry > blockmap ;
2020-10-31 15:09:22 +00:00
bool addedlinedefstoblockmap ;
2020-06-21 10:52:36 +00:00
2020-10-31 19:45:05 +00:00
// Stores sizes of the text for text labels so that they only have to be computed once
private Dictionary < string , float > textlabelsizecache ;
2021-04-22 19:10:10 +00:00
private ConcurrentDictionary < Thing , bool > determinedsectorthings ;
2021-04-17 18:06:58 +00:00
2022-09-20 21:52:41 +00:00
// Sectors that will be edited
private ICollection < Sector > editsectors ;
2023-12-15 21:49:28 +00:00
// Autosave
private bool allowautosave ;
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
// Constructor
public SectorsMode ( )
{
2020-07-16 20:01:37 +00:00
highlightasso = new Association ( renderer ) ;
2020-10-31 19:45:05 +00:00
textlabelsizecache = new Dictionary < string , float > ( ) ;
2013-09-12 15:02:08 +00:00
//mxd
effects = new Dictionary < int , string [ ] > ( ) ;
2015-12-28 15:01:53 +00:00
foreach ( SectorEffectInfo info in General . Map . Config . SortedSectorEffects )
2014-12-03 23:15:26 +00:00
{
2013-09-12 15:40:15 +00:00
string name = info . Index + ": " + info . Title ;
effects . Add ( info . Index , new [ ] { name , "E" + info . Index } ) ;
2013-09-12 15:02:08 +00:00
}
2009-04-19 18:07:22 +00:00
}
// Disposer
public override void Dispose ( )
{
// Not already disposed?
if ( ! isdisposed )
{
// Dispose old labels
2016-04-04 22:20:49 +00:00
foreach ( TextLabel [ ] lbl in labels . Values )
foreach ( TextLabel l in lbl ) l . Dispose ( ) ;
2009-04-19 18:07:22 +00:00
// Dispose base
base . Dispose ( ) ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
// This makes a CRC for the selection
2016-04-04 22:20:49 +00:00
/ * public int CreateSelectionCRC ( )
2009-04-19 18:07:22 +00:00
{
CRC crc = new CRC ( ) ;
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( true ) ;
crc . Add ( orderedselection . Count ) ;
foreach ( Sector s in orderedselection )
{
crc . Add ( s . FixedIndex ) ;
}
return ( int ) ( crc . Value & 0xFFFFFFFF ) ;
2016-04-04 22:20:49 +00:00
} * /
2009-04-19 18:07:22 +00:00
2014-04-02 10:57:52 +00:00
//mxd. This makes a CRC for given selection
2014-12-03 23:15:26 +00:00
private static int CreateSelectionCRC ( ICollection < Sector > selection )
{
2014-04-02 10:57:52 +00:00
CRC crc = new CRC ( ) ;
crc . Add ( selection . Count ) ;
2014-12-03 23:15:26 +00:00
foreach ( Sector s in selection ) crc . Add ( s . FixedIndex ) ;
2014-04-02 10:57:52 +00:00
return ( int ) ( crc . Value & 0xFFFFFFFF ) ;
}
2009-04-19 18:07:22 +00:00
// This sets up new labels
private void SetupLabels ( )
{
if ( labels ! = null )
{
// Dispose old labels
2016-03-30 23:25:03 +00:00
foreach ( TextLabel [ ] lbl in labels . Values )
foreach ( TextLabel l in lbl ) l . Dispose ( ) ;
2009-04-19 18:07:22 +00:00
}
// Make text labels for sectors
2016-05-12 22:35:11 +00:00
PixelColor c = ( General . Settings . UseHighlight ? General . Colors . Highlight : General . Colors . Selection ) ; //mxd
2009-04-19 18:07:22 +00:00
labels = new Dictionary < Sector , TextLabel [ ] > ( General . Map . Map . Sectors . Count ) ;
foreach ( Sector s in General . Map . Map . Sectors )
{
// Setup labels
TextLabel [ ] labelarray = new TextLabel [ s . Labels . Count ] ;
for ( int i = 0 ; i < s . Labels . Count ; i + + )
{
2016-03-30 23:25:03 +00:00
labelarray [ i ] = new TextLabel ( ) ;
2009-04-19 18:07:22 +00:00
labelarray [ i ] . TransformCoords = true ;
2016-04-19 20:40:42 +00:00
labelarray [ i ] . Location = s . Labels [ i ] . position ;
2009-04-19 18:07:22 +00:00
labelarray [ i ] . AlignX = TextAlignmentX . Center ;
labelarray [ i ] . AlignY = TextAlignmentY . Middle ;
2016-03-30 23:25:03 +00:00
labelarray [ i ] . Color = c ;
2016-04-06 11:44:38 +00:00
labelarray [ i ] . BackColor = General . Colors . Background . WithAlpha ( 128 ) ;
2009-04-19 18:07:22 +00:00
}
labels . Add ( s , labelarray ) ;
}
}
// This updates the overlay
private void UpdateOverlay ( )
{
2022-03-15 20:31:00 +00:00
if ( General . Map . Map . IsSafeToAccess & & renderer . StartOverlay ( true ) )
2009-04-19 18:07:22 +00:00
{
2013-09-12 15:40:15 +00:00
// Go for all selected sectors
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( true ) ;
//mxd. Render selected sectors
2016-05-12 22:35:11 +00:00
if ( General . Settings . UseHighlight )
2014-12-03 23:15:26 +00:00
{
2013-12-10 12:19:27 +00:00
renderer . RenderHighlight ( overlayGeometry , General . Colors . Selection . WithAlpha ( 64 ) . ToInt ( ) ) ;
}
//mxd. Render highlighted sector
2016-05-12 22:35:11 +00:00
if ( General . Settings . UseHighlight & & highlighted ! = null )
2014-12-03 23:15:26 +00:00
{
2013-12-10 12:19:27 +00:00
renderer . RenderHighlight ( highlighted . FlatVertices , General . Colors . Highlight . WithAlpha ( 64 ) . ToInt ( ) ) ;
2013-09-12 15:40:15 +00:00
}
2015-08-31 22:06:44 +00:00
//mxd. Render comments
if ( General . Map . UDMF & & General . Settings . RenderComments )
{
foreach ( Sector s in General . Map . Map . Sectors ) RenderComment ( s ) ;
}
2020-11-15 23:45:57 +00:00
// TODO: put this in UpdateToRenderLabels, too?
2016-04-04 22:20:49 +00:00
if ( BuilderPlug . Me . ViewSelectionNumbers & & orderedselection . Count < MAX_SECTOR_LABELS )
2014-12-03 23:15:26 +00:00
{
2016-04-25 14:48:39 +00:00
List < ITextLabel > torender = new List < ITextLabel > ( orderedselection . Count ) ;
2015-08-31 22:06:44 +00:00
foreach ( Sector s in orderedselection )
2014-12-03 23:15:26 +00:00
{
Sectors, Linedefs, Things modes: optimized text label rendering.
Fixed, Things mode: in some cases selection labels were not updated after editing a thing.
Fixed, Things mode: selection labels were positioned incorrectly on things with FixedSize setting.
Fixed, Sectors mode: fixed a crash when selecting self-referencing sector when selection labels were enabled.
Fixed, Visual mode: in some cases Auto-align texture actions were not working when "use long texture names" Map Options setting was enabled.
Fixed, MD2/MD3 loader: available animation frames upper bound check was performed incorrectly, which would cause a crash in some very special cases.
Fixed, Game configurations: most Hexen/ZDoom teleport actions use TeleportDests as teleport targets, not MapSpots.
2016-04-05 22:24:36 +00:00
//mxd. Self-referencing (and probably some other) sectors don't have labels...
if ( labels [ s ] . Length = = 0 ) continue ;
2009-04-19 18:07:22 +00:00
// Render labels
TextLabel [ ] labelarray = labels [ s ] ;
2016-04-04 22:20:49 +00:00
float requiredsize = ( labelarray [ 0 ] . TextSize . Height / 2 ) / renderer . Scale ;
2015-08-31 22:06:44 +00:00
for ( int i = 0 ; i < s . Labels . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2009-04-19 18:07:22 +00:00
// Render only when enough space for the label to see
2016-04-29 13:42:52 +00:00
if ( ! string . IsNullOrEmpty ( labelarray [ i ] . Text ) & & requiredsize < s . Labels [ i ] . radius )
torender . Add ( labelarray [ i ] ) ;
2009-04-19 18:07:22 +00:00
}
}
2016-03-30 23:25:03 +00:00
renderer . RenderText ( torender ) ;
2013-09-16 11:44:47 +00:00
}
2013-09-12 15:02:08 +00:00
2020-11-15 23:45:57 +00:00
// Render effect and tag labels
renderer . RenderText ( torenderlabels ) ;
2013-09-16 11:44:47 +00:00
renderer . Finish ( ) ;
}
}
2013-12-10 12:19:27 +00:00
//mxd
2014-12-03 23:15:26 +00:00
private string [ ] GetEffectText ( Sector s )
{
2015-07-28 15:04:21 +00:00
string tagstr = string . Empty ;
string tagstrshort = string . Empty ;
string effectstr = string . Empty ;
string effectstrshort = string . Empty ;
2013-12-10 12:19:27 +00:00
2015-07-28 15:04:21 +00:00
// Make effect text
if ( s . Effect ! = 0 )
2014-12-03 23:15:26 +00:00
{
2015-07-28 15:04:21 +00:00
if ( effects . ContainsKey ( s . Effect ) )
effectstr = effects [ s . Effect ] [ 0 ] ;
else
effectstr = s . Effect + " - " + General . Map . Config . GetGeneralizedSectorEffectName ( s . Effect ) ;
effectstrshort = "E" + s . Effect ;
}
// Make tag text
if ( s . Tag ! = 0 )
{
if ( s . Tags . Count > 1 )
2014-12-03 23:15:26 +00:00
{
2015-07-28 15:04:21 +00:00
string [ ] stags = new string [ s . Tags . Count ] ;
for ( int i = 0 ; i < s . Tags . Count ; i + + ) stags [ i ] = s . Tags [ i ] . ToString ( ) ;
tagstr = "Tags " + string . Join ( ", " , stags ) ;
tagstrshort = "T" + string . Join ( "," , stags ) ;
}
else
2014-12-03 23:15:26 +00:00
{
2015-07-28 15:04:21 +00:00
tagstr = "Tag " + s . Tag ;
tagstrshort = "T" + s . Tag ;
2013-12-10 12:19:27 +00:00
}
2015-07-28 15:04:21 +00:00
}
// Combine them
string [ ] result = new [ ] { string . Empty , string . Empty } ;
if ( s . Effect ! = 0 & & s . Tag ! = 0 )
{
2016-03-30 23:25:03 +00:00
result [ 0 ] = tagstr + Environment . NewLine + effectstr ;
result [ 1 ] = tagstrshort + Environment . NewLine + effectstrshort ;
2015-07-28 15:04:21 +00:00
}
else if ( s . Effect ! = 0 )
{
result [ 0 ] = effectstr ;
result [ 1 ] = effectstrshort ;
2014-12-03 23:15:26 +00:00
}
2015-07-28 15:04:21 +00:00
else if ( s . Tag ! = 0 )
2014-12-03 23:15:26 +00:00
{
2015-07-28 15:04:21 +00:00
result [ 0 ] = tagstr ;
result [ 1 ] = tagstrshort ;
2013-12-10 12:19:27 +00:00
}
return result ;
}
//mxd
2014-12-03 23:15:26 +00:00
private void UpdateOverlaySurfaces ( )
{
2013-12-10 12:19:27 +00:00
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( true ) ;
List < FlatVertex > vertsList = new List < FlatVertex > ( ) ;
// Go for all selected sectors
foreach ( Sector s in orderedselection ) vertsList . AddRange ( s . FlatVertices ) ;
overlayGeometry = vertsList . ToArray ( ) ;
}
//mxd
2014-12-03 23:15:26 +00:00
private void UpdateEffectLabels ( )
{
2013-12-10 12:19:27 +00:00
selectedEffectLabels = new Dictionary < Sector , string [ ] > ( ) ;
unselectedEffectLabels = new Dictionary < Sector , string [ ] > ( ) ;
//update effect labels for selected sectors
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( true ) ;
2014-12-03 23:15:26 +00:00
foreach ( Sector s in orderedselection )
{
string [ ] labelText = GetEffectText ( s ) ;
2013-12-10 12:19:27 +00:00
if ( ! string . IsNullOrEmpty ( labelText [ 0 ] ) )
selectedEffectLabels . Add ( s , labelText ) ;
}
//update effect labels for unselected sectors
orderedselection = General . Map . Map . GetSelectedSectors ( false ) ;
2014-12-03 23:15:26 +00:00
foreach ( Sector s in orderedselection )
{
string [ ] labelText = GetEffectText ( s ) ;
2013-12-10 12:19:27 +00:00
if ( ! string . IsNullOrEmpty ( labelText [ 0 ] ) )
unselectedEffectLabels . Add ( s , labelText ) ;
}
2020-11-15 23:45:57 +00:00
UpdateToRenderLabels ( ) ;
}
private void UpdateToRenderLabels ( )
{
UpdateToRenderLabels ( renderer . Scale ) ;
}
private void UpdateToRenderLabels ( float scale )
{
torenderlabels = new List < ITextLabel > ( ) ;
List < Dictionary < Sector , string [ ] > > alllabelsgroups = new List < Dictionary < Sector , string [ ] > > ( ) ;
if ( BuilderPlug . Me . ViewSelectionEffects )
{
if ( ! BuilderPlug . Me . ViewSelectionNumbers ) alllabelsgroups . Add ( selectedEffectLabels ) ;
alllabelsgroups . Add ( unselectedEffectLabels ) ;
}
foreach ( Dictionary < Sector , string [ ] > labelsGroup in alllabelsgroups )
{
foreach ( KeyValuePair < Sector , string [ ] > group in labelsGroup )
{
// Pick which text variant to use
TextLabel [ ] labelarray = labels [ group . Key ] ;
for ( int i = 0 ; i < group . Key . Labels . Count ; i + + )
{
TextLabel l = labelarray [ i ] ;
l . Color = General . Colors . InfoLine ;
// Render only when enough space for the label to see
if ( ! textlabelsizecache . ContainsKey ( group . Value [ 0 ] ) )
textlabelsizecache [ group . Value [ 0 ] ] = General . Interface . MeasureString ( group . Value [ 0 ] , l . Font ) . Width ;
float requiredsize = textlabelsizecache [ group . Value [ 0 ] ] / 2 / scale ;
if ( requiredsize > group . Key . Labels [ i ] . radius )
{
if ( ! textlabelsizecache . ContainsKey ( group . Value [ 1 ] ) )
textlabelsizecache [ group . Value [ 1 ] ] = General . Interface . MeasureString ( group . Value [ 1 ] , l . Font ) . Width ;
requiredsize = textlabelsizecache [ group . Value [ 1 ] ] / 2 / scale ;
string newtext ;
if ( requiredsize > group . Key . Labels [ i ] . radius )
newtext = ( requiredsize > group . Key . Labels [ i ] . radius * 4 ? string . Empty : "+" ) ;
else
newtext = group . Value [ 1 ] ;
if ( l . Text ! = newtext )
l . Text = newtext ;
}
else
{
if ( group . Value [ 0 ] ! = l . Text )
l . Text = group . Value [ 0 ] ;
}
if ( ! string . IsNullOrEmpty ( l . Text ) ) torenderlabels . Add ( l ) ;
}
}
}
2013-12-10 12:19:27 +00:00
}
2009-04-19 18:07:22 +00:00
// Support function for joining and merging sectors
private void JoinMergeSectors ( bool removelines )
{
// Remove lines in betwen joining sectors?
if ( removelines )
{
// Go for all selected linedefs
List < Linedef > selectedlines = new List < Linedef > ( General . Map . Map . GetSelectedLinedefs ( true ) ) ;
foreach ( Linedef ld in selectedlines )
{
// Front and back side?
if ( ( ld . Front ! = null ) & & ( ld . Back ! = null ) )
{
// Both a selected sector, but not the same?
if ( ld . Front . Sector . Selected & & ld . Back . Sector . Selected & &
( ld . Front . Sector ! = ld . Back . Sector ) )
{
// Remove this line
ld . Dispose ( ) ;
}
}
}
}
// Find the first sector that is not disposed
List < Sector > orderedselection = new List < Sector > ( General . Map . Map . GetSelectedSectors ( true ) ) ;
Sector first = null ;
foreach ( Sector s in orderedselection )
if ( ! s . IsDisposed ) { first = s ; break ; }
// Join all selected sectors with the first
for ( int i = 0 ; i < orderedselection . Count ; i + + )
if ( ( orderedselection [ i ] ! = first ) & & ! orderedselection [ i ] . IsDisposed )
orderedselection [ i ] . Join ( first ) ;
// Clear selection
General . Map . Map . ClearAllSelected ( ) ;
// Update
General . Map . Map . Update ( ) ;
// Make text labels for sectors
SetupLabels ( ) ;
UpdateSelectedLabels ( ) ;
}
// This highlights a new 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 void Highlight ( Sector s )
2009-04-19 18:07:22 +00:00
{
// Often we can get away by simply undrawing the previous
// highlight and drawing the new highlight. But if associations
// are or were drawn we need to redraw the entire display.
// Previous association highlights something?
2021-03-14 14:58:40 +00:00
bool completeredraw = ( highlighted ! = null ) & & ( highlighted . Tag ! = 0 | | Association . SectorHasUDMFFieldAssociations ( highlighted ) ) ;
2009-04-19 18:07:22 +00:00
// Set highlight association
2021-03-14 14:58:40 +00:00
if ( s ! = null & & ( s . Tag ! = 0 | | Association . SectorHasUDMFFieldAssociations ( s ) ) )
2014-12-03 23:15:26 +00:00
{
2020-07-16 20:01:37 +00:00
highlightasso . Set ( s ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2020-07-16 20:01:37 +00:00
highlightasso . Clear ( ) ;
2013-09-11 13:57:27 +00:00
}
2009-04-19 18:07:22 +00:00
// New association highlights something?
2021-03-14 14:58:40 +00:00
if ( ( s ! = null ) & & ( s . Tag ! = 0 | | Association . SectorHasUDMFFieldAssociations ( s ) ) ) completeredraw = true ;
2009-04-19 18:07:22 +00:00
// Change label color
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
TextLabel [ ] labelarray = labels [ highlighted ] ;
2016-05-12 22:35:11 +00:00
PixelColor c = ( General . Settings . UseHighlight ? General . Colors . Highlight : General . Colors . Selection ) ;
2016-03-30 23:25:03 +00:00
foreach ( TextLabel l in labelarray ) l . Color = c ;
2009-04-19 18:07:22 +00:00
}
// Change label color
if ( ( s ! = null ) & & ! s . IsDisposed )
{
TextLabel [ ] labelarray = labels [ s ] ;
2016-05-12 22:35:11 +00:00
PixelColor c = ( General . Settings . UseHighlight ? General . Colors . Selection : General . Colors . Highlight ) ;
2016-03-30 23:25:03 +00:00
foreach ( TextLabel l in labelarray ) l . Color = c ;
2009-04-19 18:07:22 +00:00
}
2020-11-15 23:45:57 +00:00
UpdateToRenderLabels ( ) ;
2009-04-19 18:07:22 +00:00
// If we're changing associations, then we
// need to redraw the entire display
2020-11-15 23:45:57 +00:00
if ( completeredraw )
2009-04-19 18:07:22 +00:00
{
// Set new highlight and redraw completely
highlighted = s ;
General . Interface . RedrawDisplay ( ) ;
}
else
{
// Update display
if ( renderer . StartPlotter ( false ) )
{
// Undraw previous highlight
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
renderer . PlotSector ( highlighted ) ;
// Set new highlight
highlighted = s ;
// Render highlighted item
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
renderer . PlotSector ( highlighted , General . Colors . Highlight ) ;
2015-07-14 23:34:31 +00:00
2009-04-19 18:07:22 +00:00
// Done
renderer . Finish ( ) ;
}
UpdateOverlay ( ) ;
renderer . Present ( ) ;
}
// Show highlight info
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
2015-07-14 09:02:48 +00:00
{
2009-04-19 18:07:22 +00:00
General . Interface . ShowSectorInfo ( highlighted ) ;
2015-07-14 09:02:48 +00:00
}
2009-04-19 18:07:22 +00:00
else
2015-07-14 09:02:48 +00:00
{
General . Interface . Display . HideToolTip ( ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . HideInfo ( ) ;
2015-07-14 09:02:48 +00:00
}
2009-04-19 18:07:22 +00:00
}
// This selectes or deselects a sector
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 void SelectSector ( Sector s , bool selectstate , bool update )
2009-04-19 18:07:22 +00:00
{
bool selectionchanged = false ;
if ( ! s . IsDisposed )
{
// Select the sector?
if ( selectstate & & ! s . Selected )
{
s . Selected = true ;
selectionchanged = true ;
// Setup labels
2014-12-03 23:15:26 +00:00
if ( update )
{
//mxd
2013-12-10 12:19:27 +00:00
string selectedCount = General . Map . Map . SelectedSectorsCount . ToString ( ) ;
2016-05-12 22:35:11 +00:00
PixelColor c = ( General . Settings . UseHighlight ? General . Colors . Highlight : General . Colors . Selection ) ;
2013-12-10 12:19:27 +00:00
TextLabel [ ] labelarray = labels [ s ] ;
2014-12-03 23:15:26 +00:00
foreach ( TextLabel l in labelarray )
{
2013-12-10 13:01:27 +00:00
l . Text = selectedCount ;
2016-03-30 23:25:03 +00:00
l . Color = c ;
2013-12-10 12:19:27 +00:00
}
2014-12-03 23:15:26 +00:00
UpdateEffectLabels ( ) ;
2009-04-19 18:07:22 +00:00
}
}
// Deselect the sector?
else if ( ! selectstate & & s . Selected )
{
s . Selected = false ;
selectionchanged = true ;
// Clear labels
2014-12-03 23:15:26 +00:00
if ( update )
{
2013-12-10 12:19:27 +00:00
TextLabel [ ] labelarray = labels [ s ] ;
2020-11-15 23:45:57 +00:00
foreach ( TextLabel l in labelarray )
{
l . Text = "" ;
l . Color = General . Colors . InfoLine ;
}
2009-04-19 18:07:22 +00:00
2013-12-10 12:19:27 +00:00
// Update all other labels
UpdateSelectedLabels ( ) ;
}
2009-04-19 18:07:22 +00:00
}
// Selection changed?
if ( selectionchanged )
{
// Make update lines selection
foreach ( Sidedef sd in s . Sidedefs )
{
bool front , back ;
if ( sd . Line . Front ! = null ) front = sd . Line . Front . Sector . Selected ; else front = false ;
if ( sd . Line . Back ! = null ) back = sd . Line . Back . Sector . Selected ; else back = false ;
sd . Line . Selected = front | back ;
}
2015-01-10 23:12:19 +00:00
//mxd. Also (de)select things?
2015-11-03 08:54:56 +00:00
if ( General . Interface . AltState ^ BuilderPlug . Me . SyncronizeThingEdit )
2015-01-10 23:12:19 +00:00
{
2020-06-21 10:52:36 +00:00
List < BlockEntry > belist = blockmap . GetSquareRange ( s . BBox ) ;
2021-04-17 18:06:58 +00:00
HashSet < Thing > detthings = new HashSet < Thing > ( ) ; // Things that still need their sector to be determined
ConcurrentBag < Thing > selthings = new ConcurrentBag < Thing > ( ) ; // Things that have to have their selection status changed
2020-06-21 10:52:36 +00:00
2021-04-17 18:06:58 +00:00
foreach ( BlockEntry be in belist )
2020-06-21 10:52:36 +00:00
{
foreach ( Thing t in be . Things )
{
2021-04-17 18:06:58 +00:00
// If the thing isn't cached we need to add it to the list of things that need their sector to be determined,
// otherwise (if they are cached) add them to the list of things that have to have their selection status changed
2021-04-22 19:10:10 +00:00
if ( ! determinedsectorthings . ContainsKey ( t ) )
2021-04-17 18:06:58 +00:00
detthings . Add ( t ) ;
else if ( t . Sector = = s & & t . Selected ! = s . Selected )
selthings . Add ( t ) ;
2020-06-21 10:52:36 +00:00
}
}
2021-04-17 18:06:58 +00:00
// Determine sectors of things in parallel. If there's a match add the thing to the list of things that have to have their selection status changed
Parallel . ForEach ( detthings , t = > {
t . DetermineSector ( blockmap ) ;
2021-04-22 19:10:10 +00:00
determinedsectorthings [ t ] = true ; // Add to cache
2021-04-17 18:06:58 +00:00
if ( t . Sector = = s & & t . Selected ! = s . Selected ) selthings . Add ( t ) ;
} ) ;
// Finally change the selection status. This has be done here (and not in parallel), since changing the Selected property
// runs some methods that are not threadsafe
foreach ( Thing t in selthings )
t . Selected = s . Selected ;
2015-01-10 23:12:19 +00:00
}
2021-04-17 18:06:58 +00:00
if ( update )
2013-12-10 12:19:27 +00:00
{
UpdateOverlay ( ) ;
renderer . Present ( ) ;
}
2009-04-19 18:07:22 +00:00
}
}
}
// This updates labels from the selected sectors
private void UpdateSelectedLabels ( )
{
// Go for all labels in all selected sectors
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( true ) ;
2016-05-12 22:35:11 +00:00
PixelColor c = ( General . Settings . UseHighlight ? General . Colors . Highlight : General . Colors . Selection ) ; //mxd
2009-04-19 18:07:22 +00:00
int index = 0 ;
foreach ( Sector s in orderedselection )
{
TextLabel [ ] labelarray = labels [ s ] ;
foreach ( TextLabel l in labelarray )
{
// Make sure the text and color are right
int labelnum = index + 1 ;
l . Text = labelnum . ToString ( ) ;
2016-03-30 23:25:03 +00:00
l . Color = c ;
2009-04-19 18:07:22 +00:00
}
index + + ;
}
2013-12-10 12:19:27 +00:00
//mxd
2014-12-03 23:15:26 +00:00
UpdateEffectLabels ( ) ;
2009-04-19 18:07:22 +00:00
}
2013-11-29 14:45:29 +00:00
//mxd
2014-12-03 23:15:26 +00:00
private bool IsInSelectionRect ( Sector s , List < Line2D > selectionOutline )
{
2013-12-11 08:47:11 +00:00
if ( selectionrect . Contains ( s . BBox ) ) return true ;
2013-12-10 12:19:27 +00:00
2014-12-03 23:15:26 +00:00
if ( BuilderPlug . Me . MarqueSelectTouching & & s . BBox . IntersectsWith ( selectionrect ) )
{
2013-11-29 14:45:29 +00:00
//check endpoints
2014-12-03 23:15:26 +00:00
foreach ( Sidedef side in s . Sidedefs )
{
2020-05-21 12:20:02 +00:00
if ( ( selectionrect . Contains ( ( float ) side . Line . Start . Position . x , ( float ) side . Line . Start . Position . y )
| | selectionrect . Contains ( ( float ) side . Line . End . Position . x , ( float ) side . Line . End . Position . y ) ) )
2013-12-10 12:19:27 +00:00
return true ;
2013-11-29 14:45:29 +00:00
}
//check line intersections
2014-12-03 23:15:26 +00:00
foreach ( Sidedef side in s . Sidedefs )
{
foreach ( Line2D line in selectionOutline )
{
if ( Line2D . GetIntersection ( side . Line . Line , line ) ) return true ;
2013-11-29 14:45:29 +00:00
}
}
}
2013-12-10 12:19:27 +00:00
return false ;
2013-11-29 14:45:29 +00:00
}
2016-04-22 20:17:21 +00:00
//mxd. Gets map elements inside of selectionoutline and sorts them by distance to targetpoint
private List < Sector > GetOrderedSelection ( Vector2D targetpoint , List < Line2D > selectionoutline )
{
// Gather affected sectors
List < Sector > result = new List < Sector > ( ) ;
foreach ( Sector s in General . Map . Map . Sectors )
{
if ( IsInSelectionRect ( s , selectionoutline ) ) result . Add ( s ) ;
}
if ( result . Count = = 0 ) return result ;
// Sort by distance to targetpoint
result . Sort ( delegate ( Sector s1 , Sector s2 )
{
if ( s1 = = s2 ) return 0 ;
// Get closest distance from s1 to selectstart
2020-05-21 12:20:02 +00:00
double closest1 = double . MaxValue ;
2016-04-22 20:17:21 +00:00
foreach ( Sidedef side in s1 . Sidedefs )
{
Vector2D pos = ( side . IsFront ? side . Line . Start : side . Line . End ) . Position ;
2020-05-21 12:20:02 +00:00
double curdistance = Vector2D . DistanceSq ( pos , targetpoint ) ;
2016-04-22 20:17:21 +00:00
if ( curdistance < closest1 ) closest1 = curdistance ;
}
// Get closest distance from s2 to selectstart
2020-05-21 12:20:02 +00:00
double closest2 = double . MaxValue ;
2016-04-22 20:17:21 +00:00
foreach ( Sidedef side in s2 . Sidedefs )
{
Vector2D pos = ( side . IsFront ? side . Line . Start : side . Line . End ) . Position ;
2020-05-21 12:20:02 +00:00
double curdistance = Vector2D . DistanceSq ( pos , targetpoint ) ;
2016-04-22 20:17:21 +00:00
if ( curdistance < closest2 ) closest2 = curdistance ;
}
// Return closer one
return ( int ) ( closest1 - closest2 ) ;
} ) ;
return result ;
}
2014-01-13 12:49:54 +00:00
//mxd
2016-03-18 12:52:12 +00:00
public override void SelectMapElement ( SelectableElement element )
2014-12-03 23:15:26 +00:00
{
2016-03-18 12:52:12 +00:00
Sector sector = element as Sector ;
if ( sector ! = null )
2014-12-03 23:15:26 +00:00
{
2016-03-18 12:52:12 +00:00
SelectSector ( sector , true , true ) ;
2014-01-13 12:49:54 +00:00
// Update overlay
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ;
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ;
2014-01-13 12:49:54 +00:00
}
}
2020-11-15 23:45:57 +00:00
/// <summary>
/// Update the labels to render with the new scale before actually doing the rendering because zooming
/// will redraw the display, and the labels to render must be updated by then
/// </summary>
public override void ZoomIn ( )
{
float z = renderer . Scale * ( 1.0f + General . Settings . ZoomFactor * 0.1f ) ;
UpdateToRenderLabels ( z ) ;
base . ZoomIn ( ) ;
}
/// <summary>
/// Update the labels to render with the new scale before actually doing the rendering because zooming
/// will redraw the display, and the labels to render must be updated by then
/// </summary>
public override void ZoomOut ( )
{
float z = renderer . Scale * ( 1.0f / ( 1.0f + General . Settings . ZoomFactor * 0.1f ) ) ;
UpdateToRenderLabels ( z ) ;
base . ZoomOut ( ) ;
}
2020-07-27 18:18:33 +00:00
/// <summary>
/// Create a blockmap containing sectors and things. This is used to speed determining which sector a
/// thing is in when synchronized thing editing is enabled
/// </summary>
private void CreateBlockmap ( )
{
RectangleF area = MapSet . CreateArea ( General . Map . Map . Vertices ) ;
area = MapSet . IncreaseArea ( area , General . Map . Map . Things ) ;
blockmap = new BlockMap < BlockEntry > ( area ) ;
blockmap . AddSectorsSet ( General . Map . Map . Sectors ) ;
blockmap . AddThingsSet ( General . Map . Map . Things ) ;
2020-10-31 15:09:22 +00:00
// Don't add linedefs here. They are only needed for paint select, so let's save some
// time (and add them when paint select is used t he first time)
addedlinedefstoblockmap = false ;
2020-07-27 18:18:33 +00:00
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Events
public override void OnHelp ( )
{
General . ShowHelp ( "e_sectors.html" ) ;
}
// Cancel mode
public override void OnCancel ( )
{
base . OnCancel ( ) ;
// Return to this mode
General . Editing . ChangeMode ( new SectorsMode ( ) ) ;
}
// Mode engages
public override void OnEngage ( )
{
base . OnEngage ( ) ;
renderer . SetPresentation ( Presentation . Standard ) ;
// Add toolbar buttons
2016-04-04 22:20:49 +00:00
General . Interface . BeginToolbarUpdate ( ) ; //mxd
2010-08-15 13:45:43 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . CopyProperties ) ;
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . PasteProperties ) ;
2014-04-09 10:16:33 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . PastePropertiesOptions ) ; //mxd
2010-08-15 13:45:43 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . SeparatorCopyPaste ) ;
2009-04-19 18:07:22 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . ViewSelectionNumbers ) ;
2016-04-04 22:20:49 +00:00
BuilderPlug . Me . MenusForm . ViewSelectionEffects . Text = "View Tags and Effects" ; //mxd
2013-09-16 11:44:47 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . ViewSelectionEffects ) ;
2009-04-19 18:07:22 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . SeparatorSectors1 ) ;
2014-02-26 14:11:06 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . MakeDoor ) ; //mxd
2015-01-16 21:38:42 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . SeparatorSectors2 ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . MakeGradientBrightness ) ;
2015-01-16 21:38:42 +00:00
if ( General . Map . UDMF ) General . Interface . AddButton ( BuilderPlug . Me . MenusForm . GradientModeMenu ) ; //mxd
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . GradientInterpolationMenu ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . MakeGradientFloors ) ;
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . MakeGradientCeilings ) ;
2015-01-16 21:38:42 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . SeparatorSectors3 ) ; //mxd
2013-03-18 13:52:27 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . MarqueSelectTouching ) ; //mxd
2015-11-03 08:54:56 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . SyncronizeThingEditButton ) ; //mxd
2020-05-03 15:25:07 +00:00
if ( General . Map . UDMF )
{
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . TextureOffsetLock , ToolbarSection . Geometry ) ; //mxd
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . TextureOffset3DFloorLock , ToolbarSection . Geometry ) ;
}
2016-04-04 22:20:49 +00:00
General . Interface . EndToolbarUpdate ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Convert geometry selection to sectors only
General . Map . Map . ConvertSelection ( SelectionType . Sectors ) ;
2015-11-03 08:54:56 +00:00
//mxd. Update the tooltip
BuilderPlug . Me . MenusForm . SyncronizeThingEditButton . ToolTipText = "Synchronized Things Editing" + Environment . NewLine + BuilderPlug . Me . MenusForm . SyncronizeThingEditSectorsItem . ToolTipText ;
2020-06-21 10:52:36 +00:00
// Create the blockmap
2020-07-27 18:18:33 +00:00
CreateBlockmap ( ) ;
2015-11-08 20:20:46 +00:00
2020-07-27 18:18:33 +00:00
// Select things in the selected sectors if synchronized thing editing is enabled
2015-11-03 08:54:56 +00:00
if ( BuilderPlug . Me . SyncronizeThingEdit )
{
ICollection < Sector > sectors = General . Map . Map . GetSelectedSectors ( true ) ;
2020-06-21 10:52:36 +00:00
foreach ( Sector s in sectors )
2015-11-03 08:54:56 +00:00
{
2020-06-21 10:52:36 +00:00
List < BlockEntry > belist = blockmap . GetSquareRange ( s . BBox ) ;
foreach ( BlockEntry be in belist )
2015-11-03 08:54:56 +00:00
{
2020-06-21 10:52:36 +00:00
foreach ( Thing t in be . Things )
{
2020-11-22 17:19:47 +00:00
// Always determine the thing's current sector because it might have change since the last determination
t . DetermineSector ( blockmap ) ;
2020-06-21 10:52:36 +00:00
if ( t . Sector = = s & & t . Selected ! = s . Selected ) t . Selected = s . Selected ;
}
2015-11-03 08:54:56 +00:00
}
}
}
2021-04-22 19:10:10 +00:00
determinedsectorthings = new ConcurrentDictionary < Thing , bool > ( ) ;
2021-04-17 18:06:58 +00:00
2009-04-19 18:07:22 +00:00
// Make text labels for sectors
SetupLabels ( ) ;
// Update
UpdateSelectedLabels ( ) ;
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ; //mxd
2023-12-15 21:49:28 +00:00
// By default we allow autosave
allowautosave = true ;
2009-04-19 18:07:22 +00:00
}
2021-04-17 18:06:58 +00:00
2009-04-19 18:07:22 +00:00
// Mode disengages
public override void OnDisengage ( )
{
base . OnDisengage ( ) ;
// Remove toolbar buttons
2016-04-04 22:20:49 +00:00
General . Interface . BeginToolbarUpdate ( ) ; //mxd
2010-08-15 13:45:43 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . CopyProperties ) ;
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . PasteProperties ) ;
2014-04-09 10:16:33 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . PastePropertiesOptions ) ; //mxd
2010-08-15 13:45:43 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . SeparatorCopyPaste ) ;
2009-04-19 18:07:22 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . ViewSelectionNumbers ) ;
2013-09-16 11:44:47 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . ViewSelectionEffects ) ;
2009-04-19 18:07:22 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . SeparatorSectors1 ) ;
2014-02-26 14:11:06 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . MakeDoor ) ; //mxd
2015-01-16 21:38:42 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . SeparatorSectors2 ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . MakeGradientBrightness ) ;
2016-11-26 00:02:56 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . GradientModeMenu ) ; //mxd
2015-01-16 21:38:42 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . GradientInterpolationMenu ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . MakeGradientFloors ) ;
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . MakeGradientCeilings ) ;
2015-01-16 21:38:42 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . SeparatorSectors3 ) ; //mxd
2013-03-18 13:52:27 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . MarqueSelectTouching ) ; //mxd
2015-11-03 08:54:56 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . SyncronizeThingEditButton ) ; //mxd
2016-11-26 00:02:56 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . TextureOffsetLock ) ; //mxd
2020-05-03 15:25:07 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . TextureOffset3DFloorLock ) ;
2016-04-04 22:20:49 +00:00
General . Interface . EndToolbarUpdate ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Keep only sectors selected
General . Map . Map . ClearSelectedLinedefs ( ) ;
// 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 . GetSelectedSectors ( true ) . Count = = 0 ) & & ( highlighted ! = null ) )
{
// Make the highlight the selection
SelectSector ( highlighted , true , false ) ;
2013-12-10 12:19:27 +00:00
UpdateSelectedLabels ( ) ; //mxd
2009-08-19 11:42:20 +00:00
}
2009-04-19 18:07:22 +00:00
}
}
2015-07-14 09:02:48 +00:00
// Hide highlight info and tooltip
2009-04-19 18:07:22 +00:00
General . Interface . HideInfo ( ) ;
2015-07-14 09:02:48 +00:00
General . Interface . Display . HideToolTip ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
2021-04-17 18:06:58 +00:00
2009-04-19 18:07:22 +00:00
// This redraws the display
public override void OnRedrawDisplay ( )
{
renderer . RedrawSurface ( ) ;
2015-06-24 21:21:19 +00:00
List < Line3D > eventlines = new List < Line3D > ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// 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 . PlotSector ( highlighted , General . Colors . Highlight ) ;
2020-07-16 20:01:37 +00:00
highlightasso . Plot ( ) ;
2009-04-19 18:07:22 +00:00
}
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 ( ) ;
}
2013-12-03 14:40:40 +00:00
// Render overlay
UpdateOverlay ( ) ;
2009-04-19 18:07:22 +00:00
// Render selection
2013-12-03 14:40:40 +00:00
if ( renderer . StartOverlay ( false ) )
2009-04-19 18:07:22 +00:00
{
2020-07-16 20:01:37 +00:00
if ( highlighted ! = null & & ! highlighted . IsDisposed ) highlightasso . Render ( ) ;
if ( selecting ) RenderMultiSelection ( ) ;
2009-04-19 18:07:22 +00:00
renderer . Finish ( ) ;
}
renderer . Present ( ) ;
}
// Selection
protected override void OnSelectBegin ( )
{
// Item highlighted?
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
// Update display
if ( renderer . StartPlotter ( false ) )
{
// Redraw highlight to show selection
renderer . PlotSector ( 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
SelectSector ( highlighted , ! highlighted . Selected , true ) ;
2009-04-19 18:07:22 +00:00
// Update display
if ( renderer . StartPlotter ( false ) )
{
// Render highlighted item
renderer . PlotSector ( highlighted , General . Colors . Highlight ) ;
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
// Update overlay
TextLabel [ ] labelarray = labels [ highlighted ] ;
2020-11-15 23:45:57 +00:00
PixelColor c ;
if ( highlighted . Selected )
c = General . Settings . UseHighlight ? General . Colors . Selection : General . Colors . Highlight ;
else
c = General . Colors . InfoLine ;
foreach ( TextLabel l in labelarray ) l . Color = c ;
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
2009-04-19 18:07:22 +00:00
UpdateOverlay ( ) ;
renderer . Present ( ) ;
2015-01-10 23:12:19 +00:00
//mxd. Thing selection state may've changed
2015-11-03 08:54:56 +00:00
if ( General . Interface . AltState ^ BuilderPlug . Me . SyncronizeThingEdit ) General . Interface . RedrawDisplay ( ) ;
}
2015-12-13 19:18:09 +00:00
else if ( BuilderPlug . Me . AutoClearSelection ) //mxd
2014-12-03 23:15:26 +00:00
{
2015-11-03 08:54:56 +00:00
if ( General . Map . Map . SelectedSectorsCount > 0 )
{
General . Map . Map . ClearSelectedLinedefs ( ) ;
General . Map . Map . ClearSelectedSectors ( ) ;
UpdateOverlaySurfaces ( ) ; //mxd
}
//mxd
if ( BuilderPlug . Me . SyncronizeThingEdit & & General . Map . Map . SelectedThingsCount > 0 )
{
General . Map . Map . ClearSelectedThings ( ) ;
}
2013-03-28 11:37:08 +00:00
General . Interface . RedrawDisplay ( ) ;
2009-04-19 18:07:22 +00:00
}
2013-07-09 11:29:10 +00:00
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
base . OnSelectEnd ( ) ;
}
// Start editing
protected override void OnEditBegin ( )
{
// Item highlighted?
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
// Edit pressed in this mode
editpressed = true ;
// Highlighted item not selected?
2022-09-18 14:54:09 +00:00
if ( ! highlighted . Selected )
2009-04-19 18:07:22 +00:00
{
// Make this the only selection
General . Map . Map . ClearSelectedSectors ( ) ;
General . Map . Map . ClearSelectedLinedefs ( ) ;
2022-09-20 21:52:41 +00:00
editsectors = new List < Sector > { highlighted } ;
2013-12-10 12:19:27 +00:00
UpdateSelectedLabels ( ) ; //mxd
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
2016-09-27 19:39:46 +00:00
UpdateSelectionInfo ( ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . RedrawDisplay ( ) ;
}
2022-09-20 21:52:41 +00:00
else // Highlight is selected, so take all selected sectors
2022-09-18 14:54:09 +00:00
{
2022-09-20 21:52:41 +00:00
editsectors = General . Map . Map . GetSelectedSectors ( true ) ;
2022-09-18 14:54:09 +00:00
}
2009-04-19 18:07:22 +00:00
// Update display
if ( renderer . StartPlotter ( false ) )
{
// Redraw highlight to show selection
2022-09-18 14:54:09 +00:00
renderer . PlotSector ( highlighted , General . Colors . Highlight ) ;
2009-04-19 18:07:22 +00:00
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
2013-12-05 09:24:55 +00:00
else if ( ! selecting & & BuilderPlug . Me . AutoDrawOnEdit ) //mxd. We don't want to draw while multiselecting
2009-04-19 18:07:22 +00:00
{
// Start drawing mode
DrawGeometryMode drawmode = new DrawGeometryMode ( ) ;
bool snaptogrid = General . Interface . ShiftState ^ General . Interface . SnapToGrid ;
bool snaptonearest = General . Interface . CtrlState ^ General . Interface . AutoMerge ;
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
if ( drawmode . DrawPointAt ( v ) )
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 )
{
2022-09-20 21:52:41 +00:00
if ( editsectors ? . Count > 0 )
2009-04-19 18:07:22 +00:00
{
if ( General . Interface . IsActiveWindow )
{
2023-12-15 21:49:28 +00:00
// Prevent autosave while the editing dialog is shown
allowautosave = false ;
2013-07-09 11:29:10 +00:00
//mxd. Show realtime vertex edit dialog
2014-02-21 14:42:12 +00:00
General . Interface . OnEditFormValuesChanged + = sectorEditForm_OnValuesChanged ;
2022-09-18 14:54:09 +00:00
DialogResult result = General . Interface . ShowEditSectors ( editsectors ) ;
2013-07-10 09:57:30 +00:00
General . Interface . OnEditFormValuesChanged - = sectorEditForm_OnValuesChanged ;
2013-07-29 08:50:50 +00:00
2023-12-15 21:49:28 +00:00
allowautosave = true ;
2013-07-29 08:50:50 +00:00
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ; //mxd
2022-09-21 19:05:30 +00:00
UpdateEffectLabels ( ) ;
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
2013-11-29 12:24:47 +00:00
General . Interface . RedrawDisplay ( ) ;
2009-04-19 18:07:22 +00:00
}
}
2013-07-09 11:29:10 +00:00
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
editpressed = false ;
base . OnEditEnd ( ) ;
}
2013-07-09 11:29:10 +00:00
//mxd
2014-12-03 23:15:26 +00:00
private void sectorEditForm_OnValuesChanged ( object sender , EventArgs e )
{
2013-07-09 11:29:10 +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 ) ;
2013-11-08 08:18:33 +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
{
2020-10-31 15:09:22 +00:00
// If linedefs were not added to the blockmap yet add them here
if ( ! addedlinedefstoblockmap )
{
blockmap . AddLinedefsSet ( General . Map . Map . Linedefs ) ;
addedlinedefstoblockmap = true ;
}
2013-03-18 13:52:27 +00:00
// Find the nearest linedef within highlight range
2020-10-31 15:09:22 +00:00
Linedef l = MapSet . NearestLinedefRange ( blockmap , mousemappos , BuilderPlug . Me . HighlightRange / renderer . Scale ) ;
2013-03-18 13:52:27 +00:00
Sector s = null ;
2014-12-03 23:15:26 +00:00
if ( l ! = null )
{
2013-03-18 13:52:27 +00:00
// Check on which side of the linedef the mouse is
2020-05-21 12:20:02 +00:00
double side = l . SideOfLine ( mousemappos ) ;
2014-12-03 23:15:26 +00:00
if ( side > 0 )
{
2013-03-18 13:52:27 +00:00
// Is there a sidedef here?
2014-12-03 23:15:26 +00:00
if ( l . Back ! = null ) s = l . Back . Sector ;
}
else
{
2013-03-18 13:52:27 +00:00
// Is there a sidedef here?
2014-12-03 23:15:26 +00:00
if ( l . Front ! = null ) s = l . Front . Sector ;
2013-03-18 13:52:27 +00:00
}
2014-12-03 23:15:26 +00:00
if ( s ! = null )
{
if ( s ! = highlighted )
{
2013-03-18 13:52:27 +00:00
//toggle selected state
highlighted = s ;
2019-06-20 13:38:41 +00:00
if ( General . Interface . ShiftState ^ BuilderPlug . Me . AdditivePaintSelect )
2013-03-18 13:52:27 +00:00
SelectSector ( highlighted , true , true ) ;
else if ( General . Interface . CtrlState )
SelectSector ( highlighted , false , true ) ;
else
SelectSector ( highlighted , ! highlighted . Selected , true ) ;
// Update entire display
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
2013-03-18 13:52:27 +00:00
General . Interface . RedrawDisplay ( ) ;
}
2014-12-03 23:15:26 +00:00
}
else if ( highlighted ! = null )
{
2013-03-18 13:52:27 +00:00
Highlight ( null ) ;
// Update entire display
General . Interface . RedrawDisplay ( ) ;
}
2013-07-09 11:29:10 +00:00
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ; //mxd
2013-03-18 13:52:27 +00:00
}
}
else if ( e . Button = = MouseButtons . None ) // Not holding any buttons?
2009-04-19 18:07:22 +00:00
{
// Find the nearest linedef within highlight range
Linedef l = General . Map . Map . NearestLinedef ( mousemappos ) ;
if ( l ! = null )
{
// Check on which side of the linedef the mouse is
2020-05-21 12:20:02 +00:00
double side = l . SideOfLine ( mousemappos ) ;
2009-04-19 18:07:22 +00:00
if ( side > 0 )
{
// Is there a sidedef here?
if ( l . Back ! = null )
{
// Highlight if not the same
if ( l . Back . Sector ! = highlighted ) Highlight ( l . Back . Sector ) ;
}
else
{
// Highlight nothing
if ( highlighted ! = null ) Highlight ( null ) ;
}
}
else
{
// Is there a sidedef here?
if ( l . Front ! = null )
{
// Highlight if not the same
if ( l . Front . Sector ! = highlighted ) Highlight ( l . Front . Sector ) ;
}
else
{
// Highlight nothing
if ( highlighted ! = null ) Highlight ( null ) ;
}
}
}
else
{
// Highlight nothing
if ( highlighted ! = null ) Highlight ( null ) ;
}
2015-07-14 09:02:48 +00:00
//mxd. Show tooltip?
2015-07-15 09:09:47 +00:00
if ( General . Map . UDMF & & General . Settings . RenderComments & & mouselastpos ! = mousepos & & highlighted ! = null & & ! highlighted . IsDisposed & & highlighted . Fields . ContainsKey ( "comment" ) )
2015-07-14 09:02:48 +00:00
{
string comment = highlighted . Fields . GetValue ( "comment" , string . Empty ) ;
2015-07-14 23:34:31 +00:00
if ( comment . Length > 2 )
{
string type = comment . Substring ( 0 , 3 ) ;
int index = Array . IndexOf ( CommentType . Types , type ) ;
if ( index > 0 ) comment = comment . TrimStart ( type . ToCharArray ( ) ) ;
}
2015-07-14 09:02:48 +00:00
General . Interface . Display . ShowToolTip ( "Comment:" , comment , ( int ) ( mousepos . x + 32 * MainForm . DPIScaler . Width ) , ( int ) ( mousepos . y + 8 * MainForm . DPIScaler . Height ) ) ;
}
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 ) ;
}
2013-03-18 13:52:27 +00:00
//mxd
2014-12-03 23:15:26 +00:00
protected override void OnPaintSelectBegin ( )
{
if ( highlighted ! = null )
{
2019-06-20 13:38:41 +00:00
if ( General . Interface . ShiftState ^ BuilderPlug . Me . AdditivePaintSelect )
2013-04-05 10:56:07 +00:00
SelectSector ( highlighted , true , true ) ;
else if ( General . Interface . CtrlState )
SelectSector ( highlighted , false , true ) ;
else
SelectSector ( highlighted , ! highlighted . Selected , true ) ;
// Update entire display
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
2013-04-05 10:56:07 +00:00
General . Interface . RedrawDisplay ( ) ;
}
2013-03-18 13:52:27 +00:00
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 )
{
2022-09-20 21:52:41 +00:00
ICollection < Sector > dragsectors ;
2024-01-06 14:15:39 +00:00
ICollection < Thing > dragthings = null ;
2022-09-18 14:54:09 +00:00
2009-04-19 18:07:22 +00:00
// Highlighted item not selected?
2022-09-18 14:54:09 +00:00
if ( ! highlighted . Selected )
2009-04-19 18:07:22 +00:00
{
// Select only this sector for dragging
General . Map . Map . ClearSelectedSectors ( ) ;
2022-09-20 21:52:41 +00:00
dragsectors = new List < Sector > { highlighted } ;
2024-01-06 14:15:39 +00:00
if ( BuilderPlug . Me . SyncronizeThingEdit )
dragthings = General . Map . Map . Things . Where ( t = > t . Sector = = highlighted ) . ToList ( ) ;
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
2022-09-18 14:54:09 +00:00
else
{
2022-09-20 21:52:41 +00:00
dragsectors = General . Map . Map . GetSelectedSectors ( true ) ;
2022-09-18 14:54:09 +00:00
}
2009-04-19 18:07:22 +00:00
// Start dragging the selection
2023-08-26 11:49:00 +00:00
if ( ! BuilderPlug . Me . DontMoveGeometryOutsideMapBoundary | | CanDrag ( dragsectors ) ) //mxd
2024-01-06 14:15:39 +00:00
General . Editing . ChangeMode ( new DragSectorsMode ( mousedownmappos , dragsectors , dragthings ) ) ;
2009-04-19 18:07:22 +00:00
}
}
}
2013-03-18 13:52:27 +00:00
//mxd. Check if any selected sector is outside of map boundary
2023-08-26 11:49:00 +00:00
private bool CanDrag ( ICollection < Sector > dragsectors )
2014-12-03 23:15:26 +00:00
{
2013-03-18 13:52:27 +00:00
int unaffectedCount = 0 ;
2023-08-26 11:49:00 +00:00
foreach ( Sector s in dragsectors )
2014-12-03 23:15:26 +00:00
{
2013-03-18 13:52:27 +00:00
// Make sure the sector is inside the map boundary
2014-12-03 23:15:26 +00:00
foreach ( Sidedef sd in s . Sidedefs )
{
2013-03-18 13:52:27 +00:00
if ( sd . Line . Start . Position . x < General . Map . Config . LeftBoundary | | sd . Line . Start . Position . x > General . Map . Config . RightBoundary
| | sd . Line . Start . Position . y > General . Map . Config . TopBoundary | | sd . Line . Start . Position . y < General . Map . Config . BottomBoundary
| | sd . Line . End . Position . x < General . Map . Config . LeftBoundary | | sd . Line . End . Position . x > General . Map . Config . RightBoundary
2014-12-03 23:15:26 +00:00
| | sd . Line . End . Position . y > General . Map . Config . TopBoundary | | sd . Line . End . Position . y < General . Map . Config . BottomBoundary )
{
2013-03-18 13:52:27 +00:00
unaffectedCount + + ;
break ;
}
}
}
2023-08-26 11:49:00 +00:00
if ( unaffectedCount = = dragsectors . Count )
2014-12-03 23:15:26 +00:00
{
2023-08-26 11:49:00 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "Unable to drag selection: " + ( dragsectors . Count = = 1 ? "selected sector is" : "all of selected sectors are" ) + " outside of map boundary!" ) ;
2013-03-18 13:52:27 +00:00
General . Interface . RedrawDisplay ( ) ;
return false ;
}
2023-08-26 11:49:00 +00:00
if ( unaffectedCount > 0 )
{
2013-03-18 13:52:27 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , unaffectedCount + " of selected sectors " + ( unaffectedCount = = 1 ? "is" : "are" ) + " outside of map boundary!" ) ;
2023-08-26 11:49:00 +00:00
return false ;
}
2013-03-18 13:52:27 +00:00
return true ;
}
2016-04-22 20:17:21 +00:00
//mxd. This is called wheh selection ends
2009-04-19 18:07:22 +00:00
protected override void OnEndMultiSelection ( )
{
2009-08-19 11:09:10 +00:00
bool selectionvolume = ( ( Math . Abs ( base . selectionrect . Width ) > 0.1f ) & & ( Math . Abs ( base . selectionrect . Height ) > 0.1f ) ) ;
if ( selectionvolume )
2009-04-19 18:07:22 +00:00
{
2016-04-22 20:17:21 +00:00
List < Line2D > selectionoutline = new List < Line2D >
{
2013-11-29 14:45:29 +00:00
new Line2D ( selectionrect . Left , selectionrect . Top , selectionrect . Right , selectionrect . Top ) ,
new Line2D ( selectionrect . Right , selectionrect . Top , selectionrect . Right , selectionrect . Bottom ) ,
new Line2D ( selectionrect . Left , selectionrect . Bottom , selectionrect . Right , selectionrect . Bottom ) ,
new Line2D ( selectionrect . Left , selectionrect . Bottom , selectionrect . Left , selectionrect . Top )
2014-12-03 23:15:26 +00:00
} ;
2013-11-29 14:45:29 +00:00
2016-04-22 20:17:21 +00:00
// (De)select sectors
2014-12-03 23:15:26 +00:00
switch ( marqueSelectionMode )
{
2013-12-20 09:24:43 +00:00
case MarqueSelectionMode . SELECT :
2016-04-22 20:17:21 +00:00
// Get ordered selection
List < Sector > selectresult = GetOrderedSelection ( base . selectstart , selectionoutline ) ;
// First deselect everything...
foreach ( Sector s in General . Map . Map . Sectors ) SelectSector ( s , false , false ) ;
// Then select sectors in correct order
foreach ( Sector s in selectresult ) SelectSector ( s , true , false ) ;
2013-12-20 09:24:43 +00:00
break ;
2013-11-29 14:45:29 +00:00
2013-12-20 09:24:43 +00:00
case MarqueSelectionMode . ADD :
2016-04-22 20:17:21 +00:00
// Get ordered selection
List < Sector > addresult = GetOrderedSelection ( selectstart , selectionoutline ) ;
// First deselect everything inside of selection...
foreach ( Sector s in addresult ) SelectSector ( s , false , false ) ;
// Then reselect in correct order
foreach ( Sector s in addresult ) SelectSector ( s , true , false ) ;
2013-12-20 09:24:43 +00:00
break ;
case MarqueSelectionMode . SUBTRACT :
2016-04-22 20:17:21 +00:00
// Selection order doesn't matter here
2014-12-03 23:15:26 +00:00
foreach ( Sector s in General . Map . Map . Sectors )
{
2013-12-20 09:24:43 +00:00
if ( ! s . Selected ) continue ;
2016-04-22 20:17:21 +00:00
if ( IsInSelectionRect ( s , selectionoutline ) )
2013-12-20 09:24:43 +00:00
SelectSector ( s , false , false ) ;
}
break ;
2016-04-22 20:17:21 +00:00
// Should be Intersect selection mode
default :
// Selection order doesn't matter here
2014-12-03 23:15:26 +00:00
foreach ( Sector s in General . Map . Map . Sectors )
{
2013-12-20 09:24:43 +00:00
if ( ! s . Selected ) continue ;
2016-04-22 20:17:21 +00:00
if ( ! IsInSelectionRect ( s , selectionoutline ) )
2013-12-20 09:24:43 +00:00
SelectSector ( s , false , false ) ;
}
break ;
2009-04-19 18:07:22 +00:00
}
2013-03-18 13:52:27 +00:00
2009-07-07 11:29:56 +00:00
// Make sure all linedefs reflect selected sectors
foreach ( Sidedef sd in General . Map . Map . Sidedefs )
2013-03-18 13:52:27 +00:00
sd . Line . Selected = sd . Sector . Selected | | ( sd . Other ! = null & & sd . Other . Sector . Selected ) ;
2013-07-09 11:29:10 +00:00
2013-12-10 12:19:27 +00:00
//mxd. Clear labels for unselected sectors
2014-12-03 23:15:26 +00:00
if ( marqueSelectionMode ! = MarqueSelectionMode . ADD )
{
2013-12-10 12:19:27 +00:00
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( false ) ;
2014-12-03 23:15:26 +00:00
foreach ( Sector s in orderedselection )
{
2013-12-10 12:19:27 +00:00
TextLabel [ ] labelarray = labels [ s ] ;
foreach ( TextLabel l in labelarray ) l . Text = "" ;
}
}
UpdateSelectedLabels ( ) ; //mxd
2014-05-08 09:24:32 +00:00
UpdateSelectionInfo ( ) ; //mxd
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
base . OnEndMultiSelection ( ) ;
if ( renderer . StartOverlay ( true ) ) renderer . Finish ( ) ;
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 . GetSelectedSectors ( true ) . Count = = 0 ) & & ( highlighted ! = null ) )
{
// Make the highlight the selection
2015-04-16 13:03:12 +00:00
SelectSector ( highlighted , true , false ) ;
//mxd. Actually, we want it marked, not selected
bool result = base . OnCopyBegin ( ) ;
SelectSector ( highlighted , false , false ) ;
return result ;
2009-04-19 18:07:22 +00:00
}
return base . OnCopyBegin ( ) ;
}
// When undo is used
public override bool OnUndoBegin ( )
{
// Clear ordered selection
General . Map . Map . ClearAllSelected ( ) ;
return base . OnUndoBegin ( ) ;
}
// When undo is performed
public override void OnUndoEnd ( )
{
2020-07-27 18:18:33 +00:00
// Recreate the blockmap to not include the potentially un-done sectors and things anymore
CreateBlockmap ( ) ;
2021-10-24 17:22:00 +00:00
// Select changed map elements
if ( BuilderPlug . Me . SelectChangedafterUndoRedo )
{
General . Map . Map . SelectMarkedGeometry ( true , true ) ;
General . Map . Map . ConvertSelection ( SelectionType . Sectors ) ;
}
2021-04-17 18:06:58 +00:00
// Clear the cache of things that already got their sector determined
2021-04-22 19:10:10 +00:00
determinedsectorthings = new ConcurrentDictionary < Thing , bool > ( ) ;
2021-04-17 18:06:58 +00:00
2020-10-09 16:53:10 +00:00
// If something is highlighted make sure to update the association so that it contains valid data
if ( highlighted ! = null & & ! highlighted . IsDisposed )
highlightasso . Set ( highlighted ) ;
2009-04-19 18:07:22 +00:00
// Clear labels
SetupLabels ( ) ;
2014-12-03 23:15:26 +00:00
UpdateEffectLabels ( ) ; //mxd
UpdateOverlaySurfaces ( ) ; //mxd
2013-12-12 09:40:20 +00:00
base . OnUndoEnd ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
// When redo is used
public override bool OnRedoBegin ( )
{
// Clear ordered selection
General . Map . Map . ClearAllSelected ( ) ;
return base . OnRedoBegin ( ) ;
}
// When redo is performed
public override void OnRedoEnd ( )
{
2020-07-27 18:18:33 +00:00
// Recreate the blockmap to include the potentially re-done sectors and things again
CreateBlockmap ( ) ;
2021-10-24 17:22:00 +00:00
// Select changed map elements
if ( BuilderPlug . Me . SelectChangedafterUndoRedo )
{
General . Map . Map . SelectMarkedGeometry ( true , true ) ;
General . Map . Map . ConvertSelection ( SelectionType . Sectors ) ;
}
2020-07-27 18:18:33 +00:00
2021-04-17 18:06:58 +00:00
// Clear the cache of things that already got their sector determined
2021-04-22 19:10:10 +00:00
determinedsectorthings = new ConcurrentDictionary < Thing , bool > ( ) ;
2021-04-17 18:06:58 +00:00
2020-10-09 16:53:10 +00:00
// If something is highlighted make sure to update the association so that it contains valid data
if ( highlighted ! = null & & ! highlighted . IsDisposed )
highlightasso . Set ( highlighted ) ;
2009-04-19 18:07:22 +00:00
// Clear labels
SetupLabels ( ) ;
2014-12-03 23:15:26 +00:00
UpdateEffectLabels ( ) ; //mxd
UpdateOverlaySurfaces ( ) ; //mxd
2013-09-12 15:02:08 +00:00
base . OnRedoEnd ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
2013-07-09 11:29:10 +00:00
2021-11-28 13:00:24 +00:00
// After a script is run
public override void OnScriptRunEnd ( )
{
base . OnScriptRunEnd ( ) ;
CreateBlockmap ( ) ;
// Redo labels
SetupLabels ( ) ;
UpdateEffectLabels ( ) ;
UpdateSelectedLabels ( ) ;
UpdateOverlay ( ) ;
UpdateOverlaySurfaces ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
2022-02-03 18:35:10 +00:00
/// <summary>
/// If map elements have changed the blockmap needs to be recreated.
/// </summary>
public override void OnMapElementsChanged ( )
{
base . OnMapElementsChanged ( ) ;
CreateBlockmap ( ) ;
}
2016-04-30 19:27:26 +00:00
//mxd
public override void OnViewSelectionNumbersChanged ( bool enabled )
{
2022-10-03 09:29:31 +00:00
UpdateSelectedLabels ( ) ;
2016-04-30 19:27:26 +00:00
}
2016-03-30 23:25:03 +00:00
//mxd
2016-05-12 22:35:11 +00:00
protected override void ToggleHighlight ( )
2016-03-30 23:25:03 +00:00
{
// Update label colors
2016-05-12 22:35:11 +00:00
PixelColor c = ( General . Settings . UseHighlight ? General . Colors . Selection : General . Colors . Highlight ) ;
2016-03-30 23:25:03 +00:00
foreach ( TextLabel [ ] labelarray in labels . Values )
foreach ( TextLabel l in labelarray ) l . Color = c ;
// Update highlighted label color
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
TextLabel [ ] labelarray = labels [ highlighted ] ;
2016-05-12 22:35:11 +00:00
c = ( General . Settings . UseHighlight ? General . Colors . Highlight : General . Colors . Selection ) ;
2016-03-30 23:25:03 +00:00
foreach ( TextLabel l in labelarray ) l . Color = c ;
}
// Pass to base
base . ToggleHighlight ( ) ;
}
2023-12-15 21:49:28 +00:00
public override bool OnAutoSaveBegin ( )
{
return allowautosave ;
}
2015-07-14 23:34:31 +00:00
//mxd
private void RenderComment ( Sector s )
{
2015-08-31 22:06:44 +00:00
if ( s . Selected | | ! s . Fields . ContainsKey ( "comment" ) ) return ;
2015-07-14 23:34:31 +00:00
2015-08-31 22:06:44 +00:00
int iconindex = 0 ;
string comment = s . Fields . GetValue ( "comment" , string . Empty ) ;
if ( comment . Length > 2 )
{
string type = comment . Substring ( 0 , 3 ) ;
int index = Array . IndexOf ( CommentType . Types , type ) ;
if ( index ! = - 1 ) iconindex = index ;
2015-07-14 23:34:31 +00:00
}
2015-08-31 22:06:44 +00:00
if ( s . Labels . Count > 0 )
foreach ( LabelPositionInfo info in s . Labels ) RenderComment ( s , info . position , iconindex ) ;
else
RenderComment ( s , new Vector2D ( s . BBox . Left + s . BBox . Width / 2 , s . BBox . Top + s . BBox . Height / 2 ) , iconindex ) ;
}
//mxd
private void RenderComment ( Sector s , Vector2D center , int iconindex )
{
2020-05-21 12:20:02 +00:00
RectangleF rect = new RectangleF ( ( float ) ( center . x - 8 / renderer . Scale ) , ( float ) ( center . y + 8 / renderer . Scale ) , 16 / renderer . Scale , - 16 / renderer . Scale ) ;
2015-08-31 22:06:44 +00:00
PixelColor c = ( s = = highlighted ? General . Colors . Highlight : PixelColor . FromColor ( Color . White ) ) ;
renderer . RenderRectangleFilled ( rect , c , true , General . Map . Data . CommentTextures [ iconindex ] ) ;
2015-07-14 23:34:31 +00:00
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Actions
2010-08-15 13:45:43 +00:00
// This copies the properties
[BeginAction("classiccopyproperties")]
public void CopyProperties ( )
{
// Determine source sectors
ICollection < Sector > 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 . SelectedSectorsCount > 0 ) sel = General . Map . Map . GetSelectedSectors ( true ) ;
else if ( highlighted ! = null ) sel = new List < Sector > { highlighted } ;
2010-08-15 13:45:43 +00:00
if ( 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
// Copy properties from the first source sector
2010-08-15 13:45:43 +00:00
BuilderPlug . Me . CopiedSectorProps = new SectorProperties ( General . GetByIndex ( sel , 0 ) ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Copied sector 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 . CopiedSectorProps ! = null )
{
// Determine target sectors
ICollection < Sector > 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 . SelectedSectorsCount > 0 ) sel = General . Map . Map . GetSelectedSectors ( true ) ;
else if ( highlighted ! = null ) sel = new List < Sector > { 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 sector" : sel . Count + " sectors" ) ; //mxd
General . Map . UndoRedo . CreateUndo ( "Paste properties to " + rest ) ;
2016-10-11 12:58:35 +00:00
BuilderPlug . Me . CopiedSectorProps . Apply ( sel , false ) ;
2010-08-15 13:45:43 +00:00
foreach ( Sector s in sel )
{
s . UpdateCeilingSurface ( ) ;
s . UpdateFloorSurface ( ) ;
}
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 ( ) ;
2013-07-29 08:50:50 +00:00
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ; //mxd
2014-12-03 23:15:26 +00:00
UpdateEffectLabels ( ) ; //mxd
2010-08-15 13:45:43 +00:00
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 sector properties first!" ) ;
}
}
//mxd. This pastes the properties with options
[BeginAction("classicpastepropertieswithoptions")]
public void PastePropertiesWithOptions ( )
{
if ( BuilderPlug . Me . CopiedSectorProps ! = null )
{
// Determine target sectors
ICollection < Sector > sel = null ;
if ( General . Map . Map . SelectedSectorsCount > 0 ) sel = General . Map . Map . GetSelectedSectors ( true ) ;
else if ( highlighted ! = null ) sel = new List < Sector > { 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 . SECTOR ) & & 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 sector" : sel . Count + " sectors" ) ;
General . Map . UndoRedo . CreateUndo ( "Paste properties with options to " + rest ) ;
2016-10-11 12:58:35 +00:00
BuilderPlug . Me . CopiedSectorProps . 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
foreach ( Sector s in sel )
{
s . UpdateCeilingSurface ( ) ;
s . UpdateFloorSurface ( ) ;
}
General . Interface . DisplayStatus ( StatusType . Action , "Pasted properties with options to " + rest + "." ) ;
// Update and redraw
General . Map . IsChanged = true ;
General . Interface . RefreshInfo ( ) ;
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ; //mxd
UpdateEffectLabels ( ) ; //mxd
General . Interface . RedrawDisplay ( ) ;
}
}
else
{
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires highlight or selection!" ) ;
}
}
else
{
General . Interface . DisplayStatus ( StatusType . Warning , "Copy sector properties first!" ) ;
2010-08-15 13:45:43 +00:00
}
}
2009-04-19 18:07:22 +00:00
// This creates a new vertex at the mouse position
[BeginAction("insertitem", BaseAction = true)]
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
public void InsertVertexAction ( )
2009-04-19 18:07:22 +00:00
{
// Start drawing mode
DrawGeometryMode drawmode = new DrawGeometryMode ( ) ;
if ( mouseinside )
{
bool snaptogrid = General . Interface . ShiftState ^ General . Interface . SnapToGrid ;
bool snaptonearest = General . Interface . CtrlState ^ General . Interface . AutoMerge ;
2016-04-21 21:00:58 +00:00
DrawnVertex v = DrawGeometryMode . GetCurrentPosition ( mousemappos , snaptonearest , snaptogrid , false , false , renderer , new List < DrawnVertex > ( ) ) ;
2009-04-19 18:07:22 +00:00
drawmode . DrawPointAt ( v ) ;
}
General . Editing . ChangeMode ( drawmode ) ;
}
[BeginAction("makedoor")]
public void MakeDoor ( )
{
2015-03-23 18:34:10 +00:00
// Anything selected?
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( true ) ;
//mxd. Should we use highlighted item?
if ( orderedselection . Count = = 0 & & highlighted ! = null )
2009-04-19 18:07:22 +00:00
{
2015-03-23 18:34:10 +00:00
orderedselection . Add ( highlighted ) ;
2009-04-19 18:07:22 +00:00
}
if ( orderedselection . Count > 0 )
{
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
string doortex = BuilderPlug . Me . MakeDoor . DoorTexture ;
string tracktex = BuilderPlug . Me . MakeDoor . TrackTexture ;
string ceiltex = BuilderPlug . Me . MakeDoor . CeilingTexture ;
2009-04-19 18:07:22 +00:00
string floortex = null ;
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
bool resetoffsets = BuilderPlug . Me . MakeDoor . ResetOffsets ;
2017-04-03 08:20:40 +00:00
bool applyactionspecials = BuilderPlug . Me . MakeDoor . ApplyActionSpecials ;
bool applytag = BuilderPlug . Me . MakeDoor . ApplyTag ;
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
// Find floor texture
2017-04-03 08:20:40 +00:00
foreach ( Sector s in orderedselection )
2009-04-19 18:07:22 +00:00
{
if ( floortex = = null ) floortex = s . FloorTexture ; else if ( floortex ! = s . FloorTexture ) floortex = "" ;
}
// Show the dialog
MakeDoorForm form = new MakeDoorForm ( ) ;
2017-04-03 08:20:40 +00:00
if ( form . Show ( General . Interface , doortex , tracktex , ceiltex , floortex , resetoffsets , applyactionspecials , applytag ) = = DialogResult . OK )
2009-04-19 18:07:22 +00:00
{
doortex = form . DoorTexture ;
2012-04-14 12:22:19 +00:00
tracktex = form . TrackTexture ;
2009-04-19 18:07:22 +00:00
ceiltex = form . CeilingTexture ;
floortex = form . FloorTexture ;
2012-04-14 12:22:19 +00:00
resetoffsets = form . ResetOffsets ;
2017-04-03 08:20:40 +00:00
applyactionspecials = form . ApplyActionSpecials ;
applytag = form . ApplyTag ;
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
//mxd. Store new settings
2017-04-03 08:20:40 +00:00
BuilderPlug . Me . MakeDoor = new BuilderPlug . MakeDoorSettings ( doortex , tracktex , ceiltex , resetoffsets , applyactionspecials , applytag ) ;
2009-04-19 18:07:22 +00:00
// Create undo
General . Map . UndoRedo . CreateUndo ( "Make door (" + doortex + ")" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Created a " + doortex + " door." ) ;
// Go for all selected sectors
foreach ( Sector s in orderedselection )
{
// Lower the ceiling down to the floor
s . CeilHeight = s . FloorHeight ;
// Make a unique tag (not sure if we need it yet, depends on the args)
int tag = General . Map . Map . GetNewTag ( ) ;
2017-04-03 08:20:40 +00:00
// Go for all its sidedefs
2009-04-19 18:07:22 +00:00
foreach ( Sidedef sd in s . Sidedefs )
{
// Singlesided?
if ( sd . Other = = null )
{
// Make this a doortrak
sd . SetTextureHigh ( "-" ) ;
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 ( ! string . IsNullOrEmpty ( tracktex ) ) sd . SetTextureMid ( tracktex ) ;
2009-04-19 18:07:22 +00:00
sd . SetTextureLow ( "-" ) ;
// Set upper/lower unpegged flags
2009-06-11 21:21:20 +00:00
sd . Line . SetFlag ( General . Map . Config . UpperUnpeggedFlag , false ) ;
sd . Line . SetFlag ( General . Map . Config . LowerUnpeggedFlag , true ) ;
2009-04-19 18:07:22 +00:00
}
else
{
// Set textures
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 ( ! string . IsNullOrEmpty ( floortex ) ) s . SetFloorTexture ( floortex ) ;
if ( ! string . IsNullOrEmpty ( ceiltex ) ) s . SetCeilTexture ( ceiltex ) ;
if ( ! string . IsNullOrEmpty ( doortex ) ) sd . Other . SetTextureHigh ( doortex ) ;
2009-04-19 18:07:22 +00:00
// Set upper/lower unpegged flags
2009-06-11 21:21:20 +00:00
sd . Line . SetFlag ( General . Map . Config . UpperUnpeggedFlag , false ) ;
sd . Line . SetFlag ( General . Map . Config . LowerUnpeggedFlag , false ) ;
2009-04-19 18:07:22 +00:00
2017-04-03 08:20:40 +00:00
if ( applyactionspecials )
{
// Get door linedef type from config
sd . Line . Action = General . Map . Config . MakeDoorAction ;
// Set activation type
sd . Line . Activate = General . Map . Config . MakeDoorActivate ;
// Set the flags for player repeatable activation
foreach ( var flagpair in General . Map . Config . MakeDoorFlags )
sd . Line . SetFlag ( flagpair . Key , flagpair . Value ) ;
}
2012-04-14 12:22:19 +00:00
2017-04-03 08:20:40 +00:00
if ( applytag )
{
//If tag checkbox is checked, apply our new tag no matter what happens next
s . Tag = tag ;
}
2012-04-14 12:22:19 +00:00
2009-04-19 18:07:22 +00:00
// Set the linedef args
for ( int i = 0 ; i < Linedef . NUM_ARGS ; i + + )
{
// A -1 arg indicates that the arg must be set to the new sector tag
// and only in this case we set the tag on the sector, because only
// then we know for sure that we need a tag.
if ( General . Map . Config . MakeDoorArgs [ i ] = = - 1 )
{
sd . Line . Args [ i ] = tag ;
s . Tag = tag ;
}
else
{
sd . Line . Args [ i ] = General . Map . Config . MakeDoorArgs [ i ] ;
}
}
// Make sure the line is facing outwards
if ( sd . IsFront )
{
sd . Line . FlipVertices ( ) ;
sd . Line . FlipSidedefs ( ) ;
}
}
2012-04-14 12:22:19 +00:00
// Reset the texture offsets if required
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 ( resetoffsets )
2012-04-14 12:22:19 +00:00
{
sd . OffsetX = 0 ;
sd . OffsetY = 0 ;
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 ( sd . Other ! = null )
2012-04-14 12:22:19 +00:00
{
sd . Other . OffsetX = 0 ;
sd . Other . OffsetY = 0 ;
}
}
2009-04-19 18:07:22 +00:00
}
}
// When a single sector was selected, deselect it now
2015-03-23 18:34:10 +00:00
if ( orderedselection . Count = = 1 ) ClearSelection ( ) ; //mxd
General . Map . Data . UpdateUsedTextures ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
// Done
form . Dispose ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
2014-03-03 09:52:55 +00:00
else //mxd
{
2022-11-06 14:08:22 +00:00
General . ToastManager . ShowToast ( "makedoor" , ToastType . WARNING , "Couldn't create door" , "You need to highlight or select at least one sector to create a door." ) ;
2014-03-03 09:52:55 +00:00
}
2009-04-19 18:07:22 +00:00
}
[BeginAction("deleteitem", BaseAction = true)]
public void DeleteItem ( )
{
2015-11-03 08:54:56 +00:00
//mxd. Make list of selected things
List < Thing > selectedthings = ( BuilderPlug . Me . SyncronizeThingEdit ? new List < Thing > ( General . Map . Map . GetSelectedThings ( true ) ) : new List < Thing > ( ) ) ;
2009-04-19 18:07:22 +00:00
// Make list of selected sectors
2015-11-03 08:54:56 +00:00
List < Sector > selectedsectors = new List < Sector > ( General . Map . Map . GetSelectedSectors ( true ) ) ;
if ( ( selectedsectors . Count = = 0 ) & & ( highlighted ! = null ) & & ! highlighted . IsDisposed )
2009-04-19 18:07:22 +00:00
{
2015-11-03 08:54:56 +00:00
selectedsectors . Add ( highlighted ) ;
//mxd. Add things?
if ( BuilderPlug . Me . SyncronizeThingEdit )
2009-04-19 18:07:22 +00:00
{
2015-12-13 19:18:09 +00:00
foreach ( Thing t in General . Map . Map . Things )
2015-11-03 08:54:56 +00:00
{
if ( t . Sector = = null ) t . DetermineSector ( ) ;
if ( t . Sector = = highlighted ) selectedthings . Add ( t ) ;
}
2009-04-19 18:07:22 +00:00
}
2015-11-03 08:54:56 +00:00
}
if ( selectedsectors . Count = = 0 & & selectedthings . Count = = 0 ) return ; //mxd
//mxd. Create undo info text
List < string > info = new List < string > ( ) ;
2015-12-28 15:01:53 +00:00
//mxd. Create sectors info text
2015-11-03 08:54:56 +00:00
if ( selectedsectors . Count > 1 )
info . Add ( selectedsectors . Count + " sectors" ) ;
else
info . Add ( "a sector" ) ;
//mxd. Create things info text
if ( selectedthings . Count > 1 )
info . Add ( selectedthings . Count + " things" ) ;
2015-12-28 15:01:53 +00:00
else if ( selectedthings . Count = = 1 )
2015-11-03 08:54:56 +00:00
info . Add ( "a thing" ) ;
2009-04-19 18:07:22 +00:00
2015-11-03 08:54:56 +00:00
//mxd. Make undo
string rest = string . Join ( " and " , info . ToArray ( ) ) ;
General . Map . UndoRedo . CreateUndo ( "Delete " + rest ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Deleted " + rest + "." ) ;
//mxd. Delete things
if ( selectedthings . Count > 0 )
{
DeleteThings ( selectedthings ) ;
General . Map . ThingsFilter . Update ( ) ;
}
// Anything to do?
if ( selectedsectors . Count > 0 )
{
2013-12-13 09:31:18 +00:00
General . Map . Map . BeginAddRemove ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Dispose selected sectors
2015-11-03 08:54:56 +00:00
foreach ( Sector s in selectedsectors )
2009-04-19 18:07:22 +00:00
{
2013-12-13 09:31:18 +00:00
//mxd. Get all the linedefs
List < Linedef > lines = new List < Linedef > ( s . Sidedefs . Count ) ;
foreach ( Sidedef side in s . Sidedefs ) lines . Add ( side . Line ) ;
2009-04-19 18:07:22 +00:00
// Dispose the sector
s . Dispose ( ) ;
// Check all the lines
for ( int i = lines . Count - 1 ; i > = 0 ; i - - )
{
// If the line has become orphaned, remove it
if ( ( lines [ i ] . Front = = null ) & & ( lines [ i ] . Back = = null ) )
{
// Remove line
lines [ i ] . Dispose ( ) ;
}
else
{
// If the line only has a back side left, flip the line and sides
if ( ( lines [ i ] . Front = = null ) & & ( lines [ i ] . Back ! = null ) )
{
lines [ i ] . FlipVertices ( ) ;
lines [ i ] . FlipSidedefs ( ) ;
}
2013-03-18 13:52:27 +00:00
//mxd. Check textures.
2014-12-03 23:15:26 +00:00
if ( lines [ i ] . Front . MiddleRequired ( ) & & lines [ i ] . Front . LongMiddleTexture = = MapSet . EmptyLongName )
{
if ( lines [ i ] . Front . LongHighTexture ! = MapSet . EmptyLongName )
{
2013-03-18 13:52:27 +00:00
lines [ i ] . Front . SetTextureMid ( lines [ i ] . Front . HighTexture ) ;
2014-12-03 23:15:26 +00:00
}
else if ( lines [ i ] . Front . LongLowTexture ! = MapSet . EmptyLongName )
{
2013-03-18 13:52:27 +00:00
lines [ i ] . Front . SetTextureMid ( lines [ i ] . Front . LowTexture ) ;
}
}
//mxd. Do we still need high/low textures?
2014-01-08 09:46:57 +00:00
lines [ i ] . Front . RemoveUnneededTextures ( false ) ;
2009-04-19 18:07:22 +00:00
// Update sided flags
lines [ i ] . ApplySidedFlags ( ) ;
}
}
}
2013-12-13 09:31:18 +00:00
General . Map . Map . EndAddRemove ( ) ; //mxd
2020-07-27 18:18:33 +00:00
// Recreate the blockmap since it shouldn't include the deleted sectors anymore
CreateBlockmap ( ) ;
2021-04-22 14:12:14 +00:00
// Clear the cache of things that already got their sector determined
2021-04-22 19:10:10 +00:00
determinedsectorthings = new ConcurrentDictionary < Thing , bool > ( ) ;
2015-11-03 08:54:56 +00:00
}
2013-12-13 09:31:18 +00:00
2015-11-03 08:54:56 +00:00
if ( selectedthings . Count > 0 | | selectedsectors . Count > 0 )
{
2009-04-19 18:07:22 +00:00
// Update cache values
General . Map . IsChanged = true ;
General . Map . Map . Update ( ) ;
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Make text labels for sectors
SetupLabels ( ) ;
UpdateSelectedLabels ( ) ;
// 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
2009-04-19 18:07:22 +00:00
General . Interface . RedrawDisplay ( ) ;
}
}
2014-01-08 09:46:57 +00:00
[BeginAction("dissolveitem", BaseAction = true)] //mxd
2014-12-03 23:15:26 +00:00
public void DissolveItem ( )
{
2014-02-18 14:04:14 +00:00
//TODO handle this differently?..
2014-01-08 09:46:57 +00:00
DeleteItem ( ) ;
}
2009-04-19 18:07:22 +00:00
// This joins sectors together and keeps all lines
[BeginAction("joinsectors")]
public void JoinSectors ( )
{
// Worth our money?
2015-12-13 19:18:09 +00:00
ICollection < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) ; //mxd
if ( selected . Count > 1 )
2009-04-19 18:07:22 +00:00
{
// Make undo
2015-12-13 19:18:09 +00:00
General . Map . UndoRedo . CreateUndo ( "Join " + selected . Count + " sectors" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Joined " + selected . Count + " sectors." ) ;
2009-04-19 18:07:22 +00:00
2015-12-13 19:18:09 +00:00
//mxd. Things may require updating
List < Thing > affectedthings = new List < Thing > ( ) ;
foreach ( Thing t in General . Map . Map . Things )
if ( t . Sector ! = null & & selected . Contains ( t . Sector ) ) affectedthings . Add ( t ) ;
2009-04-19 18:07:22 +00:00
// Merge
JoinMergeSectors ( false ) ;
2015-12-13 19:18:09 +00:00
//mxd. Things may require updating
foreach ( Thing t in affectedthings ) t . DetermineSector ( ) ;
// Map was changed
2009-04-19 18:07:22 +00:00
General . Map . IsChanged = true ;
2015-02-13 19:59:14 +00:00
//mxd. Clear selection info
General . Interface . DisplayStatus ( StatusType . Selection , string . Empty ) ;
2020-11-01 20:29:57 +00:00
// Recreate the blockmap
CreateBlockmap ( ) ;
2021-04-22 14:12:14 +00:00
// Clear the cache of things that already got their sector determined
2021-04-22 19:10:10 +00:00
determinedsectorthings = new ConcurrentDictionary < Thing , bool > ( ) ;
2021-04-22 14:12:14 +00:00
2015-02-13 19:59:14 +00:00
//mxd. Update
UpdateOverlaySurfaces ( ) ;
UpdateEffectLabels ( ) ;
2015-12-02 13:55:15 +00:00
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ;
2015-02-13 19:59:14 +00:00
2009-04-19 18:07:22 +00:00
// Redraw display
General . Interface . RedrawDisplay ( ) ;
}
}
// This joins sectors together and removes the lines in between
[BeginAction("mergesectors")]
public void MergeSectors ( )
{
// Worth our money?
2015-12-13 19:18:09 +00:00
ICollection < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) ; //mxd
if ( selected . Count > 1 )
2009-04-19 18:07:22 +00:00
{
// Make undo
2015-12-13 19:18:09 +00:00
General . Map . UndoRedo . CreateUndo ( "Merge " + selected . Count + " sectors" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Merged " + selected . Count + " sectors." ) ;
//mxd. Things may require updating
List < Thing > affectedthings = new List < Thing > ( ) ;
foreach ( Thing t in General . Map . Map . Things )
if ( t . Sector ! = null & & selected . Contains ( t . Sector ) ) affectedthings . Add ( t ) ;
2009-04-19 18:07:22 +00:00
// Merge
JoinMergeSectors ( true ) ;
2015-12-13 19:18:09 +00:00
//mxd. Things may require updating
foreach ( Thing t in affectedthings ) t . DetermineSector ( ) ;
// Map was changed
2009-04-19 18:07:22 +00:00
General . Map . IsChanged = true ;
2015-02-13 19:59:14 +00:00
//mxd. Clear selection info
General . Interface . DisplayStatus ( StatusType . Selection , string . Empty ) ;
2020-11-01 20:29:57 +00:00
2021-02-28 00:44:38 +00:00
if ( highlighted ! = null & & ! highlighted . IsDisposed )
highlightasso . Set ( highlighted ) ;
2020-11-01 20:29:57 +00:00
// Recreate the blockmap
CreateBlockmap ( ) ;
2021-04-22 14:12:14 +00:00
// Clear the cache of things that already got their sector determined
2021-04-22 19:10:10 +00:00
determinedsectorthings = new ConcurrentDictionary < Thing , bool > ( ) ;
2021-04-22 14:12:14 +00:00
2015-02-13 19:59:14 +00:00
//mxd. Update
UpdateOverlaySurfaces ( ) ;
UpdateEffectLabels ( ) ;
2015-12-02 13:55:15 +00:00
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ;
2015-02-13 19:59:14 +00:00
2009-04-19 18:07:22 +00:00
// Redraw display
General . Interface . RedrawDisplay ( ) ;
}
}
// Make gradient brightness
[BeginAction("gradientbrightness")]
public void MakeGradientBrightness ( )
{
// Need at least 3 selected sectors
// The first and last are not modified
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( true ) ;
2014-12-03 23:15:26 +00:00
if ( orderedselection . Count > 2 )
{
2013-03-18 13:52:27 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Created gradient brightness over selected sectors." ) ;
General . Map . UndoRedo . CreateUndo ( "Gradient brightness" ) ;
//mxd
Sector start = General . GetByIndex ( orderedselection , 0 ) ;
Sector end = General . GetByIndex ( orderedselection , orderedselection . Count - 1 ) ;
//mxd. Use UDMF light?
2015-01-16 21:38:42 +00:00
string mode = ( string ) BuilderPlug . Me . MenusForm . GradientModeMenu . SelectedItem ;
InterpolationTools . Mode interpolationmode = ( InterpolationTools . Mode ) BuilderPlug . Me . MenusForm . GradientInterpolationMenu . SelectedIndex ;
2015-01-29 12:14:45 +00:00
if ( General . Map . UDMF & & mode ! = MenusForm . BrightnessGradientModes . Sectors )
2014-12-03 23:15:26 +00:00
{
2015-01-16 21:38:42 +00:00
if ( mode = = MenusForm . BrightnessGradientModes . Ceilings | | mode = = MenusForm . BrightnessGradientModes . Floors )
2014-12-03 23:15:26 +00:00
{
2015-01-16 21:38:42 +00:00
string lightKey ;
string lightAbsKey ;
int startbrightness , endbrightness ;
2013-03-18 13:52:27 +00:00
2015-01-16 21:38:42 +00:00
if ( mode = = MenusForm . BrightnessGradientModes . Ceilings )
2014-12-03 23:15:26 +00:00
{
2015-01-16 21:38:42 +00:00
lightKey = "lightceiling" ;
lightAbsKey = "lightceilingabsolute" ;
}
else //should be floors...
2014-12-03 23:15:26 +00:00
{
2015-01-16 21:38:42 +00:00
lightKey = "lightfloor" ;
lightAbsKey = "lightfloorabsolute" ;
2013-03-18 13:52:27 +00:00
}
2015-01-16 21:38:42 +00:00
//get total brightness of start sector
if ( start . Fields . GetValue ( lightAbsKey , false ) )
startbrightness = start . Fields . GetValue ( lightKey , 0 ) ;
else
startbrightness = Math . Min ( 255 , Math . Max ( 0 , start . Brightness + start . Fields . GetValue ( lightKey , 0 ) ) ) ;
2013-09-11 08:49:45 +00:00
2015-01-16 21:38:42 +00:00
//get total brightness of end sector
if ( end . Fields . GetValue ( lightAbsKey , false ) )
endbrightness = end . Fields . GetValue ( lightKey , 0 ) ;
else
endbrightness = Math . Min ( 255 , Math . Max ( 0 , end . Brightness + end . Fields . GetValue ( lightKey , 0 ) ) ) ;
2013-09-11 08:49:45 +00:00
// Go for all sectors in between first and last
int index = 0 ;
2014-12-03 23:15:26 +00:00
foreach ( Sector s in orderedselection )
{
2013-09-11 08:49:45 +00:00
s . Fields . BeforeFieldsChange ( ) ;
2020-08-04 14:25:49 +00:00
double u = index / ( double ) ( orderedselection . Count - 1 ) ;
2020-05-22 20:30:32 +00:00
double b = Math . Round ( InterpolationTools . Interpolate ( startbrightness , endbrightness , u , interpolationmode ) ) ;
2015-01-16 21:38:42 +00:00
//absolute flag set?
if ( s . Fields . GetValue ( lightAbsKey , false ) )
{
if ( s . Fields . ContainsKey ( lightKey ) )
s . Fields [ lightKey ] . Value = ( int ) b ;
else
s . Fields . Add ( lightKey , new UniValue ( UniversalType . Integer , ( int ) b ) ) ;
}
else
{
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
UniFields . SetInteger ( s . Fields , lightKey , ( int ) b - s . Brightness , 0 ) ;
2015-01-16 21:38:42 +00:00
}
2015-01-16 23:37:20 +00:00
s . UpdateNeeded = true ;
2013-09-11 08:49:45 +00:00
index + + ;
}
2015-01-16 21:38:42 +00:00
}
else if ( mode = = MenusForm . BrightnessGradientModes . Fade )
{
ApplyColorGradient ( orderedselection , start , end , interpolationmode , "fadecolor" , 0 ) ;
}
else if ( mode = = MenusForm . BrightnessGradientModes . Light )
{
ApplyColorGradient ( orderedselection , start , end , interpolationmode , "lightcolor" , 0xFFFFFF ) ;
}
else if ( mode = = MenusForm . BrightnessGradientModes . LightAndFade )
{
ApplyColorGradient ( orderedselection , start , end , interpolationmode , "fadecolor" , 0 ) ;
ApplyColorGradient ( orderedselection , start , end , interpolationmode , "lightcolor" , 0xFFFFFF ) ;
2013-09-11 08:49:45 +00:00
}
2015-01-16 21:38:42 +00:00
}
2014-12-03 23:15:26 +00:00
else
{
2013-03-18 13:52:27 +00:00
// Go for all sectors in between first and last
int index = 0 ;
2014-12-03 23:15:26 +00:00
foreach ( Sector s in orderedselection )
{
2020-08-04 14:25:49 +00:00
double u = index / ( double ) ( orderedselection . Count - 1 ) ;
2016-06-03 20:22:07 +00:00
s . Brightness = ( int ) Math . Round ( InterpolationTools . Interpolate ( start . Brightness , end . Brightness , u , interpolationmode ) ) ; //mxd
2013-03-18 13:52:27 +00:00
index + + ;
}
2009-04-19 18:07:22 +00:00
}
2014-04-02 10:57:52 +00:00
// Update
General . Map . Map . Update ( ) ;
General . Interface . RedrawDisplay ( ) ;
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
2014-12-03 23:15:26 +00:00
}
else
{
2013-03-18 13:52:27 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "Select at least 3 sectors first!" ) ;
2009-04-19 18:07:22 +00:00
}
}
2015-01-16 21:38:42 +00:00
//mxd
2015-02-20 13:22:43 +00:00
private static void ApplyColorGradient ( ICollection < Sector > orderedselection , Sector start , Sector end , InterpolationTools . Mode interpolationmode , string key , int defaultvalue )
2015-01-16 21:38:42 +00:00
{
if ( ! start . Fields . ContainsKey ( key ) & & ! end . Fields . ContainsKey ( key ) )
{
2016-03-08 20:41:06 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "First or last selected sector must have the \"" + key + "\" property!" ) ;
2015-01-16 21:38:42 +00:00
}
else
{
2016-06-03 20:22:07 +00:00
PixelColor startcolor , endcolor ;
2015-02-20 13:22:43 +00:00
if ( key = = "fadecolor" )
{
2016-06-03 20:22:07 +00:00
startcolor = Tools . GetSectorFadeColor ( start ) ;
endcolor = Tools . GetSectorFadeColor ( end ) ;
2015-02-20 13:22:43 +00:00
}
else
{
2016-06-03 20:22:07 +00:00
startcolor = PixelColor . FromInt ( start . Fields . GetValue ( key , defaultvalue ) ) ;
endcolor = PixelColor . FromInt ( end . Fields . GetValue ( key , defaultvalue ) ) ;
2015-02-20 13:22:43 +00:00
}
2015-01-16 21:38:42 +00:00
// Go for all sectors in between first and last
int index = 0 ;
foreach ( Sector s in orderedselection )
{
2015-02-20 13:22:43 +00:00
if ( index > 0 & & index < orderedselection . Count - 1 )
{
s . Fields . BeforeFieldsChange ( ) ;
2016-06-03 20:22:07 +00:00
float u = index / ( orderedselection . Count - 1.0f ) ;
2016-06-20 13:36:10 +00:00
int c = InterpolationTools . InterpolateColor ( startcolor , endcolor , u , interpolationmode ) . WithAlpha ( 0 ) . ToInt ( ) ; // No alpha here!
2015-02-20 13:22:43 +00:00
2016-06-03 20:22:07 +00:00
UniFields . SetInteger ( s . Fields , key , c , defaultvalue ) ;
2015-02-20 13:22:43 +00:00
s . UpdateNeeded = true ;
}
2015-01-16 21:38:42 +00:00
index + + ;
}
}
}
2009-04-19 18:07:22 +00:00
// Make gradient floors
[BeginAction("gradientfloors")]
public void MakeGradientFloors ( )
{
// Need at least 3 selected sectors
// The first and last are not modified
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( true ) ;
2014-12-03 23:15:26 +00:00
if ( orderedselection . Count > 2 )
{
2013-03-18 13:52:27 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Created gradient floor heights over selected sectors." ) ;
General . Map . UndoRedo . CreateUndo ( "Gradient floor heights" ) ;
2015-01-16 21:38:42 +00:00
int startlevel = General . GetByIndex ( orderedselection , 0 ) . FloorHeight ;
int endlevel = General . GetByIndex ( orderedselection , orderedselection . Count - 1 ) . FloorHeight ;
InterpolationTools . Mode interpolationmode = ( InterpolationTools . Mode ) BuilderPlug . Me . MenusForm . GradientInterpolationMenu . SelectedIndex ; //mxd
2009-04-19 18:07:22 +00:00
// Go for all sectors in between first and last
int index = 0 ;
2014-12-03 23:15:26 +00:00
foreach ( Sector s in orderedselection )
{
2013-09-16 11:44:47 +00:00
float u = index / ( float ) ( orderedselection . Count - 1 ) ;
2016-06-03 20:22:07 +00:00
s . FloorHeight = ( int ) Math . Round ( InterpolationTools . Interpolate ( startlevel , endlevel , u , interpolationmode ) ) ; //mxd
2009-04-19 18:07:22 +00:00
index + + ;
}
2014-04-02 10:57:52 +00:00
// Update
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
2014-12-03 23:15:26 +00:00
}
else
{
2013-03-18 13:52:27 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "Select at least 3 sectors first!" ) ;
2009-04-19 18:07:22 +00:00
}
}
// Make gradient ceilings
[BeginAction("gradientceilings")]
public void MakeGradientCeilings ( )
{
// Need at least 3 selected sectors
// The first and last are not modified
ICollection < Sector > orderedselection = General . Map . Map . GetSelectedSectors ( true ) ;
2014-12-03 23:15:26 +00:00
if ( orderedselection . Count > 2 )
{
2013-03-18 13:52:27 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Created gradient ceiling heights over selected sectors." ) ;
General . Map . UndoRedo . CreateUndo ( "Gradient ceiling heights" ) ;
2015-01-16 21:38:42 +00:00
int startlevel = General . GetByIndex ( orderedselection , 0 ) . CeilHeight ;
int endlevel = General . GetByIndex ( orderedselection , orderedselection . Count - 1 ) . CeilHeight ;
InterpolationTools . Mode interpolationmode = ( InterpolationTools . Mode ) BuilderPlug . Me . MenusForm . GradientInterpolationMenu . SelectedIndex ; //mxd
2009-04-19 18:07:22 +00:00
// Go for all sectors in between first and last
int index = 0 ;
2014-12-03 23:15:26 +00:00
foreach ( Sector s in orderedselection )
{
2014-02-21 14:42:12 +00:00
float u = ( float ) index / ( orderedselection . Count - 1 ) ;
2016-06-03 20:22:07 +00:00
s . CeilHeight = ( int ) Math . Round ( InterpolationTools . Interpolate ( startlevel , endlevel , u , interpolationmode ) ) ;
2009-04-19 18:07:22 +00:00
index + + ;
}
2014-04-02 10:57:52 +00:00
// Update
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
2014-12-03 23:15:26 +00:00
}
else
{
2013-03-18 13:52:27 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "Select at least 3 sectors first!" ) ;
2009-04-19 18:07:22 +00:00
}
}
2014-01-13 08:06:56 +00:00
// Change heights
[BeginAction("lowerfloor8")]
2014-12-03 23:15:26 +00:00
public void LowerFloors8 ( )
{
2014-04-02 10:57:52 +00:00
// Get selection
ICollection < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) ;
if ( selected . Count = = 0 & & highlighted ! = null & & ! highlighted . IsDisposed )
selected . Add ( highlighted ) ;
2014-12-03 23:15:26 +00:00
if ( selected . Count = = 0 )
{
2014-04-02 10:57:52 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
// Make undo
2014-01-13 08:06:56 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Lowered floor heights by 8mp." ) ;
2014-04-02 10:57:52 +00:00
General . Map . UndoRedo . CreateUndo ( "Floor heights change" , this , UndoGroup . FloorHeightChange , CreateSelectionCRC ( selected ) ) ;
2014-01-13 08:06:56 +00:00
// Change heights
2014-12-03 23:15:26 +00:00
foreach ( Sector s in selected ) s . FloorHeight - = 8 ;
2014-01-13 08:06:56 +00:00
// Update
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
}
// Change heights
[BeginAction("raisefloor8")]
2014-12-03 23:15:26 +00:00
public void RaiseFloors8 ( )
{
2014-04-02 10:57:52 +00:00
// Get selection
ICollection < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) ;
if ( selected . Count = = 0 & & highlighted ! = null & & ! highlighted . IsDisposed )
selected . Add ( highlighted ) ;
2014-12-03 23:15:26 +00:00
if ( selected . Count = = 0 )
{
2014-04-02 10:57:52 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
// Make undo
2014-01-13 08:06:56 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Raised floor heights by 8mp." ) ;
2014-04-02 10:57:52 +00:00
General . Map . UndoRedo . CreateUndo ( "Floor heights change" , this , UndoGroup . FloorHeightChange , CreateSelectionCRC ( selected ) ) ;
2014-01-13 08:06:56 +00:00
// Change heights
2014-12-03 23:15:26 +00:00
foreach ( Sector s in selected ) s . FloorHeight + = 8 ;
2014-01-13 08:06:56 +00:00
// Update
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
}
// Change heights
[BeginAction("lowerceiling8")]
2014-12-03 23:15:26 +00:00
public void LowerCeilings8 ( )
{
2014-04-02 10:57:52 +00:00
// Get selection
ICollection < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) ;
if ( ( selected . Count = = 0 ) & & ( highlighted ! = null ) & & ! highlighted . IsDisposed )
selected . Add ( highlighted ) ;
2014-12-03 23:15:26 +00:00
if ( selected . Count = = 0 )
{
2014-04-02 10:57:52 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
// Make undo
2014-01-13 08:06:56 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Lowered ceiling heights by 8mp." ) ;
2014-04-02 10:57:52 +00:00
General . Map . UndoRedo . CreateUndo ( "Ceiling heights change" , this , UndoGroup . CeilingHeightChange , CreateSelectionCRC ( selected ) ) ;
2014-01-13 08:06:56 +00:00
// Change heights
2014-12-03 23:15:26 +00:00
foreach ( Sector s in selected ) s . CeilHeight - = 8 ;
2014-01-13 08:06:56 +00:00
// Update
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
}
// Change heights
[BeginAction("raiseceiling8")]
2014-12-03 23:15:26 +00:00
public void RaiseCeilings8 ( )
{
2014-04-02 10:57:52 +00:00
// Get selection
ICollection < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) ;
if ( selected . Count = = 0 & & highlighted ! = null & & ! highlighted . IsDisposed )
selected . Add ( highlighted ) ;
2014-12-03 23:15:26 +00:00
if ( selected . Count = = 0 )
{
2014-04-02 10:57:52 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
// Make undo
2014-01-13 08:06:56 +00:00
General . Interface . DisplayStatus ( StatusType . Action , "Raised ceiling heights by 8mp." ) ;
2014-04-02 10:57:52 +00:00
General . Map . UndoRedo . CreateUndo ( "Ceiling heights change" , this , UndoGroup . CeilingHeightChange , CreateSelectionCRC ( selected ) ) ;
2014-01-13 08:06:56 +00:00
// Change heights
2014-12-03 23:15:26 +00:00
foreach ( Sector s in selected ) s . CeilHeight + = 8 ;
2014-01-13 08:06:56 +00:00
// Update
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
}
2013-09-16 11:44:47 +00:00
//mxd. Raise brightness
[BeginAction("raisebrightness8")]
2014-12-03 23:15:26 +00:00
public void RaiseBrightness8 ( )
{
2014-04-02 10:57:52 +00:00
// Get selection
ICollection < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) ;
if ( ( selected . Count = = 0 ) & & ( highlighted ! = null ) & & ! highlighted . IsDisposed )
selected . Add ( highlighted ) ;
2014-12-03 23:15:26 +00:00
if ( selected . Count = = 0 )
{
2014-04-02 10:57:52 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
// Make undo
2015-05-11 20:17:50 +00:00
Sector first = General . GetByIndex ( selected , 0 ) ; //mxd
int diff = General . Map . Config . BrightnessLevels . GetNextHigher ( first . Brightness ) - first . Brightness ; //mxd
General . Interface . DisplayStatus ( StatusType . Action , "Raised sector brightness by " + diff + "." ) ;
2014-04-02 10:57:52 +00:00
General . Map . UndoRedo . CreateUndo ( "Sector brightness change" , this , UndoGroup . SectorBrightnessChange , CreateSelectionCRC ( selected ) ) ;
2009-04-19 18:07:22 +00:00
// Change heights
2014-12-03 23:15:26 +00:00
foreach ( Sector s in selected )
{
2013-09-16 11:44:47 +00:00
s . Brightness = General . Map . Config . BrightnessLevels . GetNextHigher ( s . Brightness ) ;
s . UpdateNeeded = true ;
s . UpdateCache ( ) ;
2009-04-19 18:07:22 +00:00
}
// Update
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
2013-09-16 11:44:47 +00:00
// Redraw
General . Interface . RedrawDisplay ( ) ;
2009-04-19 18:07:22 +00:00
}
2013-09-16 11:44:47 +00:00
//mxd. Lower brightness
[BeginAction("lowerbrightness8")]
2014-12-03 23:15:26 +00:00
public void LowerBrightness8 ( )
{
2014-04-02 10:57:52 +00:00
// Get selection
ICollection < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) ;
if ( selected . Count = = 0 & & highlighted ! = null & & ! highlighted . IsDisposed )
selected . Add ( highlighted ) ;
2015-12-28 15:01:53 +00:00
if ( selected . Count = = 0 )
2014-12-03 23:15:26 +00:00
{
2014-04-02 10:57:52 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
// Make undo
2015-05-11 20:17:50 +00:00
Sector first = General . GetByIndex ( selected , 0 ) ; //mxd
int diff = first . Brightness - General . Map . Config . BrightnessLevels . GetNextLower ( first . Brightness ) ; //mxd
General . Interface . DisplayStatus ( StatusType . Action , "Lowered sector brightness by " + diff + "." ) ;
2014-04-02 10:57:52 +00:00
General . Map . UndoRedo . CreateUndo ( "Sector brightness change" , this , UndoGroup . SectorBrightnessChange , CreateSelectionCRC ( selected ) ) ;
2009-04-19 18:07:22 +00:00
// Change heights
2014-12-03 23:15:26 +00:00
foreach ( Sector s in selected )
{
2013-09-16 11:44:47 +00:00
s . Brightness = General . Map . Config . BrightnessLevels . GetNextLower ( s . Brightness ) ;
s . UpdateNeeded = true ;
s . UpdateCache ( ) ;
2009-04-19 18:07:22 +00:00
}
// Update
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
2013-09-16 11:44:47 +00:00
// Redraw
General . Interface . RedrawDisplay ( ) ;
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
General . Interface . DisplayStatus ( StatusType . Selection , string . Empty ) ;
2013-07-09 11:29:10 +00:00
2009-04-19 18:07:22 +00:00
// Clear labels
foreach ( TextLabel [ ] labelarray in labels . Values )
foreach ( TextLabel l in labelarray ) l . Text = "" ;
2014-12-03 23:15:26 +00:00
UpdateOverlaySurfaces ( ) ; //mxd
UpdateEffectLabels ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Redraw
General . Interface . RedrawDisplay ( ) ;
}
2013-09-11 13:14:45 +00:00
[BeginAction("placethings")] //mxd
2014-12-03 23:15:26 +00:00
public void PlaceThings ( )
{
2013-09-11 13:14:45 +00:00
// Make list of selected sectors
ICollection < Sector > sectors = General . Map . Map . GetSelectedSectors ( true ) ;
List < Vector2D > positions = new List < Vector2D > ( ) ;
2014-12-03 23:15:26 +00:00
if ( sectors . Count = = 0 )
{
if ( highlighted ! = null & & ! highlighted . IsDisposed )
{
2013-09-11 13:14:45 +00:00
sectors . 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 ;
}
}
// Make list of suitable positions
2014-12-03 23:15:26 +00:00
foreach ( Sector s in sectors )
{
2013-09-11 13:57:27 +00:00
Vector2D pos = ( s . Labels . Count > 0 ? s . Labels [ 0 ] . position : new Vector2D ( s . BBox . X + s . BBox . Width / 2 , s . BBox . Y + s . BBox . Height / 2 ) ) ;
if ( ! positions . Contains ( pos ) ) positions . Add ( pos ) ;
2013-09-11 13:14:45 +00:00
}
2014-12-03 23:15:26 +00:00
if ( positions . Count < 1 )
{
2013-09-11 13:14:45 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "Unable to get vertex positions from selection!" ) ;
return ;
}
2014-12-03 23:15:26 +00:00
PlaceThingsAtPositions ( positions ) ;
2013-09-11 13:14:45 +00:00
}
2014-04-02 10:57:52 +00:00
//mxd. rotate clockwise
[BeginAction("rotateclockwise")]
2014-12-03 23:15:26 +00:00
public void RotateCW ( )
{
RotateTextures ( 5 ) ;
2014-04-02 10:57:52 +00:00
}
//mxd. rotate counterclockwise
[BeginAction("rotatecounterclockwise")]
2014-12-03 23:15:26 +00:00
public void RotateCCW ( )
{
RotateTextures ( - 5 ) ;
2014-04-02 10:57:52 +00:00
}
//mxd
2014-12-03 23:15:26 +00:00
private void RotateTextures ( float increment )
{
2015-12-28 15:01:53 +00:00
if ( ! General . Map . UDMF )
2014-12-03 23:15:26 +00:00
{
2014-04-02 10:57:52 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action works only in UDMF map format!" ) ;
return ;
}
// Make list of selected sectors
ICollection < Sector > sectors = General . Map . Map . GetSelectedSectors ( true ) ;
if ( sectors . Count = = 0 & & highlighted ! = null & & ! highlighted . IsDisposed )
sectors . Add ( highlighted ) ;
2014-12-03 23:15:26 +00:00
if ( sectors . Count = = 0 )
{
2014-04-02 10:57:52 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
string targets ;
string target ;
2015-12-28 15:01:53 +00:00
switch ( General . Map . Renderer2D . ViewMode )
2014-12-03 23:15:26 +00:00
{
2014-04-02 10:57:52 +00:00
case ViewMode . FloorTextures :
target = " a floor" ;
targets = " floors" ;
break ;
case ViewMode . CeilingTextures :
target = " a ceiling" ;
targets = " ceilings" ;
break ;
default :
target = " a floor and a ceiling" ;
targets = " floors and ceilings" ;
break ;
}
// Make undo
2014-12-03 23:15:26 +00:00
if ( sectors . Count > 1 )
{
2014-04-02 10:57:52 +00:00
General . Map . UndoRedo . CreateUndo ( "Rotate " + sectors . Count + targets , this , UndoGroup . TextureRotationChange , CreateSelectionCRC ( sectors ) ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Rotated " + sectors . Count + targets + "." ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2014-04-02 10:57:52 +00:00
General . Map . UndoRedo . CreateUndo ( "Rotate" + target , this , UndoGroup . TextureRotationChange , CreateSelectionCRC ( sectors ) ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Rotated" + target + "." ) ;
}
//rotate stuff
2015-12-28 15:01:53 +00:00
foreach ( Sector s in sectors )
2014-12-03 23:15:26 +00:00
{
2014-04-02 10:57:52 +00:00
s . Fields . BeforeFieldsChange ( ) ;
//floor
2016-05-04 14:02:13 +00:00
if ( General . Map . Renderer2D . ViewMode ! = ViewMode . CeilingTextures )
2014-12-03 23:15:26 +00:00
{
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
UniFields . SetFloat ( s . Fields , "rotationfloor" , General . ClampAngle ( UniFields . GetFloat ( s . Fields , "rotationfloor" ) + increment ) ) ;
2014-04-02 10:57:52 +00:00
s . UpdateNeeded = true ;
}
//ceiling
2016-05-04 14:02:13 +00:00
if ( General . Map . Renderer2D . ViewMode ! = ViewMode . FloorTextures )
2014-12-03 23:15:26 +00:00
{
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
UniFields . SetFloat ( s . Fields , "rotationceiling" , General . ClampAngle ( UniFields . GetFloat ( s . Fields , "rotationceiling" ) + increment ) ) ;
2014-04-02 10:57:52 +00:00
s . UpdateNeeded = true ;
}
}
// Redraw screen
General . Map . Map . Update ( ) ;
General . Interface . RedrawDisplay ( ) ;
General . Interface . RefreshInfo ( ) ;
}
2014-05-08 09:24:32 +00:00
//mxd
[BeginAction("selectsimilar")]
2014-12-03 23:15:26 +00:00
public void SelectSimilar ( )
{
2014-05-08 09:24:32 +00:00
ICollection < Sector > selection = General . Map . Map . GetSelectedSectors ( 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
}
2009-04-19 18:07:22 +00:00
2014-07-07 14:17:49 +00:00
//mxd
[BeginAction("fliplinedefs")]
public void FlipLinedefs ( )
2016-03-14 10:25:27 +00:00
{
// Get selection
ICollection < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) ;
if ( selected . Count = = 0 & & highlighted ! = null & & ! highlighted . IsDisposed )
selected . Add ( highlighted ) ;
if ( selected . Count = = 0 )
{
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
// Make undo
if ( selected . Count > 1 )
{
2016-07-20 19:17:31 +00:00
General . Map . UndoRedo . CreateUndo ( "Flip linedefs of " + selected . Count + " sectors" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Flipped linedefs of " + selected . Count + "sectors." ) ;
2016-03-14 10:25:27 +00:00
}
else
{
2016-07-20 19:17:31 +00:00
General . Map . UndoRedo . CreateUndo ( "Flip sector linedefs" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Flipped sector linedefs." ) ;
2016-03-14 10:25:27 +00:00
}
HashSet < Linedef > selectedlines = new HashSet < Linedef > ( ) ;
foreach ( Sector s in selected )
{
foreach ( Sidedef side in s . Sidedefs )
{
2016-07-20 19:17:31 +00:00
// Skip single-sided lines with only front side
if ( ! selectedlines . Contains ( side . Line ) & & ( side . Line . Back ! = null | | side . Line . Front = = null ) )
selectedlines . Add ( side . Line ) ;
2016-03-14 10:25:27 +00:00
}
}
// Flip all selected linedefs
foreach ( Linedef l in selectedlines )
{
l . FlipVertices ( ) ;
l . FlipSidedefs ( ) ;
}
// Redraw
General . Map . Map . Update ( ) ;
General . Map . IsChanged = true ;
General . Interface . RefreshInfo ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
//mxd
[BeginAction("alignlinedefs")]
public void AlignLinedefs ( )
2014-07-07 14:17:49 +00:00
{
// Get selection
ICollection < Sector > selection = General . Map . Map . GetSelectedSectors ( true ) ;
if ( selection . Count = = 0 & & highlighted ! = null & & ! highlighted . IsDisposed )
selection . Add ( highlighted ) ;
if ( selection . Count = = 0 )
{
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection!" ) ;
return ;
}
// Make undo
if ( selection . Count > 1 )
{
2016-03-14 10:25:27 +00:00
General . Map . UndoRedo . CreateUndo ( "Align linedefs of " + selection . Count + " sectors" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Aligned linedefs of " + selection . Count + "sectors." ) ;
2014-07-07 14:17:49 +00:00
}
else
{
2016-03-14 10:25:27 +00:00
General . Map . UndoRedo . CreateUndo ( "Align sector linedefs" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Aligned sector linedefs." ) ;
2014-07-07 14:17:49 +00:00
}
// Flip lines
Tools . FlipSectorLinedefs ( selection , false ) ;
// Redraw
General . Map . Map . Update ( ) ;
General . Map . IsChanged = true ;
General . Interface . RefreshInfo ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
2020-06-15 19:25:31 +00:00
[BeginAction("smartgridtransform", BaseAction = true)]
protected void SmartGridTransform ( )
{
General . Map . Grid . SetGridRotation ( 0.0 ) ;
General . Map . Grid . SetGridOrigin ( 0 , 0 ) ;
General . Map . GridVisibilityChanged ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
2023-06-09 09:17:01 +00:00
[BeginAction("changemapelementindex")]
private void ChangeMapElementIndex ( )
{
// Make list of selected linedefs
List < Sector > selected = General . Map . Map . GetSelectedSectors ( true ) . ToList ( ) ;
if ( ( selected . Count = = 0 ) & & ( highlighted ! = null ) & & ! highlighted . IsDisposed ) selected . Add ( highlighted ) ;
if ( selected . Count ! = 1 )
{
General . ToastManager . ShowToast ( ToastMessages . CHANGEMAPELEMENTINDEX , ToastType . WARNING , "Changing sector index failed" , "You need to select or highlight exactly 1 sector." ) ;
return ;
}
ChangeMapElementIndexForm f = new ChangeMapElementIndexForm ( "sector" , selected [ 0 ] . Index , General . Map . Map . Sectors . Count - 1 ) ;
if ( f . ShowDialog ( ) = = DialogResult . OK )
{
int newindex = f . GetNewIndex ( ) ;
int oldindex = selected [ 0 ] . Index ;
General . Map . UndoRedo . CreateUndo ( "Change sector index" ) ;
selected [ 0 ] . ChangeIndex ( newindex ) ;
General . ToastManager . ShowToast ( ToastMessages . CHANGEMAPELEMENTINDEX , ToastType . INFO , "Successfully change sector index" , $"Changed index of sector {oldindex} to {newindex}." ) ;
}
}
2009-04-19 18:07:22 +00:00
#endregion
}
}