2013-09-13 14:54:43 +00:00
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
2012-06-19 13:12:28 +00:00
using System.Collections.Generic ;
using System.Drawing ;
using System.Windows.Forms ;
2014-12-03 23:15:26 +00:00
using CodeImp.DoomBuilder.Config ;
2012-06-19 13:12:28 +00:00
using CodeImp.DoomBuilder.Editing ;
using CodeImp.DoomBuilder.Rendering ;
using CodeImp.DoomBuilder.Geometry ;
using CodeImp.DoomBuilder.Actions ;
using CodeImp.DoomBuilder.Windows ;
using CodeImp.DoomBuilder.Map ;
using CodeImp.DoomBuilder.BuilderModes.Interface ;
2013-09-13 14:54:43 +00:00
#endregion
2014-12-03 23:15:26 +00:00
namespace CodeImp.DoomBuilder.BuilderModes.ClassicModes
{
2013-09-11 09:47:53 +00:00
[ EditMode ( DisplayName = "Bridge Mode" ,
SwitchAction = "bridgemode" ,
ButtonImage = "BridgeMode.png" ,
2014-02-26 14:11:06 +00:00
ButtonOrder = 2 ,
ButtonGroup = "002_modify" ,
2013-09-11 09:47:53 +00:00
AllowCopyPaste = false ,
Volatile = true ,
Optional = false ) ]
2013-09-13 14:54:43 +00:00
public class BridgeMode : BaseClassicMode
{
#region = = = = = = = = = = = = = = = = = = Constants
2013-09-11 09:47:53 +00:00
private const float GRIP_SIZE = 9.0f ;
private const float LINE_THICKNESS = 0.8f ;
2013-09-27 10:56:44 +00:00
internal const int MAX_SUBDIVISIONS = 32 ;
internal const int MIN_SUBDIVISIONS = 0 ;
2013-09-11 09:47:53 +00:00
2013-09-13 14:54:43 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
2013-09-11 09:47:53 +00:00
private Vector2D [ ] pointGroup1 ;
private Vector2D [ ] pointGroup2 ;
private SectorProperties [ ] sectorProps1 ;
private SectorProperties [ ] sectorProps2 ;
private float [ ] relLenGroup1 ;
private float [ ] relLenGroup2 ;
private ControlHandle [ ] controlHandles ;
private int curControlHandle = - 1 ;
private PixelColor handleColor ;
private List < Vector2D [ ] > curves ;
private int segmentsCount ;
// Options
2014-12-03 23:15:26 +00:00
private bool snaptogrid ; // SHIFT to toggle
2013-09-11 09:47:53 +00:00
//tools form
private BridgeModeForm form ;
2013-09-13 14:54:43 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
2014-12-03 23:15:26 +00:00
public BridgeMode ( )
{
2013-09-11 09:47:53 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
2013-09-13 14:54:43 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
2013-09-11 09:47:53 +00:00
// Engaging
2014-12-03 23:15:26 +00:00
public override void OnEngage ( )
{
2013-09-11 09:47:53 +00:00
base . OnEngage ( ) ;
renderer . SetPresentation ( Presentation . Standard ) ;
//check selection
ICollection < Linedef > selection = General . Map . Map . GetSelectedLinedefs ( true ) ;
List < Line > lines = new List < Line > ( ) ;
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
foreach ( Linedef ld in selection )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
Line l = new Line ( ld ) ;
lines . Add ( l ) ;
}
//do we have valid selection?
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 ( ! Setup ( lines ) )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
FinishDraw ( ) ;
return ;
}
//show form
form = new BridgeModeForm ( ) ;
2014-02-10 09:26:13 +00:00
form . OnCancelClick + = form_OnCancelClick ;
form . OnOkClick + = form_OnOkClick ;
form . OnFlipClick + = form_OnFlipClick ;
form . OnSubdivisionChanged + = form_OnSubdivisionChanged ;
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
form . Show ( General . Interface ) ;
2013-09-11 09:47:53 +00:00
General . Interface . FocusDisplay ( ) ;
handleColor = General . Colors . BrightColors [ new Random ( ) . Next ( General . Colors . BrightColors . Length - 1 ) ] ;
2014-12-03 23:15:26 +00:00
Update ( ) ;
2013-09-11 09:47:53 +00:00
}
// When select button is pressed
2014-12-03 23:15:26 +00:00
protected override void OnSelectBegin ( )
{
2013-09-11 09:47:53 +00:00
base . OnSelectBegin ( ) ;
//check if control handle is selected
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < 4 ; i + + )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
if ( mousemappos . x < = controlHandles [ i ] . Position . x + GRIP_SIZE
2014-12-03 23:15:26 +00:00
& & mousemappos . x > = controlHandles [ i ] . Position . x - GRIP_SIZE
& & mousemappos . y < = controlHandles [ i ] . Position . y + GRIP_SIZE
& & mousemappos . y > = controlHandles [ i ] . Position . y - GRIP_SIZE )
{
2013-09-11 09:47:53 +00:00
curControlHandle = i ;
General . Interface . SetCursor ( Cursors . Cross ) ;
return ;
}
}
curControlHandle = - 1 ;
}
// When select button is released
2014-12-03 23:15:26 +00:00
protected override void OnSelectEnd ( )
{
2013-09-11 09:47:53 +00:00
base . OnSelectEnd ( ) ;
General . Interface . SetCursor ( Cursors . Default ) ;
curControlHandle = - 1 ;
}
// Mouse moves
2014-12-03 23:15:26 +00:00
public override void OnMouseMove ( MouseEventArgs e )
{
2013-09-11 09:47:53 +00:00
base . OnMouseMove ( e ) ;
2013-07-29 08:50:50 +00:00
if ( panning ) return ; //mxd. Skip all this jass while panning
2012-06-19 13:12:28 +00:00
2015-12-28 15:01:53 +00:00
if ( curControlHandle ! = - 1 )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
ControlHandle handle = controlHandles [ curControlHandle ] ;
2014-12-03 23:15:26 +00:00
handle . Position = ( snaptogrid ? General . Map . Grid . SnappedToGrid ( mousemappos ) : mousemappos ) ;
2012-06-19 13:12:28 +00:00
2015-12-28 15:01:53 +00:00
if ( form . MirrorMode )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
Vector2D pos = handle . RelativePosition ;
//handle angle
2013-09-27 10:56:44 +00:00
float angle = ( float ) Math . Atan2 ( - pos . y , - pos . x ) + Angle2D . PIHALF ;
2013-09-11 09:47:53 +00:00
//angle of line, connecting handles ControlledPoints
float dirAngle = - ( float ) Math . Atan2 ( handle . Pair . ControlledPoint . y - handle . ControlledPoint . y , handle . Pair . ControlledPoint . x - handle . ControlledPoint . x ) ;
float length = ( float ) Math . Sqrt ( Math . Pow ( Math . Abs ( pos . x ) , 2.0 ) + Math . Pow ( Math . Abs ( pos . y ) , 2.0 ) ) ;
float mirroredAngle = angle + dirAngle * 2.0f ;
handle . Pair . RelativePosition = new Vector2D ( ( float ) Math . Sin ( mirroredAngle ) * length , ( float ) Math . Cos ( mirroredAngle ) * length ) ;
2014-12-03 23:15:26 +00:00
}
2015-12-28 15:01:53 +00:00
else if ( form . CopyMode )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
handle . Pair . RelativePosition = handle . RelativePosition ;
}
2014-12-03 23:15:26 +00:00
Update ( ) ;
2013-09-11 09:47:53 +00:00
}
}
// Accepted
2014-12-03 23:15:26 +00:00
public override void OnAccept ( )
{
2013-09-11 09:47:53 +00:00
Cursor . Current = Cursors . AppStarting ;
General . Settings . FindDefaultDrawSettings ( ) ;
//get vertices
2014-12-03 23:15:26 +00:00
List < List < Vector2D [ ] > > shapes = GetShapes ( ) ;
2013-09-11 09:47:53 +00:00
List < List < List < DrawnVertex > > > drawShapes = new List < List < List < DrawnVertex > > > ( ) ;
//set stitch range
float stitchrange = BuilderPlug . Me . StitchRange ;
BuilderPlug . Me . StitchRange = 0.1f ;
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < shapes . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
List < List < DrawnVertex > > shapesRow = new List < List < DrawnVertex > > ( ) ;
for ( int c = 0 ; c < shapes [ i ] . Count ; c + + )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
List < DrawnVertex > points = new List < DrawnVertex > ( ) ;
for ( int p = 0 ; p < shapes [ i ] [ c ] . Length ; p + + )
2016-04-21 21:00:58 +00:00
points . Add ( DrawGeometryMode . GetCurrentPosition ( shapes [ i ] [ c ] [ p ] , true , false , false , false , renderer , points ) ) ;
2013-09-11 09:47:53 +00:00
shapesRow . Add ( points ) ;
}
drawShapes . Add ( shapesRow ) ;
}
//restore stitch range
BuilderPlug . Me . StitchRange = stitchrange ;
//draw lines
2015-12-28 15:01:53 +00:00
if ( drawShapes . Count > 0 )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
// Make undo for the draw
General . Map . UndoRedo . CreateUndo ( "Bridge (" + form . Subdivisions + " subdivisions)" ) ;
List < List < SectorProperties > > sectorProps = new List < List < SectorProperties > > ( ) ;
2016-05-20 15:04:00 +00:00
List < List < HashSet < Sector > > > newSectors = new List < List < HashSet < Sector > > > ( ) ;
2013-09-11 09:47:53 +00:00
//create sector properties collection
//sector row
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < drawShapes . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
sectorProps . Add ( new List < SectorProperties > ( ) ) ;
//sector in row
2015-12-28 15:01:53 +00:00
for ( int c = 0 ; c < drawShapes [ i ] . Count ; c + + )
2014-12-03 23:15:26 +00:00
sectorProps [ i ] . Add ( GetSectorProperties ( i , c ) ) ;
2013-09-11 09:47:53 +00:00
}
// Make the drawing
//sector row
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < drawShapes . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2016-05-20 15:04:00 +00:00
newSectors . Add ( new List < HashSet < Sector > > ( ) ) ;
2013-09-11 09:47:53 +00:00
//sector in row
2015-12-28 15:01:53 +00:00
for ( int c = 0 ; c < drawShapes [ i ] . Count ; c + + )
2014-12-03 23:15:26 +00:00
{
if ( ! Tools . DrawLines ( drawShapes [ i ] [ c ] , false , true ) )
{
2013-09-11 09:47:53 +00:00
// Drawing failed
// NOTE: I have to call this twice, because the first time only cancels this volatile mode
General . Interface . DisplayStatus ( StatusType . Warning , "Failed to create a Bezier Path..." ) ;
General . Map . UndoRedo . WithdrawUndo ( ) ;
General . Map . UndoRedo . WithdrawUndo ( ) ;
return ;
}
2016-05-20 15:04:00 +00:00
HashSet < Sector > newsectors = General . Map . Map . GetUnselectedSectorsFromLinedefs ( General . Map . Map . GetMarkedLinedefs ( true ) ) ;
2013-09-11 09:47:53 +00:00
newSectors [ i ] . Add ( newsectors ) ;
//set floor/ceiling heights and brightness
2016-05-20 15:04:00 +00:00
foreach ( Sector s in newsectors )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
SectorProperties sp = sectorProps [ i ] [ c ] ;
s . Brightness = sp . Brightness ;
s . FloorHeight = sp . FloorHeight ;
s . CeilHeight = ( sp . CeilingHeight < sp . FloorHeight ? sp . FloorHeight + 8 : sp . CeilingHeight ) ;
}
}
}
//apply textures
//sector row
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < newSectors . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
//sector in row
2015-12-28 15:01:53 +00:00
for ( int c = 0 ; c < newSectors [ i ] . Count ; c + + )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
foreach ( Sector s in newSectors [ i ] [ c ] )
2014-12-03 23:15:26 +00:00
{
foreach ( Sidedef sd in s . Sidedefs )
{
2015-12-28 15:01:53 +00:00
if ( sd . LowRequired ( ) )
2012-11-27 23:04:49 +00:00
sd . SetTextureLow ( sectorProps [ i ] [ c ] . LowTexture ) ;
2015-12-28 15:01:53 +00:00
if ( sd . HighRequired ( ) )
2013-09-11 09:47:53 +00:00
sd . SetTextureHigh ( sectorProps [ i ] [ c ] . HighTexture ) ;
}
}
}
}
//apply textures to front/back sides of shape
//sector row
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < newSectors . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
//first/last sector in row
2015-12-28 15:01:53 +00:00
for ( int c = 0 ; c < newSectors [ i ] . Count ; c + = newSectors [ i ] . Count - 1 )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
foreach ( Sector s in newSectors [ i ] [ c ] )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
foreach ( Sidedef sd in s . Sidedefs )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
if ( sd . Other ! = null )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
if ( sd . Other . LowRequired ( ) & & sd . Other . LowTexture = = "-" )
2013-09-11 09:47:53 +00:00
sd . Other . SetTextureLow ( sectorProps [ i ] [ c ] . LowTexture ) ;
2015-12-28 15:01:53 +00:00
if ( sd . Other . HighRequired ( ) & & sd . Other . HighTexture = = "-" )
2013-09-11 09:47:53 +00:00
sd . Other . SetTextureHigh ( sectorProps [ i ] [ c ] . HighTexture ) ;
}
}
}
}
}
General . Interface . DisplayStatus ( StatusType . Action , "Created a Bridge with " + form . Subdivisions + " subdivisions." ) ;
// Snap to map format accuracy
General . Map . Map . SnapAllToAccuracy ( ) ;
// Clear selection
General . Map . Map . ClearAllSelected ( ) ;
// Update cached values
General . Map . Map . Update ( ) ;
// Update the used textures
General . Map . Data . UpdateUsedTextures ( ) ;
// Map is changed
General . Map . IsChanged = true ;
}
//close form
2015-12-28 15:01:53 +00:00
if ( form ! = null ) form . Close ( ) ;
2013-09-11 09:47:53 +00:00
// Done
Cursor . Current = Cursors . Default ;
// Return to original mode
General . Editing . ChangeMode ( General . Editing . PreviousStableMode . Name ) ;
}
// Cancelled
2014-12-03 23:15:26 +00:00
public override void OnCancel ( )
{
2013-09-11 09:47:53 +00:00
// Cancel base class
base . OnCancel ( ) ;
//close form
2015-12-28 15:01:53 +00:00
if ( form ! = null ) form . Dispose ( ) ;
2013-09-11 09:47:53 +00:00
// Return to original mode
General . Editing . ChangeMode ( General . Editing . PreviousStableMode . Name ) ;
}
// When a key is released
2014-12-03 23:15:26 +00:00
public override void OnKeyUp ( KeyEventArgs e )
{
2013-09-11 09:47:53 +00:00
base . OnKeyUp ( e ) ;
2015-12-28 15:01:53 +00:00
if ( snaptogrid ! = ( General . Interface . ShiftState ^ General . Interface . SnapToGrid ) ) Update ( ) ;
2013-09-11 09:47:53 +00:00
}
// When a key is pressed
2014-12-03 23:15:26 +00:00
public override void OnKeyDown ( KeyEventArgs e )
{
2013-09-11 09:47:53 +00:00
base . OnKeyDown ( e ) ;
2015-12-28 15:01:53 +00:00
if ( snaptogrid ! = ( General . Interface . ShiftState ^ General . Interface . SnapToGrid ) ) Update ( ) ;
2013-09-11 09:47:53 +00:00
}
// This redraws the display
2014-12-03 23:15:26 +00:00
public override void OnRedrawDisplay ( )
{
2013-09-11 09:47:53 +00:00
renderer . RedrawSurface ( ) ;
// Render lines
2015-12-28 15:01:53 +00:00
if ( renderer . StartPlotter ( true ) )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
renderer . PlotLinedefSet ( General . Map . Map . Linedefs ) ;
renderer . PlotVerticesSet ( General . Map . Map . Vertices ) ;
renderer . Finish ( ) ;
}
// Render things
2015-12-28 15:01:53 +00:00
if ( renderer . StartThings ( true ) )
2014-12-03 23:15:26 +00:00
{
2016-04-01 10:49:19 +00:00
renderer . RenderThingSet ( General . Map . Map . Things , General . Settings . ActiveThingsAlpha ) ;
2013-09-11 09:47:53 +00:00
renderer . Finish ( ) ;
}
// Normal update
2014-12-03 23:15:26 +00:00
Update ( ) ;
2013-09-11 09:47:53 +00:00
}
2014-12-03 23:15:26 +00:00
public override void OnHelp ( )
{
2013-09-13 14:54:43 +00:00
General . ShowHelp ( "/gzdb/features/classic_modes/mode_drawbridge.html" ) ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Setup / Update / Utility
2013-09-11 09:47:53 +00:00
//this checks if initial data is valid
2014-12-03 23:15:26 +00:00
private bool Setup ( List < Line > lines )
{
2015-12-28 15:01:53 +00:00
if ( ! SetupPointGroups ( lines ) ) return false ;
2013-09-11 09:47:53 +00:00
//setup control handles
Vector2D center1 = CurveTools . GetPointOnLine ( pointGroup1 [ 0 ] , pointGroup1 [ segmentsCount - 1 ] , 0.5f ) ;
2013-04-08 13:43:02 +00:00
Vector2D center2 = CurveTools . GetPointOnLine ( pointGroup2 [ 0 ] , pointGroup2 [ segmentsCount - 1 ] , 0.5f ) ;
2012-06-19 13:12:28 +00:00
2014-12-03 23:15:26 +00:00
Vector2D loc1 = GetHandleLocation ( pointGroup1 [ 0 ] , pointGroup1 [ segmentsCount - 1 ] , center2 ) ;
Vector2D loc2 = GetHandleLocation ( pointGroup2 [ 0 ] , pointGroup2 [ segmentsCount - 1 ] , center1 ) ;
2012-06-19 13:12:28 +00:00
2014-12-03 23:15:26 +00:00
ControlHandle ch1 = new ControlHandle { ControlledPoint = pointGroup1 [ 0 ] , RelativePosition = loc1 } ;
ControlHandle ch2 = new ControlHandle { ControlledPoint = pointGroup2 [ 0 ] , RelativePosition = loc2 } ;
ControlHandle ch3 = new ControlHandle { ControlledPoint = pointGroup1 [ segmentsCount - 1 ] , RelativePosition = loc1 } ;
ControlHandle ch4 = new ControlHandle { ControlledPoint = pointGroup2 [ segmentsCount - 1 ] , RelativePosition = loc2 } ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
ch1 . Pair = ch3 ;
ch2 . Pair = ch4 ;
ch3 . Pair = ch1 ;
ch4 . Pair = ch2 ;
2012-06-19 13:12:28 +00:00
2013-09-27 10:56:44 +00:00
controlHandles = new [ ] { ch1 , ch2 , ch3 , ch4 } ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
//setup relative segments lengths
2014-12-03 23:15:26 +00:00
relLenGroup1 = GetRelativeLengths ( pointGroup1 ) ;
relLenGroup2 = GetRelativeLengths ( pointGroup2 ) ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
return true ;
}
2012-06-19 13:12:28 +00:00
2014-12-03 23:15:26 +00:00
private void Update ( )
{
2015-12-28 15:01:53 +00:00
if ( renderer . StartOverlay ( true ) )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
snaptogrid = General . Interface . ShiftState ^ General . Interface . SnapToGrid ;
PixelColor linesColor = snaptogrid ? General . Colors . Selection : General . Colors . Highlight ;
//draw curves
curves = new List < Vector2D [ ] > ( ) ;
2012-06-19 13:12:28 +00:00
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < segmentsCount ; i + + )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
Vector2D cp1 = CurveTools . GetPointOnLine ( controlHandles [ 0 ] . Position , controlHandles [ 2 ] . Position , relLenGroup1 [ i ] ) ;
Vector2D cp2 = CurveTools . GetPointOnLine ( controlHandles [ 1 ] . Position , controlHandles [ 3 ] . Position , relLenGroup2 [ i ] ) ;
2013-04-08 13:43:02 +00:00
curves . Add ( CurveTools . GetCubicCurve ( pointGroup1 [ i ] , pointGroup2 [ i ] , cp1 , cp2 , form . Subdivisions ) ) ;
2012-06-19 13:12:28 +00:00
2015-12-28 15:01:53 +00:00
for ( int c = 1 ; c < curves [ i ] . Length ; c + + )
2013-09-11 09:47:53 +00:00
renderer . RenderLine ( curves [ i ] [ c - 1 ] , curves [ i ] [ c ] , LINE_THICKNESS , linesColor , true ) ;
}
//draw connecting lines
2015-12-28 15:01:53 +00:00
if ( form . Subdivisions > 1 )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
for ( int i = 1 ; i < segmentsCount ; i + + )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
for ( int c = 1 ; c < form . Subdivisions ; c + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
renderer . RenderLine ( curves [ i - 1 ] [ c ] , curves [ i ] [ c ] , LINE_THICKNESS , linesColor , true ) ;
}
}
}
//draw vertices
2013-09-27 10:56:44 +00:00
float vsize = ( renderer . VertexSize + 1.0f ) / renderer . Scale ;
2013-09-11 09:47:53 +00:00
2014-12-03 23:15:26 +00:00
foreach ( Vector2D [ ] points in curves )
{
2015-12-28 15:01:53 +00:00
for ( int i = 1 ; i < points . Length - 1 ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
renderer . RenderRectangleFilled ( new RectangleF ( points [ i ] . x - vsize , points [ i ] . y - vsize , vsize * 2.0f , vsize * 2.0f ) , linesColor , true ) ;
}
}
//draw handle lines
renderer . RenderLine ( pointGroup1 [ 0 ] , controlHandles [ 0 ] . Position , LINE_THICKNESS , handleColor , true ) ;
renderer . RenderLine ( pointGroup2 [ 0 ] , controlHandles [ 1 ] . Position , LINE_THICKNESS , handleColor , true ) ;
renderer . RenderLine ( pointGroup1 [ segmentsCount - 1 ] , controlHandles [ 2 ] . Position , LINE_THICKNESS , handleColor , true ) ;
renderer . RenderLine ( pointGroup2 [ segmentsCount - 1 ] , controlHandles [ 3 ] . Position , LINE_THICKNESS , handleColor , true ) ;
//draw handles
float gripsize = GRIP_SIZE / renderer . Scale ;
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < 4 ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
RectangleF handleRect = new RectangleF ( controlHandles [ i ] . Position . x - gripsize * 0.5f , controlHandles [ i ] . Position . y - gripsize * 0.5f , gripsize , gripsize ) ;
renderer . RenderRectangleFilled ( handleRect , General . Colors . Background , true ) ;
renderer . RenderRectangle ( handleRect , 2 , General . Colors . Highlight , true ) ;
}
renderer . Finish ( ) ;
}
renderer . Present ( ) ;
}
2014-12-03 23:15:26 +00:00
private SectorProperties GetSectorProperties ( int lineIndex , int sectorIndex )
{
2013-09-27 10:56:44 +00:00
float delta = sectorIndex / ( float ) form . Subdivisions ;
delta + = ( 1.0f - delta ) / form . Subdivisions ;
2013-09-11 09:47:53 +00:00
SectorProperties sp = new SectorProperties ( ) ;
2014-12-03 23:15:26 +00:00
sp . Brightness = IntepolateValue ( sectorProps1 [ lineIndex ] . Brightness , sectorProps2 [ lineIndex ] . Brightness , delta , form . BrightnessMode ) ;
sp . FloorHeight = IntepolateValue ( sectorProps1 [ lineIndex ] . FloorHeight , sectorProps2 [ lineIndex ] . FloorHeight , delta , form . FloorAlignMode ) ;
sp . CeilingHeight = IntepolateValue ( sectorProps1 [ lineIndex ] . CeilingHeight , sectorProps2 [ lineIndex ] . CeilingHeight , delta , form . CeilingAlignMode ) ;
2013-09-11 09:47:53 +00:00
//textures
sp . LowTexture = sectorProps1 [ lineIndex ] . LowTexture ! = "-" ? sectorProps1 [ lineIndex ] . LowTexture : sectorProps2 [ lineIndex ] . LowTexture ;
sp . HighTexture = sectorProps1 [ lineIndex ] . HighTexture ! = "-" ? sectorProps1 [ lineIndex ] . HighTexture : sectorProps2 [ lineIndex ] . HighTexture ;
return sp ;
}
//this returns a list of shapes to draw
2014-12-03 23:15:26 +00:00
private List < List < Vector2D [ ] > > GetShapes ( )
{
2013-09-11 09:47:53 +00:00
List < List < Vector2D [ ] > > shapes = new List < List < Vector2D [ ] > > ( ) ;
2015-12-28 15:01:53 +00:00
for ( int i = 1 ; i < segmentsCount ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
List < Vector2D [ ] > segShapes = new List < Vector2D [ ] > ( ) ;
2015-12-28 15:01:53 +00:00
for ( int c = 1 ; c < = form . Subdivisions ; c + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
Vector2D p0 = curves [ i - 1 ] [ c - 1 ] ;
Vector2D p1 = curves [ i - 1 ] [ c ] ;
Vector2D p2 = curves [ i ] [ c ] ;
Vector2D p3 = curves [ i ] [ c - 1 ] ;
2013-09-27 10:56:44 +00:00
segShapes . Add ( new [ ] { p0 , p1 , p2 , p3 , p0 } ) ;
2013-09-11 09:47:53 +00:00
}
shapes . Add ( segShapes ) ;
}
return shapes ;
}
2012-06-19 13:12:28 +00:00
2013-09-13 14:54:43 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Point ops
2013-09-11 09:47:53 +00:00
//this returns an array of linedef lengths relative to total segment length
2014-12-03 23:15:26 +00:00
private float [ ] GetRelativeLengths ( Vector2D [ ] pointGroup )
{
2013-09-11 09:47:53 +00:00
float [ ] relLenGroup = new float [ pointGroup . Length ] ;
relLenGroup [ 0 ] = 0.0f ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
//get length and angle of line, which defines the shape
2014-12-03 23:15:26 +00:00
float length = Vector2D . Distance ( pointGroup [ 0 ] , pointGroup [ segmentsCount - 1 ] ) ;
2013-09-11 09:47:53 +00:00
float angle = ( float ) Math . Atan2 ( pointGroup [ 0 ] . y - pointGroup [ segmentsCount - 1 ] . y , pointGroup [ 0 ] . x - pointGroup [ segmentsCount - 1 ] . x ) ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
//get relative length of every line
2015-12-28 15:01:53 +00:00
for ( int i = 1 ; i < pointGroup . Length - 1 ; i + + )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
Vector2D p0 = pointGroup [ i - 1 ] ;
Vector2D p1 = pointGroup [ i ] ;
float curAngle = ( float ) Math . Atan2 ( p0 . y - p1 . y , p0 . x - p1 . x ) ;
float diff = ( angle + Angle2D . PI ) - ( curAngle + Angle2D . PI ) ;
float segLen = ( int ) ( Vector2D . Distance ( p0 , p1 ) * Math . Cos ( diff ) ) ;
2013-09-11 09:47:53 +00:00
relLenGroup [ i ] = relLenGroup [ i - 1 ] + segLen / length ;
}
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
relLenGroup [ pointGroup . Length - 1 ] = 1.0f ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
return relLenGroup ;
}
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
//this returns relative handle location
2014-12-03 23:15:26 +00:00
private static Vector2D GetHandleLocation ( Vector2D start , Vector2D end , Vector2D direction )
{
2013-09-11 09:47:53 +00:00
float angle = - ( float ) Math . Atan2 ( start . y - end . y , start . x - end . x ) ;
float dirAngle = - ( float ) Math . Atan2 ( direction . y - start . y , direction . x - start . x ) ;
float length = ( float ) Math . Sqrt ( Math . Pow ( Math . Abs ( start . x - end . x ) , 2.0 ) + Math . Pow ( Math . Abs ( start . y - end . y ) , 2.0 ) ) * 0.3f ;
2013-04-11 09:27:16 +00:00
float diff = ( angle + Angle2D . PI ) - ( dirAngle + Angle2D . PI ) ;
2012-06-19 13:12:28 +00:00
2014-12-03 23:15:26 +00:00
if ( diff > Angle2D . PI | | ( diff < 0 & & diff > - Angle2D . PI ) ) angle + = Angle2D . PI ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
return new Vector2D ( ( float ) ( Math . Sin ( angle ) * length ) , ( float ) ( Math . Cos ( angle ) * length ) ) ;
}
2012-06-19 13:12:28 +00:00
//LINE DRAWING
2013-09-11 09:47:53 +00:00
//returns true if 2 lines intersect
2014-12-03 23:15:26 +00:00
private static bool LinesIntersect ( Line line1 , Line line2 )
{
2013-09-11 09:47:53 +00:00
float zn = ( line2 . End . y - line2 . Start . y ) * ( line1 . End . x - line1 . Start . x ) - ( line2 . End . x - line2 . Start . x ) * ( line1 . End . y - line1 . Start . y ) ;
float ch1 = ( line2 . End . x - line2 . Start . x ) * ( line1 . Start . y - line2 . Start . y ) - ( line2 . End . y - line2 . Start . y ) * ( line1 . Start . x - line2 . Start . x ) ;
float ch2 = ( line1 . End . x - line1 . Start . x ) * ( line1 . Start . y - line2 . Start . y ) - ( line1 . End . y - line1 . Start . y ) * ( line1 . Start . x - line2 . Start . x ) ;
2012-06-19 13:12:28 +00:00
2015-12-28 15:01:53 +00:00
if ( zn = = 0 ) return false ;
2014-05-20 09:09:28 +00:00
return ( ch1 / zn < = 1 & & ch1 / zn > = 0 ) & & ( ch2 / zn < = 1 & & ch2 / zn > = 0 ) ;
2013-09-11 09:47:53 +00:00
}
2012-06-19 13:12:28 +00:00
2013-09-13 14:54:43 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Line sorting
2013-09-11 09:47:53 +00:00
//this gets two arrays of connected points from given lines. Returns true if all went well.
2014-12-03 23:15:26 +00:00
private bool SetupPointGroups ( List < Line > linesList )
{
2013-09-11 09:47:53 +00:00
//find prev/next lines for each line
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < linesList . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
Line curLine = linesList [ i ] ;
2015-12-28 15:01:53 +00:00
for ( int c = 0 ; c < linesList . Count ; c + + )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
if ( c ! = i ) //don't wanna play with ourselves :)
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
Line line = linesList [ c ] ;
//check start and end points
2015-12-28 15:01:53 +00:00
if ( curLine . Start = = line . Start )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
line . Invert ( ) ;
curLine . Previous = line ;
2014-12-03 23:15:26 +00:00
}
2015-12-28 15:01:53 +00:00
else if ( curLine . Start = = line . End )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
curLine . Previous = line ;
2014-12-03 23:15:26 +00:00
}
2015-12-28 15:01:53 +00:00
else if ( curLine . End = = line . End )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
line . Invert ( ) ;
curLine . Next = line ;
2014-12-03 23:15:26 +00:00
}
2015-12-28 15:01:53 +00:00
else if ( curLine . End = = line . Start )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
curLine . Next = line ;
}
}
}
}
List < List < Vector2D > > pointGroups = new List < List < Vector2D > > ( ) ;
List < List < Line > > sortedLines = new List < List < Line > > ( ) ;
//now find start lines
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < linesList . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
Line curLine = linesList [ i ] ;
2015-12-28 15:01:53 +00:00
if ( curLine . Previous = = null ) //found start
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
//collect points
Line l = curLine ;
List < Vector2D > points = new List < Vector2D > ( ) ;
List < Line > lines = new List < Line > ( ) ;
points . Add ( l . Start ) ;
2014-12-03 23:15:26 +00:00
do
{
2013-09-11 09:47:53 +00:00
points . Add ( l . End ) ;
lines . Add ( l ) ;
2015-12-28 15:01:53 +00:00
} while ( ( l = l . Next ) ! = null ) ;
2013-09-11 09:47:53 +00:00
pointGroups . Add ( points ) ;
sortedLines . Add ( lines ) ;
}
}
2015-12-28 15:01:53 +00:00
if ( pointGroups . Count ! = 2 )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "Incorrect number of linedef groups! Expected 2, but got " + pointGroups . Count ) ;
return false ;
}
2015-12-28 15:01:53 +00:00
if ( pointGroups [ 0 ] . Count ! = pointGroups [ 1 ] . Count )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "Linedefs groups must have equal length! Got " + pointGroups [ 0 ] . Count + " in first group and " + pointGroups [ 1 ] . Count + " in second." ) ;
return false ;
}
//check if lines from first group intersect with lines from second group
2015-12-28 15:01:53 +00:00
foreach ( Line l1 in sortedLines [ 0 ] )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
foreach ( Line l2 in sortedLines [ 1 ] )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
if ( LinesIntersect ( l1 , l2 ) )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
General . Interface . DisplayStatus ( StatusType . Warning , "One or more lines from first group intersect with one or more lines from second group!" ) ;
return false ;
}
}
}
//both groups count should match at this point
segmentsCount = pointGroups [ 0 ] . Count ;
//collect sector properties
sectorProps1 = new SectorProperties [ sortedLines [ 0 ] . Count ] ;
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < sortedLines [ 0 ] . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
sectorProps1 [ i ] = sortedLines [ 0 ] [ i ] . SectorProperties ;
}
sectorProps2 = new SectorProperties [ sortedLines [ 1 ] . Count ] ;
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < sortedLines [ 1 ] . Count ; i + + )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
sectorProps2 [ i ] = sortedLines [ 1 ] [ i ] . SectorProperties ;
}
//check if we need to reverse one of point groups
Line line1 = new Line ( pointGroups [ 0 ] [ 0 ] , pointGroups [ 1 ] [ 0 ] ) ;
Line line2 = new Line ( pointGroups [ 0 ] [ segmentsCount - 1 ] , pointGroups [ 1 ] [ segmentsCount - 1 ] ) ;
2015-12-28 15:01:53 +00:00
if ( LinesIntersect ( line1 , line2 ) )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
pointGroups [ 0 ] . Reverse ( ) ;
Array . Reverse ( sectorProps1 ) ;
}
//fill point groups
pointGroup1 = new Vector2D [ segmentsCount ] ;
pointGroup2 = new Vector2D [ segmentsCount ] ;
pointGroups [ 0 ] . CopyTo ( pointGroup1 ) ;
pointGroups [ 1 ] . CopyTo ( pointGroup2 ) ;
return true ;
}
2012-06-19 13:12:28 +00:00
2013-09-13 14:54:43 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Easing functions
2012-06-19 13:12:28 +00:00
2014-12-03 23:15:26 +00:00
private static int IntepolateValue ( int val1 , int val2 , float delta , string mode )
{
2015-12-28 15:01:53 +00:00
switch ( mode )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
case BridgeInterpolationMode . HIGHEST :
case BridgeInterpolationMode . BRIGHTNESS_HIGHEST :
return Math . Max ( val1 , val2 ) ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
case BridgeInterpolationMode . LOWEST :
case BridgeInterpolationMode . BRIGHTNESS_LOWEST :
return Math . Min ( val1 , val2 ) ;
case BridgeInterpolationMode . LINEAR :
2016-06-03 20:22:07 +00:00
return ( int ) Math . Round ( InterpolationTools . Linear ( val1 , val2 , delta ) ) ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
case BridgeInterpolationMode . IN_SINE :
2016-06-03 20:22:07 +00:00
return ( int ) Math . Round ( InterpolationTools . EaseInSine ( val1 , val2 , delta ) ) ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
case BridgeInterpolationMode . OUT_SINE :
2016-06-03 20:22:07 +00:00
return ( int ) Math . Round ( InterpolationTools . EaseOutSine ( val1 , val2 , delta ) ) ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
case BridgeInterpolationMode . IN_OUT_SINE :
2016-06-03 20:22:07 +00:00
return ( int ) Math . Round ( InterpolationTools . EaseInOutSine ( val1 , val2 , delta ) ) ;
2012-06-19 13:12:28 +00:00
2013-09-11 09:47:53 +00:00
default :
2016-03-08 20:41:06 +00:00
throw new Exception ( "DrawBezierPathMode.IntepolateValue: \"" + mode + "\" mode is not supported!" ) ;
2013-09-11 09:47:53 +00:00
}
}
2012-06-19 13:12:28 +00:00
2013-09-13 14:54:43 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Events
2014-12-03 23:15:26 +00:00
private void form_OnSubdivisionChanged ( object sender , EventArgs e )
{
Update ( ) ;
2013-09-11 09:47:53 +00:00
}
2014-12-03 23:15:26 +00:00
private void form_OnOkClick ( object sender , EventArgs e )
{
2013-09-11 09:47:53 +00:00
FinishDraw ( ) ;
}
2014-12-03 23:15:26 +00:00
private void form_OnCancelClick ( object sender , EventArgs e )
{
2013-09-11 09:47:53 +00:00
OnCancel ( ) ;
}
2014-12-03 23:15:26 +00:00
private void form_OnFlipClick ( object sender , EventArgs e )
{
2013-09-11 09:47:53 +00:00
Array . Reverse ( pointGroup1 ) ;
Array . Reverse ( sectorProps1 ) ;
//swap handles position
Vector2D p = controlHandles [ 0 ] . Position ;
controlHandles [ 0 ] . Position = controlHandles [ 2 ] . Position ;
controlHandles [ 2 ] . Position = p ;
2014-12-03 23:15:26 +00:00
Update ( ) ;
2013-09-11 09:47:53 +00:00
}
2012-06-19 13:12:28 +00:00
2013-09-13 14:54:43 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Actions
2013-09-11 09:47:53 +00:00
// Finish drawing
[BeginAction("finishdraw")]
2014-12-03 23:15:26 +00:00
private void FinishDraw ( )
{
2013-09-11 09:47:53 +00:00
// Accept the changes
General . Editing . AcceptMode ( ) ;
}
[BeginAction("increasesubdivlevel")]
2014-12-03 23:15:26 +00:00
private void IncreaseSubdivLevel ( )
{
2015-12-28 15:01:53 +00:00
if ( form ! = null & & form . Subdivisions < MAX_SUBDIVISIONS ) form . Subdivisions + + ;
2013-09-11 09:47:53 +00:00
}
[BeginAction("decreasesubdivlevel")]
2014-12-03 23:15:26 +00:00
private void DecreaseSubdivLevel ( )
{
2015-12-28 15:01:53 +00:00
if ( form ! = null & & form . Subdivisions > MIN_SUBDIVISIONS ) form . Subdivisions - - ;
2013-09-11 09:47:53 +00:00
}
2013-09-13 14:54:43 +00:00
#endregion
2013-09-11 09:47:53 +00:00
}
2013-09-13 14:54:43 +00:00
#region = = = = = = = = = = = = = = = = = = Helper classes
2014-12-03 23:15:26 +00:00
internal struct SectorProperties
{
2013-09-11 09:47:53 +00:00
public int FloorHeight ;
public int CeilingHeight ;
public int Brightness ;
public string HighTexture ;
public string LowTexture ;
}
internal class ControlHandle
{
public Vector2D Position ;
public Vector2D ControlledPoint ; //point, to which this handle is assigned
2014-12-03 23:15:26 +00:00
public Vector2D RelativePosition
{
get
{
2013-09-11 09:47:53 +00:00
return new Vector2D ( Position . x - ControlledPoint . x , Position . y - ControlledPoint . y ) ;
}
2014-12-03 23:15:26 +00:00
set
{
2013-09-11 09:47:53 +00:00
Position = new Vector2D ( ControlledPoint . x + value . x , ControlledPoint . y + value . y ) ;
}
}
public ControlHandle Pair ; //second handle, to which this handle is paired
}
2014-12-03 23:15:26 +00:00
internal class Line
{
2013-09-11 09:47:53 +00:00
public Vector2D Start { get { return start ; } }
private Vector2D start ;
public Vector2D End { get { return end ; } }
private Vector2D end ;
public SectorProperties SectorProperties ;
public Line Previous ;
public Line Next ;
2014-12-03 23:15:26 +00:00
public Line ( Linedef ld )
{
2013-09-11 09:47:53 +00:00
start = new Vector2D ( ( int ) ld . Start . Position . x , ( int ) ld . Start . Position . y ) ;
end = new Vector2D ( ( int ) ld . End . Position . x , ( int ) ld . End . Position . y ) ;
SectorProperties = new SectorProperties ( ) ;
2015-12-28 15:01:53 +00:00
if ( ld . Back ! = null )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
SectorProperties . CeilingHeight = ld . Back . Sector . CeilHeight ;
SectorProperties . FloorHeight = ld . Back . Sector . FloorHeight ;
SectorProperties . Brightness = ld . Back . Sector . Brightness ;
2012-11-27 23:04:49 +00:00
SectorProperties . HighTexture = ld . Back . HighTexture ! = "-" ? ld . Back . HighTexture : ld . Back . MiddleTexture ;
SectorProperties . LowTexture = ld . Back . LowTexture ! = "-" ? ld . Back . LowTexture : ld . Back . MiddleTexture ;
2014-12-03 23:15:26 +00:00
}
else if ( ld . Front ! = null )
{
2013-09-11 09:47:53 +00:00
SectorProperties . CeilingHeight = ld . Front . Sector . CeilHeight ;
SectorProperties . FloorHeight = ld . Front . Sector . FloorHeight ;
SectorProperties . Brightness = ld . Front . Sector . Brightness ;
2012-11-27 23:04:49 +00:00
SectorProperties . HighTexture = ld . Front . HighTexture ! = "-" ? ld . Front . HighTexture : ld . Front . MiddleTexture ;
SectorProperties . LowTexture = ld . Front . LowTexture ! = "-" ? ld . Front . LowTexture : ld . Front . MiddleTexture ;
2014-12-03 23:15:26 +00:00
}
else
{
2013-09-11 09:47:53 +00:00
SectorProperties . CeilingHeight = 128 ;
SectorProperties . FloorHeight = 0 ;
SectorProperties . Brightness = 192 ;
SectorProperties . HighTexture = "-" ;
SectorProperties . LowTexture = "-" ;
}
}
2014-12-03 23:15:26 +00:00
public Line ( Vector2D start , Vector2D end )
{
2013-09-11 09:47:53 +00:00
this . start = start ;
this . end = end ;
}
2014-12-03 23:15:26 +00:00
public void Invert ( )
{
2013-09-11 09:47:53 +00:00
Vector2D s = start ;
start = end ;
end = s ;
}
}
2013-09-13 14:54:43 +00:00
#endregion
2012-06-19 13:12:28 +00:00
}