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 ;
2014-01-23 13:55:03 +00:00
using System.Drawing ;
2009-04-19 18:07:22 +00:00
using System.Windows.Forms ;
using CodeImp.DoomBuilder.Windows ;
using CodeImp.DoomBuilder.Map ;
using CodeImp.DoomBuilder.Rendering ;
using CodeImp.DoomBuilder.Geometry ;
using CodeImp.DoomBuilder.Editing ;
using CodeImp.DoomBuilder.Actions ;
using CodeImp.DoomBuilder.Types ;
using CodeImp.DoomBuilder.Config ;
2013-05-30 12:52:27 +00:00
using CodeImp.DoomBuilder.GZBuilder.Tools ;
using CodeImp.DoomBuilder.Data ;
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder.BuilderModes
{
[ EditMode ( DisplayName = "Linedefs Mode" ,
SwitchAction = "linedefsmode" , // Action name used to switch to this mode
ButtonImage = "LinesMode.png" , // Image resource name for the button
ButtonOrder = int . MinValue + 100 , // 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 LinedefsMode : BaseClassicMode
{
#region = = = = = = = = = = = = = = = = = = Constants
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Highlighted item
private Linedef highlighted ;
private Association [ ] association = new Association [ Linedef . NUM_ARGS ] ;
private Association highlightasso = new Association ( ) ;
2014-01-23 13:55:03 +00:00
private Vector2D insertPreview = new Vector2D ( float . NaN , float . NaN ) ; //mxd
2009-04-19 18:07:22 +00:00
// Interface
private bool editpressed ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
2009-05-17 14:00:36 +00:00
public override object HighlightedObject { get { return highlighted ; } }
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
// This highlights a new item
protected void Highlight ( Linedef l )
{
bool completeredraw = false ;
LinedefActionInfo action = null ;
// 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?
if ( ( highlighted ! = null ) & & ( highlighted . Tag > 0 ) ) completeredraw = true ;
// Set highlight association
if ( l ! = null )
2012-09-17 21:57:08 +00:00
highlightasso . Set ( new Vector2D ( ( l . Start . Position + l . End . Position ) / 2 ) , l . Tag , UniversalType . LinedefTag ) ;
2009-04-19 18:07:22 +00:00
else
2012-09-17 21:57:08 +00:00
highlightasso . Set ( new Vector2D ( ) , 0 , 0 ) ;
2009-04-19 18:07:22 +00:00
// New association highlights something?
if ( ( l ! = null ) & & ( l . Tag > 0 ) ) completeredraw = true ;
// Use the line tag to highlight sectors (Doom style)
if ( General . Map . Config . LineTagIndicatesSectors )
{
if ( l ! = null )
2012-09-17 21:57:08 +00:00
association [ 0 ] . Set ( new Vector2D ( ( l . Start . Position + l . End . Position ) / 2 ) , l . Tag , UniversalType . SectorTag ) ;
2009-04-19 18:07:22 +00:00
else
2012-09-17 21:57:08 +00:00
association [ 0 ] . Set ( new Vector2D ( ) , 0 , 0 ) ;
2009-04-19 18:07:22 +00:00
}
else
{
if ( l ! = null )
{
// Check if we can find the linedefs action
if ( ( l . Action > 0 ) & & General . Map . Config . LinedefActions . ContainsKey ( l . Action ) )
action = General . Map . Config . LinedefActions [ l . Action ] ;
}
// Determine linedef associations
for ( int i = 0 ; i < Linedef . NUM_ARGS ; i + + )
{
// Previous association highlights something?
if ( ( association [ i ] . type = = UniversalType . SectorTag ) | |
( association [ i ] . type = = UniversalType . LinedefTag ) | |
( association [ i ] . type = = UniversalType . ThingTag ) ) completeredraw = true ;
// Make new association
if ( action ! = null )
2012-09-17 21:57:08 +00:00
association [ i ] . Set ( new Vector2D ( ( l . Start . Position + l . End . Position ) / 2 ) , l . Args [ i ] , action . Args [ i ] . Type ) ;
2009-04-19 18:07:22 +00:00
else
2012-09-17 21:57:08 +00:00
association [ i ] . Set ( new Vector2D ( ) , 0 , 0 ) ;
2009-04-19 18:07:22 +00:00
// New association highlights something?
if ( ( association [ i ] . type = = UniversalType . SectorTag ) | |
( association [ i ] . type = = UniversalType . LinedefTag ) | |
( association [ i ] . type = = UniversalType . ThingTag ) ) completeredraw = true ;
}
}
// If we're changing associations, then we
// need to redraw the entire display
if ( completeredraw )
{
// Set new highlight and redraw completely
highlighted = l ;
General . Interface . RedrawDisplay ( ) ;
}
else
{
// Update display
if ( renderer . StartPlotter ( false ) )
{
// Undraw previous highlight
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
renderer . PlotLinedef ( highlighted , renderer . DetermineLinedefColor ( highlighted ) ) ;
renderer . PlotVertex ( highlighted . Start , renderer . DetermineVertexColor ( highlighted . Start ) ) ;
renderer . PlotVertex ( highlighted . End , renderer . DetermineVertexColor ( highlighted . End ) ) ;
}
// Set new highlight
highlighted = l ;
// Render highlighted item
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
renderer . PlotLinedef ( highlighted , General . Colors . Highlight ) ;
renderer . PlotVertex ( highlighted . Start , renderer . DetermineVertexColor ( highlighted . Start ) ) ;
renderer . PlotVertex ( highlighted . End , renderer . DetermineVertexColor ( highlighted . End ) ) ;
}
// Done
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
// Show highlight info
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
General . Interface . ShowLinedefInfo ( highlighted ) ;
else
General . Interface . HideInfo ( ) ;
}
2013-05-30 12:52:27 +00:00
//mxd
private void alignTextureToLine ( bool alignFloors , bool alignToFrontSide ) {
ICollection < Linedef > lines = General . Map . Map . GetSelectedLinedefs ( true ) ;
if ( lines . Count = = 0 ) {
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires a selection" ) ;
return ;
}
//Create Undo
string rest = ( alignFloors ? "Floors" : "Ceilings" ) + " to " + ( alignToFrontSide ? "Front" : "Back" ) + " Side" ;
General . Map . UndoRedo . CreateUndo ( "Align " + rest ) ;
int counter = 0 ;
foreach ( Linedef l in lines ) {
Sector s = null ;
if ( alignToFrontSide ) {
if ( l . Front ! = null & & l . Front . Sector ! = null ) s = l . Front . Sector ;
} else {
if ( l . Back ! = null & & l . Back . Sector ! = null ) s = l . Back . Sector ;
}
if ( s = = null ) continue ;
counter + + ;
s . Fields . BeforeFieldsChange ( ) ;
float sourceAngle = ( float ) Math . Round ( General . ClampAngle ( alignToFrontSide ? - Angle2D . RadToDeg ( l . Angle ) + 90 : - Angle2D . RadToDeg ( l . Angle ) - 90 ) , 1 ) ;
if ( ! alignToFrontSide ) sourceAngle = General . ClampAngle ( sourceAngle + 180 ) ;
//update angle
2013-08-10 11:28:51 +00:00
UDMFTools . SetFloat ( s . Fields , ( alignFloors ? "rotationfloor" : "rotationceiling" ) , sourceAngle , 0f ) ;
2013-05-30 12:52:27 +00:00
//update offset
Vector2D offset = ( alignToFrontSide ? l . Start . Position : l . End . Position ) . GetRotated ( Angle2D . DegToRad ( sourceAngle ) ) ;
ImageData texture = General . Map . Data . GetFlatImage ( s . LongFloorTexture ) ;
if ( ( texture = = null ) | | ( texture = = General . Map . Data . WhiteTexture ) | |
( texture . Width < = 0 ) | | ( texture . Height < = 0 ) | | ! texture . IsImageLoaded ) {
} else {
offset . x % = texture . Width / s . Fields . GetValue ( ( alignFloors ? "xscalefloor" : "xscaleceiling" ) , 1.0f ) ;
offset . y % = texture . Height / s . Fields . GetValue ( ( alignFloors ? "yscalefloor" : "yscaleceiling" ) , 1.0f ) ;
}
2013-08-10 11:28:51 +00:00
UDMFTools . SetFloat ( s . Fields , ( alignFloors ? "xpanningfloor" : "xpanningceiling" ) , ( float ) Math . Round ( - offset . x ) , 0f ) ;
UDMFTools . SetFloat ( s . Fields , ( alignFloors ? "ypanningfloor" : "ypanningceiling" ) , ( float ) Math . Round ( offset . y ) , 0f ) ;
2013-05-30 12:52:27 +00:00
//update
s . UpdateNeeded = true ;
s . UpdateCache ( ) ;
}
General . Interface . DisplayStatus ( StatusType . Info , "Aligned " + counter + " " + rest ) ;
//update
General . Map . Map . Update ( ) ;
General . Interface . RedrawDisplay ( ) ;
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
}
2013-11-29 14:45:29 +00:00
//mxd
private bool isInSelectionRect ( Linedef l , List < Line2D > selectionOutline ) {
if ( BuilderPlug . Me . MarqueSelectTouching ) {
bool selected = selectionrect . Contains ( l . Start . Position . x , l . Start . Position . y ) | | selectionrect . Contains ( l . End . Position . x , l . End . Position . y ) ;
//check intersections with outline
if ( ! selected ) {
foreach ( Line2D line in selectionOutline ) {
if ( Line2D . GetIntersection ( l . Line , line ) )
return true ;
}
}
return selected ;
}
return selectionrect . Contains ( l . Start . Position . x , l . Start . Position . y ) & & selectionrect . Contains ( l . End . Position . x , l . End . Position . y ) ;
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Events
public override void OnHelp ( )
{
General . ShowHelp ( "e_linedefs.html" ) ;
}
// Cancel mode
public override void OnCancel ( )
{
base . OnCancel ( ) ;
// Return to this mode
General . Editing . ChangeMode ( new LinedefsMode ( ) ) ;
}
// Mode engages
public override void OnEngage ( )
{
base . OnEngage ( ) ;
renderer . SetPresentation ( Presentation . Standard ) ;
// Add toolbar buttons
2010-08-15 13:45:43 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . CopyProperties ) ;
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . PasteProperties ) ;
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . SeparatorCopyPaste ) ;
2013-03-18 13:52:27 +00:00
if ( General . Map . UDMF ) General . Interface . AddButton ( BuilderPlug . Me . MenusForm . MakeGradientBrightness ) ; //mxd
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . MarqueSelectTouching ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . AddButton ( BuilderPlug . Me . MenusForm . CurveLinedefs ) ;
2013-04-11 09:27:16 +00:00
if ( General . Map . UDMF ) General . Interface . AddButton ( BuilderPlug . Me . MenusForm . TextureOffsetLock , ToolbarSection . Geometry ) ; //mxd
2009-04-19 18:07:22 +00:00
// Convert geometry selection to linedefs selection
General . Map . Map . ConvertSelection ( SelectionType . Linedefs ) ;
2013-07-09 11:29:10 +00:00
updateSelectionInfo ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
// Mode disengages
public override void OnDisengage ( )
{
base . OnDisengage ( ) ;
// Remove toolbar buttons
2010-08-15 13:45:43 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . CopyProperties ) ;
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . PasteProperties ) ;
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . SeparatorCopyPaste ) ;
2013-03-18 13:52:27 +00:00
if ( General . Map . UDMF ) General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . MakeGradientBrightness ) ; //mxd
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . MarqueSelectTouching ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . CurveLinedefs ) ;
2013-04-11 09:27:16 +00:00
if ( General . Map . UDMF ) General . Interface . RemoveButton ( BuilderPlug . Me . MenusForm . TextureOffsetLock ) ; //mxd
2009-04-19 18:07:22 +00:00
// Going to EditSelectionMode?
if ( General . Editing . NewMode is EditSelectionMode )
{
2009-08-19 11:42:20 +00:00
// Not pasting anything?
EditSelectionMode editmode = ( General . Editing . NewMode as EditSelectionMode ) ;
if ( ! editmode . 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 . GetSelectedLinedefs ( true ) . Count = = 0 ) & & ( highlighted ! = null ) )
{
// Make the highlight the selection
highlighted . Selected = true ;
}
2009-04-19 18:07:22 +00:00
}
}
// Hide highlight info
General . Interface . HideInfo ( ) ;
}
// This redraws the display
public override void OnRedrawDisplay ( )
{
renderer . RedrawSurface ( ) ;
// Render lines
if ( renderer . StartPlotter ( true ) )
{
renderer . PlotLinedefSet ( General . Map . Map . Linedefs ) ;
2013-12-03 14:40:40 +00:00
if ( ! panning ) //mxd
for ( int i = 0 ; i < Linedef . NUM_ARGS ; i + + ) BuilderPlug . Me . PlotAssociations ( renderer , association [ i ] ) ;
2013-11-08 08:18:33 +00:00
2009-04-19 18:07:22 +00:00
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
2013-12-03 14:40:40 +00:00
if ( ! panning ) BuilderPlug . Me . PlotReverseAssociations ( renderer , highlightasso ) ;
2009-04-19 18:07:22 +00:00
renderer . PlotLinedef ( highlighted , General . Colors . Highlight ) ;
}
renderer . PlotVerticesSet ( General . Map . Map . Vertices ) ;
renderer . Finish ( ) ;
}
// Render things
if ( renderer . StartThings ( true ) )
{
renderer . RenderThingSet ( General . Map . ThingsFilter . HiddenThings , Presentation . THINGS_HIDDEN_ALPHA ) ;
renderer . RenderThingSet ( General . Map . ThingsFilter . VisibleThings , 1.0f ) ;
renderer . Finish ( ) ;
}
// Render selection
if ( renderer . StartOverlay ( true ) )
{
2014-01-27 11:18:24 +00:00
if ( ! panning & & ! selecting ) { //mxd
2013-12-03 14:40:40 +00:00
for ( int i = 0 ; i < Linedef . NUM_ARGS ; i + + ) BuilderPlug . Me . RenderAssociations ( renderer , association [ i ] ) ;
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed ) BuilderPlug . Me . RenderReverseAssociations ( renderer , highlightasso ) ; //mxd
}
2009-04-19 18:07:22 +00:00
if ( selecting ) RenderMultiSelection ( ) ;
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 . PlotLinedef ( highlighted , renderer . DetermineLinedefColor ( highlighted ) ) ;
renderer . PlotVertex ( highlighted . Start , renderer . DetermineVertexColor ( highlighted . Start ) ) ;
renderer . PlotVertex ( highlighted . End , renderer . DetermineVertexColor ( highlighted . End ) ) ;
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
base . OnSelectBegin ( ) ;
}
// End selection
protected override void OnSelectEnd ( )
{
// Not stopping from multiselection?
if ( ! selecting )
{
// Item highlighted?
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
2013-03-18 13:52:27 +00:00
//mxd. Flip selection
highlighted . Selected = ! highlighted . Selected ;
2009-04-19 18:07:22 +00:00
// Update display
if ( renderer . StartPlotter ( false ) )
{
// Render highlighted item
renderer . PlotLinedef ( highlighted , General . Colors . Highlight ) ;
renderer . PlotVertex ( highlighted . Start , renderer . DetermineVertexColor ( highlighted . Start ) ) ;
renderer . PlotVertex ( highlighted . End , renderer . DetermineVertexColor ( highlighted . End ) ) ;
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
2013-03-28 11:37:08 +00:00
//mxd
} else if ( BuilderPlug . Me . AutoClearSelection & & General . Map . Map . SelectedLinedefsCount > 0 ) {
General . Map . Map . ClearSelectedLinedefs ( ) ;
General . Interface . RedrawDisplay ( ) ;
2009-04-19 18:07:22 +00:00
}
2013-07-09 11:29:10 +00:00
//mxd
updateSelectionInfo ( ) ;
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?
2009-07-09 14:03:47 +00:00
if ( ! highlighted . Selected & & ( BuilderPlug . Me . AutoClearSelection | | ( General . Map . Map . SelectedLinedefsCount = = 0 ) ) )
2009-04-19 18:07:22 +00:00
{
// Make this the only selection
General . Map . Map . ClearSelectedLinedefs ( ) ;
highlighted . Selected = true ;
General . Interface . RedrawDisplay ( ) ;
}
// Update display
if ( renderer . StartPlotter ( false ) )
{
// Redraw highlight to show selection
renderer . PlotLinedef ( highlighted , renderer . DetermineLinedefColor ( highlighted ) ) ;
renderer . PlotVertex ( highlighted . Start , renderer . DetermineVertexColor ( highlighted . Start ) ) ;
renderer . PlotVertex ( highlighted . End , renderer . DetermineVertexColor ( highlighted . End ) ) ;
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 ;
DrawnVertex v = DrawGeometryMode . GetCurrentPosition ( mousemappos , snaptonearest , snaptogrid , 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 )
{
// Anything selected?
ICollection < Linedef > selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
if ( selected . Count > 0 )
{
if ( General . Interface . IsActiveWindow )
{
// Show line edit dialog
2013-11-29 12:24:47 +00:00
DialogResult result = General . Interface . ShowEditLinedefs ( selected ) ;
2009-04-19 18:07:22 +00:00
General . Map . Map . Update ( ) ;
// When a single line was selected, deselect it now
2013-11-29 12:24:47 +00:00
if ( selected . Count = = 1 ) {
General . Map . Map . ClearSelectedLinedefs ( ) ;
} else if ( result = = DialogResult . Cancel ) { //mxd. Restore selection...
foreach ( Linedef l in selected ) l . Selected = true ;
}
2009-04-19 18:07:22 +00:00
// Update entire display
2013-07-29 08:50:50 +00:00
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ; //mxd
2009-04-19 18:07:22 +00:00
General . Interface . RedrawDisplay ( ) ;
}
}
2013-07-09 11:29:10 +00:00
updateSelectionInfo ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
editpressed = false ;
base . OnEditEnd ( ) ;
}
// Mouse moves
public override void OnMouseMove ( MouseEventArgs e )
{
base . OnMouseMove ( e ) ;
2013-07-29 08:50:50 +00:00
if ( panning ) return ; //mxd. Skip all this jass while panning
2009-04-19 18:07:22 +00:00
2013-03-18 13:52:27 +00:00
//mxd
if ( selectpressed & & ! editpressed & & ! selecting ) {
// Check if moved enough pixels for multiselect
Vector2D delta = mousedownpos - mousepos ;
if ( ( Math . Abs ( delta . x ) > MULTISELECT_START_MOVE_PIXELS ) | |
( Math . Abs ( delta . y ) > MULTISELECT_START_MOVE_PIXELS ) ) {
// Start multiselecting
StartMultiSelection ( ) ;
}
}
2013-03-28 12:31:37 +00:00
else if ( paintselectpressed & & ! editpressed & & ! selecting ) //mxd. Drag-select
2013-03-18 13:52:27 +00:00
{
// Find the nearest thing within highlight range
Linedef l = General . Map . Map . NearestLinedefRange ( mousemappos , BuilderPlug . Me . HighlightRange / renderer . Scale ) ;
if ( l ! = null ) {
if ( l ! = highlighted ) {
//toggle selected state
if ( General . Interface . ShiftState ^ BuilderPlug . Me . AdditiveSelect )
l . Selected = true ;
else if ( General . Interface . CtrlState )
l . Selected = false ;
else
l . Selected = ! l . Selected ;
highlighted = l ;
2013-07-09 11:29:10 +00:00
updateSelectionInfo ( ) ; //mxd
2013-03-18 13:52:27 +00:00
// Update entire display
General . Interface . RedrawDisplay ( ) ;
}
} else if ( highlighted ! = null ) {
highlighted = null ;
Highlight ( null ) ;
// Update entire display
General . Interface . RedrawDisplay ( ) ;
}
}
else if ( e . Button = = MouseButtons . None ) // Not holding any buttons?
2009-04-19 18:07:22 +00:00
{
// Find the nearest linedef within highlight range
2014-02-18 14:04:14 +00:00
Linedef l = General . Map . Map . NearestLinedefRange ( mousemappos , BuilderPlug . Me . StitchRange / renderer . Scale ) ;
2009-04-19 18:07:22 +00:00
2014-01-23 13:55:03 +00:00
//mxd. Render insert vertex preview
if ( l ! = null ) {
bool snaptogrid = General . Interface . ShiftState ^ General . Interface . SnapToGrid ;
bool snaptonearest = General . Interface . CtrlState ^ General . Interface . AutoMerge ;
insertPreview = DrawGeometryMode . GetCurrentPosition ( mousemappos , snaptonearest , snaptogrid , renderer , new List < DrawnVertex > ( ) ) . pos ;
//render preview
if ( renderer . StartOverlay ( true ) ) {
2014-01-27 11:18:24 +00:00
if ( ! panning ) {
for ( int i = 0 ; i < Linedef . NUM_ARGS ; i + + ) BuilderPlug . Me . RenderAssociations ( renderer , association [ i ] ) ;
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed ) BuilderPlug . Me . RenderReverseAssociations ( renderer , highlightasso ) ; //mxd
}
2014-01-23 13:55:03 +00:00
float dist = Math . Min ( Vector2D . Distance ( mousemappos , insertPreview ) , BuilderPlug . Me . SplitLinedefsRange ) ;
byte alpha = ( byte ) ( 255 - ( dist / BuilderPlug . Me . SplitLinedefsRange ) * 128 ) ;
float vsize = ( renderer . VertexSize + 1.0f ) / renderer . Scale ;
renderer . RenderRectangleFilled ( new RectangleF ( insertPreview . x - vsize , insertPreview . y - vsize , vsize * 2.0f , vsize * 2.0f ) , General . Colors . InfoLine . WithAlpha ( alpha ) , true ) ;
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
} else if ( insertPreview . IsFinite ( ) ) {
insertPreview . x = float . NaN ;
//undraw preveiw
if ( renderer . StartOverlay ( true ) ) {
2014-01-27 11:18:24 +00:00
if ( ! panning ) {
for ( int i = 0 ; i < Linedef . NUM_ARGS ; i + + ) BuilderPlug . Me . RenderAssociations ( renderer , association [ i ] ) ;
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed ) BuilderPlug . Me . RenderReverseAssociations ( renderer , highlightasso ) ; //mxd
}
2014-01-23 13:55:03 +00:00
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
2009-04-19 18:07:22 +00:00
// Highlight if not the same
if ( l ! = highlighted ) Highlight ( l ) ;
2013-03-18 13:52:27 +00:00
}
2009-04-19 18:07:22 +00:00
}
// Mouse leaves
public override void OnMouseLeave ( EventArgs e )
{
base . OnMouseLeave ( e ) ;
// Highlight nothing
Highlight ( null ) ;
}
2014-01-23 13:55:03 +00:00
//mxd
protected override void BeginViewPan ( ) {
if ( insertPreview . IsFinite ( ) ) {
insertPreview . x = float . NaN ;
//undraw preveiw
if ( renderer . StartOverlay ( true ) ) {
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
base . BeginViewPan ( ) ;
}
2013-03-18 13:52:27 +00:00
//mxd
protected override void OnPaintSelectBegin ( ) {
highlighted = null ;
base . OnPaintSelectBegin ( ) ;
}
2009-04-19 18:07:22 +00:00
// Mouse wants to drag
protected override void OnDragStart ( MouseEventArgs e )
{
base . OnDragStart ( e ) ;
// Edit button used?
if ( General . Actions . CheckActionActive ( null , "classicedit" ) )
{
// Anything highlighted?
if ( ( highlighted ! = null ) & & ! highlighted . IsDisposed )
{
// Highlighted item not selected?
if ( ! highlighted . Selected )
{
// Select only this linedef for dragging
General . Map . Map . ClearSelectedLinedefs ( ) ;
highlighted . Selected = true ;
}
// Start dragging the selection
2013-03-18 13:52:27 +00:00
if ( ! BuilderPlug . Me . DontMoveGeometryOutsideMapBoundary | | canDrag ( ) ) //mxd
General . Editing . ChangeMode ( new DragLinedefsMode ( mousedownmappos ) ) ;
}
}
}
//mxd. Check if any selected linedef is outside of map boundary
private bool canDrag ( ) {
ICollection < Linedef > selectedlines = General . Map . Map . GetSelectedLinedefs ( true ) ;
int unaffectedCount = 0 ;
foreach ( Linedef l in selectedlines ) {
// Make sure the linedef is inside the map boundary
if ( l . Start . Position . x < General . Map . Config . LeftBoundary | | l . Start . Position . x > General . Map . Config . RightBoundary
| | l . Start . Position . y > General . Map . Config . TopBoundary | | l . Start . Position . y < General . Map . Config . BottomBoundary
| | l . End . Position . x < General . Map . Config . LeftBoundary | | l . End . Position . x > General . Map . Config . RightBoundary
| | l . End . Position . y > General . Map . Config . TopBoundary | | l . End . Position . y < General . Map . Config . BottomBoundary ) {
l . Selected = false ;
unaffectedCount + + ;
2009-04-19 18:07:22 +00:00
}
}
2013-03-18 13:52:27 +00:00
if ( unaffectedCount = = selectedlines . Count ) {
General . Interface . DisplayStatus ( StatusType . Warning , "Unable to drag selection: " + ( selectedlines . Count = = 1 ? "selected linedef is" : "all of selected linedefs are" ) + " outside of map boundary!" ) ;
General . Interface . RedrawDisplay ( ) ;
return false ;
}
if ( unaffectedCount > 0 )
General . Interface . DisplayStatus ( StatusType . Warning , unaffectedCount + " of selected linedefs " + ( unaffectedCount = = 1 ? "is" : "are" ) + " outside of map boundary!" ) ;
return true ;
2009-04-19 18:07:22 +00:00
}
// This is called wheh selection ends
protected override void OnEndMultiSelection ( )
{
2013-12-20 09:24:43 +00:00
bool selectionvolume = ( ( Math . Abs ( selectionrect . Width ) > 0.1f ) & & ( Math . Abs ( selectionrect . Height ) > 0.1f ) ) ;
2009-08-19 11:09:10 +00:00
if ( selectionvolume )
2009-04-19 18:07:22 +00:00
{
2013-11-29 14:45:29 +00:00
List < Line2D > selectionOutline = new List < Line2D > ( ) {
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 )
} ;
2013-03-18 13:52:27 +00:00
//mxd
2013-12-20 09:24:43 +00:00
switch ( marqueSelectionMode ) {
case MarqueSelectionMode . SELECT :
foreach ( Linedef l in General . Map . Map . Linedefs )
l . Selected = isInSelectionRect ( l , selectionOutline ) ;
break ;
case MarqueSelectionMode . ADD :
foreach ( Linedef l in General . Map . Map . Linedefs )
l . Selected | = isInSelectionRect ( l , selectionOutline ) ;
break ;
case MarqueSelectionMode . SUBTRACT :
foreach ( Linedef l in General . Map . Map . Linedefs )
if ( isInSelectionRect ( l , selectionOutline ) ) l . Selected = false ;
break ;
default :
foreach ( Linedef l in General . Map . Map . Linedefs )
if ( ! isInSelectionRect ( l , selectionOutline ) ) l . Selected = false ;
break ;
2009-04-19 18:07:22 +00:00
}
2013-07-09 11:29:10 +00:00
//mxd
updateSelectionInfo ( ) ;
2009-04-19 18:07:22 +00:00
}
base . OnEndMultiSelection ( ) ;
// Clear overlay
if ( renderer . StartOverlay ( true ) ) renderer . Finish ( ) ;
// Redraw
General . Interface . RedrawDisplay ( ) ;
}
// This is called when the selection is updated
protected override void OnUpdateMultiSelection ( )
{
base . OnUpdateMultiSelection ( ) ;
// Render selection
if ( renderer . StartOverlay ( true ) )
{
RenderMultiSelection ( ) ;
renderer . Finish ( ) ;
renderer . Present ( ) ;
}
}
// When copying
public override bool OnCopyBegin ( )
{
// No selection made? But we have a highlight!
if ( ( General . Map . Map . GetSelectedLinedefs ( true ) . Count = = 0 ) & & ( highlighted ! = null ) )
{
// Make the highlight the selection
highlighted . Selected = true ;
}
return base . OnCopyBegin ( ) ;
}
2013-07-09 11:29:10 +00:00
//mxd
protected override void updateSelectionInfo ( ) {
if ( General . Map . Map . SelectedLinedefsCount > 0 )
General . Interface . DisplayStatus ( StatusType . Selection , General . Map . Map . SelectedLinedefsCount + ( General . Map . Map . SelectedLinedefsCount = = 1 ? " linedef" : " linedefs" ) + " selected." ) ;
else
General . Interface . DisplayStatus ( StatusType . Selection , string . Empty ) ;
}
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 linedefs
ICollection < Linedef > sel = null ;
if ( General . Map . Map . SelectedLinedefsCount > 0 )
sel = General . Map . Map . GetSelectedLinedefs ( true ) ;
else if ( highlighted ! = null )
2013-12-20 09:24:43 +00:00
sel = new List < Linedef > { highlighted } ;
2010-08-15 13:45:43 +00:00
if ( sel ! = null )
{
// Copy properties from first source linedef
BuilderPlug . Me . CopiedLinedefProps = new LinedefProperties ( General . GetByIndex ( sel , 0 ) ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Copied linedef properties." ) ;
}
}
// This pastes the properties
[BeginAction("classicpasteproperties")]
public void PasteProperties ( )
{
if ( BuilderPlug . Me . CopiedLinedefProps ! = null )
{
// Determine target linedefs
ICollection < Linedef > sel = null ;
if ( General . Map . Map . SelectedLinedefsCount > 0 )
sel = General . Map . Map . GetSelectedLinedefs ( true ) ;
else if ( highlighted ! = null )
{
sel = new List < Linedef > ( ) ;
sel . Add ( highlighted ) ;
}
if ( sel ! = null )
{
// Apply properties to selection
General . Map . UndoRedo . CreateUndo ( "Paste linedef properties" ) ;
foreach ( Linedef l in sel )
{
BuilderPlug . Me . CopiedLinedefProps . Apply ( l ) ;
l . UpdateCache ( ) ;
}
General . Interface . DisplayStatus ( StatusType . Action , "Pasted linedef properties." ) ;
// Update and redraw
General . Map . IsChanged = true ;
General . Interface . RefreshInfo ( ) ;
2013-07-29 08:50:50 +00:00
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ; //mxd
2010-08-15 13:45:43 +00:00
General . Interface . RedrawDisplay ( ) ;
}
}
}
2009-04-19 18:07:22 +00:00
// This keeps only the single-sided lines selected
[BeginAction("selectsinglesided")]
public void SelectSingleSided ( )
{
int counter = 0 ;
ICollection < Linedef > selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
foreach ( Linedef ld in selected )
{
if ( ( ld . Front ! = null ) & & ( ld . Back ! = null ) )
ld . Selected = false ;
else
counter + + ;
}
General . Interface . DisplayStatus ( StatusType . Action , "Selected only single-sided linedefs (" + counter + ")" ) ;
General . Interface . RedrawDisplay ( ) ;
}
// This keeps only the double-sided lines selected
[BeginAction("selectdoublesided")]
public void SelectDoubleSided ( )
{
int counter = 0 ;
ICollection < Linedef > selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
foreach ( Linedef ld in selected )
{
if ( ( ld . Front = = null ) | | ( ld . Back = = null ) )
ld . Selected = false ;
else
counter + + ;
}
General . Interface . DisplayStatus ( StatusType . Action , "Selected only double-sided linedefs (" + counter + ")" ) ;
General . Interface . RedrawDisplay ( ) ;
}
// This clears the selection
[BeginAction("clearselection", BaseAction = true)]
public void ClearSelection ( )
{
// Clear selection
General . Map . Map . ClearAllSelected ( ) ;
2013-12-12 09:07:30 +00:00
//mxd. Clear selection info
2013-07-09 11:29:10 +00:00
General . Interface . DisplayStatus ( StatusType . Selection , string . Empty ) ;
2009-04-19 18:07:22 +00:00
// Redraw
General . Interface . RedrawDisplay ( ) ;
}
// This creates a new vertex at the mouse position
[BeginAction("insertitem", BaseAction = true)]
public virtual void InsertVertexAction ( )
{
// 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 ;
DrawnVertex v = DrawGeometryMode . GetCurrentPosition ( mousemappos , snaptonearest , snaptogrid , renderer , new List < DrawnVertex > ( ) ) ;
drawmode . DrawPointAt ( v ) ;
}
General . Editing . ChangeMode ( drawmode ) ;
}
2014-01-08 09:46:57 +00:00
2009-04-19 18:07:22 +00:00
[BeginAction("deleteitem", BaseAction = true)]
2014-01-08 09:46:57 +00:00
public void DeleteItem ( ) {
// Make list of selected linedefs
ICollection < Linedef > selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
if ( ( selected . Count = = 0 ) & & ( highlighted ! = null ) & & ! highlighted . IsDisposed ) selected . Add ( highlighted ) ;
if ( selected . Count = = 0 ) return ;
// Make undo
if ( selected . Count > 1 ) {
General . Map . UndoRedo . CreateUndo ( "Delete " + selected . Count + " linedefs" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Deleted " + selected . Count + " linedefs." ) ;
} else {
General . Map . UndoRedo . CreateUndo ( "Delete linedef" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Deleted a linedef." ) ;
}
// Dispose selected linedefs
foreach ( Linedef ld in selected ) ld . Dispose ( ) ;
// Update cache values
General . Map . IsChanged = true ;
General . Map . Map . Update ( ) ;
// Invoke a new mousemove so that the highlighted item updates
MouseEventArgs e = new MouseEventArgs ( MouseButtons . None , 0 , ( int ) mousepos . x , ( int ) mousepos . y , 0 ) ;
OnMouseMove ( e ) ;
// Redraw screen
General . Interface . RedrawDisplay ( ) ;
}
[BeginAction("dissolveitem", BaseAction = true)] //mxd
public void DissolveItem ( )
2009-04-19 18:07:22 +00:00
{
// Make list of selected linedefs
ICollection < Linedef > selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
if ( ( selected . Count = = 0 ) & & ( highlighted ! = null ) & & ! highlighted . IsDisposed ) selected . Add ( highlighted ) ;
// Anything to do?
if ( selected . Count > 0 )
{
// Make undo
if ( selected . Count > 1 )
{
2014-01-08 09:46:57 +00:00
General . Map . UndoRedo . CreateUndo ( "Dissolve " + selected . Count + " linedefs" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Dissolved " + selected . Count + " linedefs." ) ;
2009-04-19 18:07:22 +00:00
}
else
{
2014-01-08 09:46:57 +00:00
General . Map . UndoRedo . CreateUndo ( "Dissolve linedef" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Dissolved a linedef." ) ;
2009-04-19 18:07:22 +00:00
}
2013-03-22 12:53:34 +00:00
//mxd. Find sectors, which will become invalid after linedefs removal.
Dictionary < Sector , Vector2D > toMerge = new Dictionary < Sector , Vector2D > ( ) ;
foreach ( Linedef l in selected ) {
if ( l . Front ! = null & & l . Front . Sector . Sidedefs . Count < 4 & & ! toMerge . ContainsKey ( l . Front . Sector ) )
toMerge . Add ( l . Front . Sector , new Vector2D ( l . Front . Sector . BBox . Location . X + l . Front . Sector . BBox . Width / 2 , l . Front . Sector . BBox . Location . Y + l . Front . Sector . BBox . Height / 2 ) ) ;
if ( l . Back ! = null & & l . Back . Sector . Sidedefs . Count < 4 & & ! toMerge . ContainsKey ( l . Back . Sector ) )
toMerge . Add ( l . Back . Sector , new Vector2D ( l . Back . Sector . BBox . Location . X + l . Back . Sector . BBox . Width / 2 , l . Back . Sector . BBox . Location . Y + l . Back . Sector . BBox . Height / 2 ) ) ;
}
2013-12-13 09:31:18 +00:00
General . Map . Map . BeginAddRemove ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Dispose selected linedefs
2013-03-26 12:31:07 +00:00
foreach ( Linedef ld in selected ) {
//mxd. If there are different sectors on both sides, join them
if ( ld . Front ! = null & & ld . Front . Sector ! = null & & ld . Back ! = null & & ld . Back . Sector ! = null & & ld . Front . Sector . Index ! = ld . Back . Sector . Index ) {
if ( ld . Front . Sector . BBox . Width * ld . Front . Sector . BBox . Height > ld . Back . Sector . BBox . Width * ld . Back . Sector . BBox . Height )
ld . Back . Sector . Join ( ld . Front . Sector ) ;
else
ld . Front . Sector . Join ( ld . Back . Sector ) ;
}
ld . Dispose ( ) ;
}
2013-03-22 12:53:34 +00:00
//mxd
2013-12-13 09:31:18 +00:00
General . Map . Map . EndAddRemove ( ) ;
2013-03-22 12:53:34 +00:00
Tools . MergeInvalidSectors ( toMerge ) ;
2009-04-19 18:07:22 +00:00
// Update cache values
General . Map . IsChanged = true ;
General . Map . Map . Update ( ) ;
// Invoke a new mousemove so that the highlighted item updates
MouseEventArgs e = new MouseEventArgs ( MouseButtons . None , 0 , ( int ) mousepos . x , ( int ) mousepos . y , 0 ) ;
OnMouseMove ( e ) ;
// Redraw screen
General . Interface . RedrawDisplay ( ) ;
}
}
[BeginAction("splitlinedefs")]
public void SplitLinedefs ( )
{
// Make list of selected linedefs
ICollection < Linedef > selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
if ( ( selected . Count = = 0 ) & & ( highlighted ! = null ) & & ! highlighted . IsDisposed ) selected . Add ( highlighted ) ;
// Anything to do?
if ( selected . Count > 0 )
{
// Make undo
if ( selected . Count > 1 )
{
General . Map . UndoRedo . CreateUndo ( "Split " + selected . Count + " linedefs" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Split " + selected . Count + " linedefs." ) ;
}
else
{
General . Map . UndoRedo . CreateUndo ( "Split linedef" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Split a linedef." ) ;
}
// Go for all linedefs to split
foreach ( Linedef ld in selected )
{
Vertex splitvertex ;
// Linedef highlighted?
if ( ld = = highlighted )
{
// Split at nearest position on the line
Vector2D nearestpos = ld . NearestOnLine ( mousemappos ) ;
splitvertex = General . Map . Map . CreateVertex ( nearestpos ) ;
}
else
{
// Split in middle of line
splitvertex = General . Map . Map . CreateVertex ( ld . GetCenterPoint ( ) ) ;
}
2010-08-15 19:43:00 +00:00
if ( splitvertex = = null )
{
General . Map . UndoRedo . WithdrawUndo ( ) ;
break ;
}
2009-04-19 18:07:22 +00:00
// Snap to map format accuracy
splitvertex . SnapToAccuracy ( ) ;
2010-08-15 19:43:00 +00:00
2009-04-19 18:07:22 +00:00
// Split the line
2010-08-15 19:43:00 +00:00
Linedef sld = ld . Split ( splitvertex ) ;
if ( sld = = null )
{
General . Map . UndoRedo . WithdrawUndo ( ) ;
break ;
}
2012-03-19 21:31:10 +00:00
BuilderPlug . Me . AdjustSplitCoordinates ( ld , sld ) ;
2009-04-19 18:07:22 +00:00
}
// Update cache values
General . Map . IsChanged = true ;
General . Map . Map . Update ( ) ;
// Redraw screen
General . Interface . RedrawDisplay ( ) ;
}
}
[BeginAction("curvelinesmode")]
public void CurveLinedefs ( )
{
// No selected lines?
ICollection < Linedef > selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
if ( selected . Count = = 0 )
{
// Anything highlighted?
if ( highlighted ! = null )
{
// Select the highlighted item
highlighted . Selected = true ;
selected . Add ( highlighted ) ;
}
}
// Any selected lines?
if ( selected . Count > 0 )
{
// Go into curve linedefs mode
General . Editing . ChangeMode ( new CurveLinedefsMode ( new LinedefsMode ( ) ) ) ;
}
}
[BeginAction("fliplinedefs")]
public void FlipLinedefs ( )
{
// No selected lines?
ICollection < Linedef > selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
if ( selected . Count = = 0 )
{
// Anything highlighted?
if ( highlighted ! = null )
{
// Select the highlighted item
highlighted . Selected = true ;
selected . Add ( highlighted ) ;
}
}
// Any selected lines?
if ( selected . Count > 0 )
{
// Make undo
if ( selected . Count > 1 )
{
General . Map . UndoRedo . CreateUndo ( "Flip " + selected . Count + " linedefs" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Flipped " + selected . Count + " linedefs." ) ;
}
else
{
General . Map . UndoRedo . CreateUndo ( "Flip linedef" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Flipped a linedef." ) ;
}
// Flip all selected linedefs
foreach ( Linedef l in selected )
{
l . FlipVertices ( ) ;
l . FlipSidedefs ( ) ;
}
// Remove selection if only one was selected
if ( selected . Count = = 1 )
{
foreach ( Linedef ld in selected ) ld . Selected = false ;
selected . Clear ( ) ;
}
// Redraw
General . Map . Map . Update ( ) ;
General . Map . IsChanged = true ;
General . Interface . RefreshInfo ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
}
[BeginAction("flipsidedefs")]
public void FlipSidedefs ( )
{
// No selected lines?
ICollection < Linedef > selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
if ( selected . Count = = 0 )
{
// Anything highlighted?
if ( highlighted ! = null )
{
// Select the highlighted item
highlighted . Selected = true ;
selected . Add ( highlighted ) ;
}
}
// Any selected lines?
if ( selected . Count > 0 )
{
// Make undo
if ( selected . Count > 1 )
{
General . Map . UndoRedo . CreateUndo ( "Flip " + selected . Count + " sidedefs" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Flipped " + selected . Count + " sidedefs." ) ;
}
else
{
General . Map . UndoRedo . CreateUndo ( "Flip sidedefs" ) ;
General . Interface . DisplayStatus ( StatusType . Action , "Flipped sidedefs." ) ;
}
// Flip sidedefs in all selected linedefs
foreach ( Linedef l in selected )
{
l . FlipSidedefs ( ) ;
if ( l . Front ! = null ) l . Front . Sector . UpdateNeeded = true ;
if ( l . Back ! = null ) l . Back . Sector . UpdateNeeded = true ;
}
// Remove selection if only one was selected
if ( selected . Count = = 1 )
{
foreach ( Linedef ld in selected ) ld . Selected = false ;
selected . Clear ( ) ;
}
// Redraw
General . Map . Map . Update ( ) ;
General . Map . IsChanged = true ;
General . Interface . RefreshInfo ( ) ;
General . Interface . RedrawDisplay ( ) ;
}
}
2013-03-18 13:52:27 +00:00
//mxd. Make gradient brightness
[BeginAction("gradientbrightness")]
public void MakeGradientBrightness ( ) {
if ( ! General . Map . UDMF ) return ;
// Need at least 3 selected linedefs
// The first and last are not modified
ICollection < Linedef > orderedselection = General . Map . Map . GetSelectedLinedefs ( true ) ;
if ( orderedselection . Count > 2 ) {
General . Interface . DisplayStatus ( StatusType . Action , "Created gradient brightness over selected linedefs." ) ;
General . Map . UndoRedo . CreateUndo ( "Linedefs gradient brightness" ) ;
Linedef start = General . GetByIndex ( orderedselection , 0 ) ;
Linedef end = General . GetByIndex ( orderedselection , orderedselection . Count - 1 ) ;
2013-09-05 13:03:17 +00:00
const string lightKey = "light" ;
const string lightAbsKey = "lightabsolute" ;
2013-03-18 13:52:27 +00:00
float startbrightness = float . NaN ;
float endbrightness = float . NaN ;
//get total brightness of start sidedef(s)
if ( start . Front ! = null ) {
if ( start . Front . Fields . GetValue ( lightAbsKey , false ) ) {
2013-09-05 13:03:17 +00:00
startbrightness = start . Front . Fields . GetValue ( lightKey , 0 ) ;
2013-03-18 13:52:27 +00:00
} else {
startbrightness = Math . Min ( 255 , Math . Max ( 0 , ( float ) start . Front . Sector . Brightness + start . Front . Fields . GetValue ( lightKey , 0 ) ) ) ;
}
}
if ( start . Back ! = null ) {
2013-09-05 13:03:17 +00:00
float b ;
2013-03-18 13:52:27 +00:00
if ( start . Back . Fields . GetValue ( lightAbsKey , false ) ) {
2013-09-05 13:03:17 +00:00
b = start . Back . Fields . GetValue ( lightKey , 0 ) ;
2013-03-18 13:52:27 +00:00
} else {
b = Math . Min ( 255 , Math . Max ( 0 , ( float ) start . Back . Sector . Brightness + start . Back . Fields . GetValue ( lightKey , 0 ) ) ) ;
}
2013-09-05 13:03:17 +00:00
startbrightness = ( float . IsNaN ( startbrightness ) ? b : ( startbrightness + b ) / 2 ) ;
2013-03-18 13:52:27 +00:00
}
//get total brightness of end sidedef(s)
if ( end . Front ! = null ) {
if ( end . Front . Fields . GetValue ( lightAbsKey , false ) ) {
2013-09-05 13:03:17 +00:00
endbrightness = end . Front . Fields . GetValue ( lightKey , 0 ) ;
2013-03-18 13:52:27 +00:00
} else {
endbrightness = Math . Min ( 255 , Math . Max ( 0 , ( float ) end . Front . Sector . Brightness + end . Front . Fields . GetValue ( lightKey , 0 ) ) ) ;
}
}
if ( end . Back ! = null ) {
2013-09-05 13:03:17 +00:00
float b ;
2013-03-18 13:52:27 +00:00
if ( end . Back . Fields . GetValue ( lightAbsKey , false ) ) {
2013-09-05 13:03:17 +00:00
b = end . Back . Fields . GetValue ( lightKey , 0 ) ;
2013-03-18 13:52:27 +00:00
} else {
b = Math . Min ( 255 , Math . Max ( 0 , ( float ) end . Back . Sector . Brightness + end . Back . Fields . GetValue ( lightKey , 0 ) ) ) ;
}
2013-09-05 13:03:17 +00:00
endbrightness = ( float . IsNaN ( endbrightness ) ? b : ( endbrightness + b ) / 2 ) ;
2013-03-18 13:52:27 +00:00
}
float delta = endbrightness - startbrightness ;
// Go for all sectors in between first and last
int index = 0 ;
foreach ( Linedef l in orderedselection ) {
2013-09-05 13:03:17 +00:00
float u = index / ( float ) ( orderedselection . Count - 1 ) ;
2013-03-18 13:52:27 +00:00
float b = startbrightness + delta * u ;
if ( l . Front ! = null ) {
l . Front . Fields . BeforeFieldsChange ( ) ;
//absolute flag set?
if ( l . Front . Fields . GetValue ( lightAbsKey , false ) ) {
if ( l . Front . Fields . ContainsKey ( lightKey ) )
l . Front . Fields [ lightKey ] . Value = ( int ) b ;
else
l . Front . Fields . Add ( lightKey , new UniValue ( UniversalType . Integer , ( int ) b ) ) ;
} else {
if ( l . Front . Fields . ContainsKey ( lightKey ) )
l . Front . Fields [ lightKey ] . Value = ( int ) b - l . Front . Sector . Brightness ;
else
l . Front . Fields . Add ( lightKey , new UniValue ( UniversalType . Integer , ( int ) b - l . Front . Sector . Brightness ) ) ;
}
}
if ( l . Back ! = null ) {
l . Back . Fields . BeforeFieldsChange ( ) ;
//absolute flag set?
if ( l . Back . Fields . GetValue ( lightAbsKey , false ) ) {
if ( l . Back . Fields . ContainsKey ( lightKey ) )
l . Back . Fields [ lightKey ] . Value = ( int ) b ;
else
l . Back . Fields . Add ( lightKey , new UniValue ( UniversalType . Integer , ( int ) b ) ) ;
} else {
if ( l . Back . Fields . ContainsKey ( lightKey ) )
l . Back . Fields [ lightKey ] . Value = ( int ) b - l . Back . Sector . Brightness ;
else
l . Back . Fields . Add ( lightKey , new UniValue ( UniversalType . Integer , ( int ) b - l . Back . Sector . Brightness ) ) ;
}
}
index + + ;
}
} else {
General . Interface . DisplayStatus ( StatusType . Warning , "Select at least 3 linedefs first!" ) ;
}
// Update
General . Map . Map . Update ( ) ;
General . Interface . RedrawDisplay ( ) ;
General . Interface . RefreshInfo ( ) ;
General . Map . IsChanged = true ;
}
2013-09-11 13:14:45 +00:00
[BeginAction("placethings")] //mxd
public void PlaceThings ( ) {
// Make list of selected linedefs
ICollection < Linedef > lines = General . Map . Map . GetSelectedLinedefs ( true ) ;
List < Vector2D > positions = new List < Vector2D > ( ) ;
if ( lines . Count = = 0 ) {
if ( highlighted ! = null & & ! highlighted . IsDisposed ) {
lines . Add ( highlighted ) ;
} else {
General . Interface . DisplayStatus ( StatusType . Warning , "This action requires selection of some description!" ) ;
return ;
}
}
// Make list of vertex positions
foreach ( Linedef l in lines ) {
if ( ! positions . Contains ( l . Start . Position ) ) positions . Add ( l . Start . Position ) ;
if ( ! positions . Contains ( l . End . Position ) ) positions . Add ( l . End . Position ) ;
}
if ( positions . Count < 1 ) {
General . Interface . DisplayStatus ( StatusType . Warning , "Unable to get vertex positions from selection!" ) ;
return ;
}
placeThingsAtPositions ( positions ) ;
}
2013-05-30 12:52:27 +00:00
//mxd
[BeginAction("alignfloortofront")]
public void AlignFloorToFront ( ) {
if ( ! General . Map . UDMF ) return ;
alignTextureToLine ( true , true ) ;
}
//mxd
[BeginAction("alignfloortoback")]
public void AlignFloorToBack ( ) {
if ( ! General . Map . UDMF ) return ;
alignTextureToLine ( true , false ) ;
}
//mxd
[BeginAction("alignceilingtofront")]
public void AlignCeilingToFront ( ) {
if ( ! General . Map . UDMF ) return ;
alignTextureToLine ( false , true ) ;
}
//mxd
[BeginAction("alignceilingtoback")]
public void AlignCeilingToBack ( ) {
if ( ! General . Map . UDMF ) return ;
alignTextureToLine ( false , false ) ;
}
2009-04-19 18:07:22 +00:00
#endregion
}
}