2020-08-29 14:26:59 +00:00
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections.Generic ;
using System.Windows.Forms ;
using CodeImp.DoomBuilder.Map ;
using CodeImp.DoomBuilder.Rendering ;
using CodeImp.DoomBuilder.Geometry ;
using CodeImp.DoomBuilder.Editing ;
using CodeImp.DoomBuilder.Windows ;
using System.Drawing ;
#endregion
//JBR Parallel Linedef mode
namespace CodeImp.DoomBuilder.BuilderModes
{
[ EditMode ( DisplayName = "Parallel Linedef" ,
AllowCopyPaste = false ,
Volatile = true ) ]
public sealed class ParallelLinedefMode : BaseClassicMode
{
#region = = = = = = = = = = = = = = = = = = Constants
private const float LINE_THICKNESS = 0.6f ;
private const int LINKED_LINEDEFS = 0 ;
private const int UNLINKED_LINEDEFS = 1 ;
private const int LINEDEFS = 1 ;
private const int VERTICES = 2 ;
private const int THINGS = 3 ;
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
private EditMode basemode ;
private ICollection < Linedef > selected ;
private TracksTracer trackstracer ;
private bool clearlinedefs ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
// Just keep the base mode button checked
public override string EditModeButtonName { get { return General . Editing . PreviousStableMode . Name ; } }
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
public ParallelLinedefMode ( EditMode basemode )
{
this . basemode = basemode ;
}
// Disposer
public override void Dispose ( )
{
// Not already disposed?
if ( ! isdisposed )
{
// Clean up
// Done
base . Dispose ( ) ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
public List < Linedef > GetSelectedLinedefFromVertex ( Vertex v )
{
List < Linedef > list = new List < Linedef > ( ) ;
foreach ( Linedef ld in v . Linedefs )
{
if ( ld . Selected ) list . Add ( ld ) ;
}
return list ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Events
public override void OnHelp ( )
{
General . ShowHelp ( "e_parallellinedef.html" ) ;
}
// Cancelled
public override void OnCancel ( )
{
// Cancel base class
base . OnCancel ( ) ;
// Clear selection that is not the current mode
if ( clearlinedefs ) General . Map . Map . ClearSelectedLinedefs ( ) ;
// Return to base mode
General . Editing . ChangeMode ( General . Editing . PreviousStableMode . Name ) ;
}
// Mode engages
public override void OnEngage ( )
{
base . OnEngage ( ) ;
renderer . SetPresentation ( Presentation . Standard ) ;
// Make collections by selection
if ( basemode is VerticesMode )
{
selected = new List < Linedef > ( ) ;
ICollection < Vertex > selectedvertices = General . Map . Map . GetSelectedVertices ( true ) ;
foreach ( Vertex v in selectedvertices )
{
foreach ( Linedef ld in v . Linedefs )
{
if ( ld . Start . Selected & & ld . End . Selected )
{
ld . Selected = true ;
if ( ! selected . Contains ( ld ) ) selected . Add ( ld ) ;
}
}
}
clearlinedefs = true ;
}
if ( basemode is LinedefsMode )
{
selected = General . Map . Map . GetSelectedLinedefs ( true ) ;
}
if ( basemode is SectorsMode )
{
selected = new List < Linedef > ( ) ;
ICollection < Sector > selectedsectors = General . Map . Map . GetSelectedSectors ( true ) ;
foreach ( Sector sc in selectedsectors )
{
foreach ( Sidedef sd in sc . Sidedefs )
{
sd . Line . Selected = true ;
if ( ! selected . Contains ( sd . Line ) ) selected . Add ( sd . Line ) ;
}
}
clearlinedefs = true ;
}
// Create the tracks tracer
trackstracer = new TracksTracer ( selected ) ;
// Check if tracing was valid
if ( ! trackstracer . IsValid )
{
DialogResult dr = MessageBox . Show ( "Detected intersections while tracing!\nMake sure you're selecting vertices with maximum of 2 linedefs connected to them.\nResults may not be desirable, continue anyway?" , "Warning" , MessageBoxButtons . YesNo , MessageBoxIcon . Warning ) ;
if ( dr ! = DialogResult . Yes )
{
OnCancel ( ) ;
return ;
}
}
BuilderPlug . Me . ParallelLinedefForm . SetNumOpenPaths ( trackstracer . OpenPaths . Count ) ;
BuilderPlug . Me . ParallelLinedefForm . SetNumClosePaths ( trackstracer . ClosePaths . Count ) ;
// Show toolbox window
BuilderPlug . Me . ParallelLinedefForm . Show ( ( Form ) General . Interface ) ;
}
// Disenagaging
public override void OnDisengage ( )
{
base . OnDisengage ( ) ;
// Hide toolbox window
BuilderPlug . Me . ParallelLinedefForm . Hide ( ) ;
}
// This applies the curves and returns to the base mode
public override void OnAccept ( )
{
// Create undo
General . Map . UndoRedo . CreateUndo ( "Parallel (Linedef)" ) ;
int createas = BuilderPlug . Me . ParallelLinedefForm . CreateAs ;
float distance = BuilderPlug . Me . ParallelLinedefForm . Distance ;
bool closeopenpath = BuilderPlug . Me . ParallelLinedefForm . CloseOpenPath ;
bool backwards = BuilderPlug . Me . ParallelLinedefForm . Backwards ;
ThingBrowser2Form . Result thingresult = new ThingBrowser2Form . Result ( ) ;
// Ask for thing type...
if ( createas = = THINGS )
{
BuilderPlug . Me . ParallelLinedefForm . Hide ( ) ;
// Pick the thing to add...
thingresult = ThingBrowser2Form . BrowseThing ( BuilderPlug . Me . ParallelLinedefForm ) ;
if ( ! thingresult . OK )
{
General . Map . UndoRedo . WithdrawUndo ( ) ;
General . Map . UndoRedo . WithdrawUndo ( ) ;
General . Interface . DisplayStatus ( StatusType . Warning , "Operation aborted." ) ;
return ;
}
BuilderPlug . Me . ParallelLinedefForm . Show ( ) ;
BuilderPlug . Me . ParallelLinedefForm . Activate ( ) ;
}
// Go for all selected lines
foreach ( List < Vector2D > path in trackstracer . OpenPaths )
{
List < Vector2D > parallelpath = TracksTracer . ParallelizeOpenPath ( path , distance , backwards ) ;
if ( createas = = LINKED_LINEDEFS )
{
List < DrawnVertex > dvl = new List < DrawnVertex > ( ) ;
if ( closeopenpath ) TracksTracer . AddPointToDrawnVertex ( dvl , path [ 0 ] , true , true ) ;
TracksTracer . AddPathToDrawnVertex ( dvl , parallelpath , true , true ) ;
if ( closeopenpath ) TracksTracer . AddPointToDrawnVertex ( dvl , path [ path . Count - 1 ] , true , true ) ;
if ( ! Tools . DrawLines ( dvl , true , BuilderPlug . Me . AutoAlignTextureOffsetsOnCreate ) )
{
// Drawing failed
// NOTE: I have to call this twice, because the first time only cancels this volatile mode
General . Map . UndoRedo . WithdrawUndo ( ) ;
General . Map . UndoRedo . WithdrawUndo ( ) ;
return ;
}
}
else if ( createas = = UNLINKED_LINEDEFS )
{
// Unlinked linedef
Vertex oldv = General . Map . Map . CreateVertex ( parallelpath [ 0 ] ) ;
for ( int i = 1 ; i < parallelpath . Count ; i + + )
{
Vertex newv = General . Map . Map . CreateVertex ( parallelpath [ i ] ) ;
General . Map . Map . CreateLinedef ( oldv , newv ) ;
oldv = newv ;
}
if ( closeopenpath )
{
Vertex vtf = General . Map . Map . CreateVertex ( path [ 0 ] ) ;
Vertex vtl = General . Map . Map . CreateVertex ( path [ path . Count - 1 ] ) ;
Vertex vpf = General . Map . Map . CreateVertex ( parallelpath [ 0 ] ) ;
Vertex vpl = General . Map . Map . CreateVertex ( parallelpath [ parallelpath . Count - 1 ] ) ;
General . Map . Map . CreateLinedef ( vtf , vpf ) ;
General . Map . Map . CreateLinedef ( vpl , vtl ) ;
}
}
else if ( createas = = VERTICES )
{
// Vertex
foreach ( Vector2D pos in parallelpath )
{
General . Map . Map . CreateVertex ( pos ) ;
}
}
else if ( createas = = THINGS )
{
foreach ( Vector2D pos in parallelpath )
{
Thing tp = General . Map . Map . CreateThing ( ) ;
if ( tp ! = null )
{
General . Settings . ApplyDefaultThingSettings ( tp ) ;
thingresult . Apply ( tp ) ;
tp . Move ( pos ) ;
tp . UpdateConfiguration ( ) ;
}
}
}
}
foreach ( List < Vector2D > path in trackstracer . ClosePaths )
{
List < Vector2D > parallelpath = TracksTracer . ParallelizeClosePath ( path , distance , backwards ) ;
if ( createas = = LINKED_LINEDEFS )
{
List < DrawnVertex > dvl = new List < DrawnVertex > ( ) ;
TracksTracer . AddPathToDrawnVertex ( dvl , parallelpath , true , true ) ;
if ( ! Tools . DrawLines ( dvl , true , BuilderPlug . Me . AutoAlignTextureOffsetsOnCreate ) )
{
// Drawing failed
// NOTE: I have to call this twice, because the first time only cancels this volatile mode
General . Map . UndoRedo . WithdrawUndo ( ) ;
General . Map . UndoRedo . WithdrawUndo ( ) ;
return ;
}
}
else if ( createas = = UNLINKED_LINEDEFS )
{
// Unlinked linedef
Vertex oldv = General . Map . Map . CreateVertex ( parallelpath [ 0 ] ) ;
for ( int i = 1 ; i < parallelpath . Count ; i + + )
{
Vertex newv = General . Map . Map . CreateVertex ( parallelpath [ i ] ) ;
General . Map . Map . CreateLinedef ( oldv , newv ) ;
oldv = newv ;
}
}
else if ( createas = = VERTICES )
{
// Vertex
for ( int i = 0 ; i < parallelpath . Count - 1 ; i + + )
{
General . Map . Map . CreateVertex ( parallelpath [ i ] ) ;
}
}
else if ( createas = = THINGS )
{
// Thing
for ( int i = 0 ; i < parallelpath . Count - 1 ; i + + )
{
Thing tp = General . Map . Map . CreateThing ( ) ;
if ( tp ! = null )
{
General . Settings . ApplyDefaultThingSettings ( tp ) ;
thingresult . Apply ( tp ) ;
tp . Move ( parallelpath [ i ] ) ;
tp . UpdateConfiguration ( ) ;
}
}
}
}
// Announce how many we created
int num = trackstracer . OpenPaths . Count + trackstracer . ClosePaths . Count ;
if ( num = = 0 )
{
General . Interface . DisplayStatus ( StatusType . Warning , "No parallel tracks created." ) ;
General . Map . UndoRedo . WithdrawUndo ( ) ;
General . Map . UndoRedo . WithdrawUndo ( ) ;
return ;
}
if ( num > 1 )
General . Interface . DisplayStatus ( StatusType . Action , "Created " + num . ToString ( ) + " parallel tracks." ) ;
else
General . Interface . DisplayStatus ( StatusType . Action , "Created a parallel track." ) ;
if ( createas = = THINGS )
{
//Update Things filter
General . Map . ThingsFilter . Update ( ) ;
}
// Snap to map format accuracy
General . Map . Map . SnapAllToAccuracy ( ) ;
// Clear selection
General . Map . Map . ClearAllSelected ( ) ;
// Update cached values
General . Map . Map . Update ( ) ;
// Edit new sectors?
List < Sector > newsectors = General . Map . Map . GetMarkedSectors ( true ) ;
if ( BuilderPlug . Me . EditNewSector & & ( newsectors . Count > 0 ) )
General . Interface . ShowEditSectors ( newsectors ) ;
// Update the used textures
General . Map . Data . UpdateUsedTextures ( ) ;
//mxd
General . Map . Renderer2D . UpdateExtraFloorFlag ( ) ;
// Map is changed
General . Map . IsChanged = true ;
// Return to base mode
General . Editing . ChangeMode ( General . Editing . PreviousStableMode . Name ) ;
}
// Redrawing display
public override void OnRedrawDisplay ( )
{
renderer . RedrawSurface ( ) ;
float vsize = ( renderer . VertexSize + 1.0f ) / renderer . Scale ;
// Render lines
if ( renderer . StartPlotter ( true ) )
{
renderer . PlotLinedefSet ( General . Map . Map . Linedefs ) ;
renderer . PlotVerticesSet ( General . Map . Map . Vertices ) ;
renderer . Finish ( ) ;
}
// Render things
if ( renderer . StartThings ( true ) )
{
renderer . RenderThingSet ( General . Map . Map . Things , Presentation . THINGS_ALPHA ) ;
2023-05-01 18:08:25 +00:00
renderer . RenderSRB2Extras ( ) ;
2020-08-29 14:26:59 +00:00
renderer . Finish ( ) ;
}
int createas = BuilderPlug . Me . ParallelLinedefForm . CreateAs ;
float distance = BuilderPlug . Me . ParallelLinedefForm . Distance ;
bool closeopenpath = BuilderPlug . Me . ParallelLinedefForm . CloseOpenPath ;
bool backwards = BuilderPlug . Me . ParallelLinedefForm . Backwards ;
// Render overlay
bool renderlines = ( createas < = LINEDEFS ) ;
if ( renderer . StartOverlay ( true ) )
{
foreach ( List < Vector2D > path in trackstracer . OpenPaths )
{
// Selected path in info color
for ( int i = 1 ; i < path . Count ; i + + )
renderer . RenderLine ( path [ i - 1 ] , path [ i ] , LINE_THICKNESS , General . Colors . InfoLine , true ) ;
renderer . RenderRectangleFilled ( new RectangleF ( path [ 0 ] . x - vsize , path [ 0 ] . y - vsize , vsize * 2.0f , vsize * 2.0f ) , General . Colors . InfoLine , true ) ;
renderer . RenderRectangleFilled ( new RectangleF ( path [ path . Count - 1 ] . x - vsize , path [ path . Count - 1 ] . y - vsize , vsize * 2.0f , vsize * 2.0f ) , General . Colors . InfoLine , true ) ;
// Parallel path
List < Vector2D > parallelpath = TracksTracer . ParallelizeOpenPath ( path , distance , backwards ) ;
renderer . RenderRectangleFilled ( new RectangleF ( parallelpath [ 0 ] . x - vsize , parallelpath [ 0 ] . y - vsize , vsize * 2.0f , vsize * 2.0f ) , General . Colors . Highlight , true ) ;
for ( int i = 1 ; i < parallelpath . Count ; i + + )
{
if ( renderlines ) renderer . RenderLine ( parallelpath [ i - 1 ] , parallelpath [ i ] , LINE_THICKNESS , General . Colors . Highlight , true ) ;
renderer . RenderRectangleFilled ( new RectangleF ( parallelpath [ i ] . x - vsize , parallelpath [ i ] . y - vsize , vsize * 2.0f , vsize * 2.0f ) , General . Colors . Highlight , true ) ;
}
if ( closeopenpath & & renderlines )
{
renderer . RenderLine ( path [ 0 ] , parallelpath [ 0 ] , LINE_THICKNESS , General . Colors . Highlight , true ) ;
renderer . RenderLine ( path [ path . Count - 1 ] , parallelpath [ parallelpath . Count - 1 ] , LINE_THICKNESS , General . Colors . Highlight , true ) ;
}
}
foreach ( List < Vector2D > path in trackstracer . ClosePaths )
{
// Selected path in info color
for ( int i = 1 ; i < path . Count ; i + + )
renderer . RenderLine ( path [ i - 1 ] , path [ i ] , LINE_THICKNESS , General . Colors . InfoLine , true ) ;
renderer . RenderRectangleFilled ( new RectangleF ( path [ 0 ] . x - vsize , path [ 0 ] . y - vsize , vsize * 2.0f , vsize * 2.0f ) , General . Colors . InfoLine , true ) ;
renderer . RenderRectangleFilled ( new RectangleF ( path [ path . Count - 1 ] . x - vsize , path [ path . Count - 1 ] . y - vsize , vsize * 2.0f , vsize * 2.0f ) , General . Colors . InfoLine , true ) ;
// Parallel path
List < Vector2D > parallelpath = TracksTracer . ParallelizeClosePath ( path , distance , backwards ) ;
renderer . RenderRectangleFilled ( new RectangleF ( parallelpath [ 0 ] . x - vsize , parallelpath [ 0 ] . y - vsize , vsize * 2.0f , vsize * 2.0f ) , General . Colors . Highlight , true ) ;
for ( int i = 1 ; i < parallelpath . Count ; i + + )
{
if ( renderlines ) renderer . RenderLine ( parallelpath [ i - 1 ] , parallelpath [ i ] , LINE_THICKNESS , General . Colors . Highlight , true ) ;
renderer . RenderRectangleFilled ( new RectangleF ( parallelpath [ i ] . x - vsize , parallelpath [ i ] . y - vsize , vsize * 2.0f , vsize * 2.0f ) , General . Colors . Highlight , true ) ;
}
}
renderer . Finish ( ) ;
}
renderer . Present ( ) ;
}
#endregion
}
}