mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-27 06:02:11 +00:00
ea57d45eb3
Probably fixed probable I/O race condition when loading images. Fixed Visual mode stuttering due to floating point precision degradation when running the editor for several days without restarting (internal timer is now reset when saving the map or creating a new one). Fixed, Nodes Viewer, cosmetic: Nodes Viewer window position was reset after pressing the "Rebuild Nodes" button. Added Eternity Game configurations by printz. Updated ZDoom_ACS.cfg (CheckClass). Updated ZDoom ACC (CheckClass).
534 lines
13 KiB
C#
534 lines
13 KiB
C#
|
|
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
|
|
|
/*
|
|
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
|
* This program is released under GNU General Public License
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#endregion
|
|
|
|
#region ================== Namespaces
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Windows.Forms;
|
|
using CodeImp.DoomBuilder.Map;
|
|
using CodeImp.DoomBuilder.Rendering;
|
|
using CodeImp.DoomBuilder.Geometry;
|
|
using CodeImp.DoomBuilder.Editing;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.BuilderModes
|
|
{
|
|
[EditMode(DisplayName = "Make Sectors Mode",
|
|
SwitchAction = "makesectormode",
|
|
ButtonImage = "NewSector2.png", // Image resource name for the button
|
|
ButtonOrder = int.MinValue + 302, // Position of the button (lower is more to the left)
|
|
ButtonGroup = "000_editing",
|
|
UseByDefault = true)]
|
|
|
|
public class MakeSectorMode : BaseClassicMode
|
|
{
|
|
#region ================== Constants
|
|
|
|
private const float FLASH_DURATION = 300.0f;
|
|
|
|
#endregion
|
|
|
|
#region ================== Variables
|
|
|
|
// Nearest sidedef
|
|
private LinedefSide editside;
|
|
private LinedefSide nearestside;
|
|
private List<LinedefSide> allsides;
|
|
private List<Linedef> alllines;
|
|
|
|
// Flash polygon
|
|
private FlatVertex[] flashpolygon;
|
|
private float flashintensity;
|
|
private long flashstarttime;
|
|
|
|
// Interface
|
|
protected bool editpressed;
|
|
|
|
//mxd. Used in overlay rendering
|
|
private Dictionary<Sector, Sector> associates;
|
|
|
|
#endregion
|
|
|
|
#region ================== Properties
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructor / Disposer
|
|
|
|
// Constructor
|
|
public MakeSectorMode()
|
|
{
|
|
}
|
|
|
|
// Disposer
|
|
public override void Dispose()
|
|
{
|
|
// Not already disposed?
|
|
if(!isdisposed)
|
|
{
|
|
// Clean up
|
|
nearestside = null;
|
|
allsides = null;
|
|
|
|
// Dispose base
|
|
base.Dispose();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Methods
|
|
|
|
// This draws the geometry
|
|
private void DrawGeometry()
|
|
{
|
|
associates = new Dictionary<Sector, Sector>();
|
|
|
|
// Render lines and vertices
|
|
if(renderer.StartPlotter(true))
|
|
{
|
|
renderer.PlotLinedefSet(General.Map.Map.Linedefs);
|
|
|
|
// Render sector indication
|
|
if(allsides != null)
|
|
{
|
|
foreach(LinedefSide sd in allsides)
|
|
{
|
|
if(sd.Front)
|
|
{
|
|
if(sd.Line.Front != null)
|
|
{
|
|
if(!associates.ContainsKey(sd.Line.Front.Sector))
|
|
{
|
|
renderer.PlotSector(sd.Line.Front.Sector, General.Colors.Indication);
|
|
associates[sd.Line.Front.Sector] = sd.Line.Front.Sector;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(sd.Line.Back != null)
|
|
{
|
|
if(!associates.ContainsKey(sd.Line.Back.Sector))
|
|
{
|
|
renderer.PlotSector(sd.Line.Back.Sector, General.Colors.Indication);
|
|
associates[sd.Line.Back.Sector] = sd.Line.Back.Sector;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Render highlight
|
|
if(alllines != null)
|
|
{
|
|
foreach(Linedef l in alllines) renderer.PlotLinedef(l, General.Colors.Highlight);
|
|
}
|
|
|
|
renderer.PlotVerticesSet(General.Map.Map.Vertices);
|
|
renderer.Finish();
|
|
}
|
|
}
|
|
|
|
// This draws the overlay
|
|
private void DrawOverlay()
|
|
{
|
|
// Redraw overlay
|
|
if(renderer.StartOverlay(true))
|
|
{
|
|
if((flashpolygon != null) && (flashintensity > 0.0f))
|
|
{
|
|
renderer.RenderGeometry(flashpolygon, null, true);
|
|
}
|
|
else if(General.Settings.UseHighlight) //mxd
|
|
{
|
|
int color = General.Colors.Indication.WithAlpha(64).ToInt();
|
|
foreach(Sector s in associates.Keys)
|
|
{
|
|
renderer.RenderHighlight(s.FlatVertices, color);
|
|
}
|
|
}
|
|
|
|
renderer.Finish();
|
|
}
|
|
}
|
|
|
|
// This highlights a new region
|
|
private void Highlight(bool buttonspressed)
|
|
{
|
|
// Mouse inside?
|
|
if(mouseinside)
|
|
{
|
|
// Highlighting from a new sidedef?
|
|
Linedef nl = General.Map.Map.NearestLinedef(mousemappos);
|
|
if(nl != null)
|
|
{
|
|
float side = nl.SideOfLine(mousemappos);
|
|
LinedefSide newnearest = new LinedefSide(nl, (side <= 0.0f));
|
|
if(newnearest != nearestside)
|
|
{
|
|
// Only change when buttons are not pressed
|
|
if(!buttonspressed || (editside == newnearest))
|
|
{
|
|
// Find new sector
|
|
General.Interface.SetCursor(Cursors.AppStarting);
|
|
nearestside = newnearest;
|
|
allsides = Tools.FindPotentialSectorAt(mousemappos);
|
|
if(allsides != null)
|
|
{
|
|
alllines = new List<Linedef>(allsides.Count);
|
|
foreach(LinedefSide sd in allsides) alllines.Add(sd.Line);
|
|
}
|
|
else
|
|
{
|
|
alllines = null;
|
|
}
|
|
General.Interface.SetCursor(Cursors.Default);
|
|
}
|
|
else
|
|
{
|
|
// Don't highlight this one
|
|
nearestside = null;
|
|
allsides = null;
|
|
alllines = null;
|
|
}
|
|
|
|
// Redraw overlay
|
|
DrawGeometry();
|
|
DrawOverlay(); //mxd
|
|
renderer.Present();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No valid region
|
|
nearestside = null;
|
|
allsides = null;
|
|
alllines = null;
|
|
|
|
// Redraw overlay
|
|
DrawGeometry();
|
|
renderer.Present();
|
|
}
|
|
}
|
|
|
|
// This makes this highlighted potential sector
|
|
private Sector MakeSector()
|
|
{
|
|
General.Interface.SetCursor(Cursors.WaitCursor);
|
|
General.Settings.FindDefaultDrawSettings();
|
|
General.Map.UndoRedo.CreateUndo("Make Sector");
|
|
|
|
// Mark the lines we are going to use for this sector
|
|
General.Map.Map.ClearAllMarks(true);
|
|
foreach(LinedefSide ls in allsides) ls.Line.Marked = false;
|
|
List<Linedef> oldlines = General.Map.Map.GetMarkedLinedefs(true);
|
|
|
|
// Make the sector
|
|
Sector s = Tools.MakeSector(allsides, oldlines, false);
|
|
if(s != null)
|
|
{
|
|
// Now we go for all the lines along the sector to
|
|
// see if they only have a back side. In that case we want
|
|
// to flip the linedef to that it only has a front side.
|
|
foreach(Sidedef sd in s.Sidedefs)
|
|
{
|
|
if((sd.Line.Front == null) && (sd.Line.Back != null))
|
|
{
|
|
// Flip linedef
|
|
sd.Line.FlipVertices();
|
|
sd.Line.FlipSidedefs();
|
|
}
|
|
}
|
|
|
|
General.Map.Data.UpdateUsedTextures();
|
|
General.Interface.SetCursor(Cursors.Default);
|
|
return s;
|
|
}
|
|
else
|
|
{
|
|
General.Map.UndoRedo.WithdrawUndo();
|
|
return null;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Events
|
|
|
|
public override void OnHelp()
|
|
{
|
|
General.ShowHelp("e_makesectors.html");
|
|
}
|
|
|
|
// When the mapset changes (undo/redo)
|
|
public override void OnMapSetChangeBegin()
|
|
{
|
|
// No valid region
|
|
nearestside = null;
|
|
allsides = null;
|
|
alllines = null;
|
|
|
|
base.OnMapSetChangeBegin();
|
|
}
|
|
|
|
// Cancel mode
|
|
public override void OnCancel()
|
|
{
|
|
base.OnCancel();
|
|
|
|
// Return to base mode
|
|
General.Editing.ChangeMode(new SectorsMode());
|
|
}
|
|
|
|
// Mode engages
|
|
public override void OnEngage()
|
|
{
|
|
base.OnEngage();
|
|
|
|
// Make customized presentation
|
|
CustomPresentation p = new CustomPresentation();
|
|
p.AddLayer(new PresentLayer(RendererLayer.Background, BlendingMode.Mask, General.Settings.BackgroundAlpha));
|
|
p.AddLayer(new PresentLayer(RendererLayer.Surface, BlendingMode.Mask));
|
|
p.AddLayer(new PresentLayer(RendererLayer.Grid, BlendingMode.Mask));
|
|
p.AddLayer(new PresentLayer(RendererLayer.Overlay, BlendingMode.Alpha, 1f, true));
|
|
p.AddLayer(new PresentLayer(RendererLayer.Things, BlendingMode.Alpha, General.Settings.InactiveThingsAlpha, false));
|
|
p.AddLayer(new PresentLayer(RendererLayer.Geometry, BlendingMode.Alpha, 1f, true));
|
|
renderer.SetPresentation(p);
|
|
General.Map.Map.SelectionType = SelectionType.All;
|
|
}
|
|
|
|
// Mode disengages
|
|
public override void OnDisengage()
|
|
{
|
|
base.OnDisengage();
|
|
|
|
// Check which mode we are switching to
|
|
if(General.Editing.NewMode is VerticesMode || General.Editing.NewMode is LinedefsMode)
|
|
{
|
|
// Clear selected sectors
|
|
General.Map.Map.ClearSelectedSectors();
|
|
}
|
|
|
|
// Hide highlight info
|
|
General.Interface.HideInfo();
|
|
|
|
// Stop processing
|
|
General.Interface.DisableProcessing();
|
|
}
|
|
|
|
// This redraws the display
|
|
public override void OnRedrawDisplay()
|
|
{
|
|
renderer.RedrawSurface();
|
|
|
|
// Render lines and vertices
|
|
DrawGeometry();
|
|
|
|
// Render things
|
|
if(renderer.StartThings(true))
|
|
{
|
|
renderer.RenderThingSet(General.Map.ThingsFilter.HiddenThings, General.Settings.HiddenThingsAlpha);
|
|
renderer.RenderThingSet(General.Map.ThingsFilter.VisibleThings, General.Settings.ActiveThingsAlpha);
|
|
renderer.Finish();
|
|
}
|
|
|
|
// Render overlay
|
|
DrawOverlay();
|
|
renderer.Present();
|
|
}
|
|
|
|
// Start select
|
|
protected override void OnSelectBegin()
|
|
{
|
|
// Select pressed in this mode
|
|
selectpressed = true;
|
|
editside = nearestside;
|
|
base.OnEditBegin();
|
|
}
|
|
|
|
// Done selecting
|
|
protected override void OnSelectEnd()
|
|
{
|
|
// Select was pressed in this mode?
|
|
if(selectpressed && (editside == nearestside) && (nearestside != null))
|
|
{
|
|
// Possible to make a sector?
|
|
if(allsides != null)
|
|
{
|
|
// Make the sector
|
|
Sector s = MakeSector();
|
|
if(s != null)
|
|
{
|
|
// Quickly flash this sector to indicate it was created
|
|
General.Map.IsChanged = true;
|
|
General.Map.Map.Update();
|
|
General.Interface.RedrawDisplay();
|
|
flashpolygon = new FlatVertex[s.FlatVertices.Length];
|
|
s.FlatVertices.CopyTo(flashpolygon, 0);
|
|
flashintensity = 1.0f;
|
|
flashstarttime = Clock.CurrentTime;
|
|
General.Interface.EnableProcessing();
|
|
}
|
|
|
|
// Redraw overlay
|
|
DrawGeometry();
|
|
DrawOverlay();
|
|
renderer.Present();
|
|
}
|
|
}
|
|
|
|
base.OnSelectEnd();
|
|
}
|
|
|
|
// Start editing
|
|
protected override void OnEditBegin()
|
|
{
|
|
// Edit pressed in this mode
|
|
editpressed = true;
|
|
editside = nearestside;
|
|
base.OnEditBegin();
|
|
}
|
|
|
|
// Done editing
|
|
protected override void OnEditEnd()
|
|
{
|
|
// Edit was pressed in this mode?
|
|
if(editpressed && (editside == nearestside) && (nearestside != null))
|
|
{
|
|
// Possible to make a sector?
|
|
if(allsides != null)
|
|
{
|
|
// Make the sector
|
|
Sector s = MakeSector();
|
|
if(s != null)
|
|
{
|
|
General.Map.Map.Update();
|
|
|
|
// Edit the sector
|
|
List<Sector> secs = new List<Sector>(); secs.Add(s);
|
|
if(General.Interface.ShowEditSectors(secs) == DialogResult.OK)
|
|
{
|
|
// Quickly flash this sector to indicate it was created
|
|
General.Map.IsChanged = true;
|
|
General.Map.Map.Update();
|
|
flashpolygon = new FlatVertex[s.FlatVertices.Length];
|
|
s.FlatVertices.CopyTo(flashpolygon, 0);
|
|
flashintensity = 1.0f;
|
|
flashstarttime = Clock.CurrentTime;
|
|
General.Interface.EnableProcessing();
|
|
}
|
|
else
|
|
{
|
|
// Undo
|
|
General.Map.UndoRedo.WithdrawUndo();
|
|
}
|
|
}
|
|
|
|
// Redraw overlay
|
|
DrawGeometry();
|
|
DrawOverlay();
|
|
renderer.Present();
|
|
}
|
|
}
|
|
|
|
editpressed = false;
|
|
base.OnEditEnd();
|
|
}
|
|
|
|
// Mouse moves
|
|
public override void OnMouseMove(MouseEventArgs e)
|
|
{
|
|
base.OnMouseMove(e);
|
|
if(panning) return; //mxd. Skip all this jass while panning
|
|
|
|
// Highlight the region
|
|
Highlight((e.Button != MouseButtons.None));
|
|
}
|
|
|
|
// Mouse leaves
|
|
public override void OnMouseLeave(EventArgs e)
|
|
{
|
|
base.OnMouseLeave(e);
|
|
|
|
// Highlight nothing
|
|
Highlight(false);
|
|
}
|
|
|
|
// Something is undone
|
|
public override void OnUndoEnd()
|
|
{
|
|
base.OnUndoEnd();
|
|
|
|
editside = null;
|
|
nearestside = null;
|
|
if(alllines != null)
|
|
alllines.Clear();
|
|
if(allsides != null)
|
|
allsides.Clear();
|
|
}
|
|
|
|
// Something is redone
|
|
public override void OnRedoEnd()
|
|
{
|
|
base.OnRedoEnd();
|
|
|
|
editside = null;
|
|
nearestside = null;
|
|
if(alllines != null)
|
|
alllines.Clear();
|
|
if(allsides != null)
|
|
allsides.Clear();
|
|
}
|
|
|
|
// Processing
|
|
public override void OnProcess(long deltatime)
|
|
{
|
|
base.OnProcess(deltatime);
|
|
|
|
// Process flash
|
|
if(flashpolygon != null)
|
|
{
|
|
// Determine the intensity of the flash by time elapsed
|
|
flashintensity = 1f - ((Clock.CurrentTime - flashstarttime) / FLASH_DURATION);
|
|
if(flashintensity > 0.0f)
|
|
{
|
|
// Update vertices in polygon
|
|
PixelColor pc = new PixelColor((byte)(flashintensity * 255.0f), 255, 255, 255);
|
|
int intcolor = pc.ToInt();
|
|
for(int i = 0; i < flashpolygon.Length; i++) flashpolygon[i].c = intcolor;
|
|
}
|
|
else
|
|
{
|
|
// End of flash, trash the polygon
|
|
flashpolygon = null;
|
|
flashintensity = 0.0f;
|
|
General.Interface.DisableProcessing();
|
|
}
|
|
|
|
// Redraw overlay
|
|
DrawOverlay();
|
|
renderer.Present();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
|