ZoneBuilder/Source/Core/Editing/ClassicMode.cs
MaxED 47aeedc6e0 Changed, Classic modes: displayed mouse map position coordinates are now snapped to current grid size.
Updated model pitch handling to match current GZDoom implementation.
Fixed imprecise vertex coordinates generated by Draw Ellipse mode.
Fixed a resource loading exception when opened map file wad was located in the root of a Directory resource.
Internal: changed output of all InterpolationTools methods from int to float.
Fixed, Internal: InterpolationTools.InterpolateColor() delta usage was inverted.
2023-01-04 23:43:14 +01:00

982 lines
26 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.Drawing;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Actions;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.Windows;
#endregion
namespace CodeImp.DoomBuilder.Editing
{
/// <summary>
/// Provides specialized functionality for a classic (2D) Doom Builder editing mode.
/// </summary>
public abstract class ClassicMode : EditMode
{
#region ================== Constants
private const float SCALE_MAX = 90f;
private const float SCALE_MIN = 0.01f;
private const float SELECTION_BORDER_SIZE = 2f;
private const int SELECTION_ALPHA = 200;
private const float CENTER_VIEW_PADDING = 0.06f;
private const float AUTOPAN_BORDER_SIZE = 100.0f;
#endregion
#region ================== Variables
// Cancelled?
protected bool cancelled;
// Graphics
protected IRenderer2D renderer;
private Renderer2D renderer2d;
// Mouse status
protected Vector2D mousepos;
protected Vector2D mouselastpos;
protected Vector2D mousemappos;
protected Vector2D mousedownpos;
protected Vector2D mousedownmappos;
protected MouseButtons mousebuttons;
protected bool mouseinside;
protected MouseButtons mousedragging = MouseButtons.None;
// Selection
protected bool selecting;
protected bool selectpressed; //mxd
protected Vector2D selectstart;
protected RectangleF selectionrect;
protected MarqueSelectionMode marqueSelectionMode; //mxd
// View panning
protected bool panning;
private bool autopanenabled;
//mxd. used in "Play From Here" Action
private Thing playerStart;
private Vector3D playerStartPosition;
#endregion
#region ================== Properties
// Mouse status
public Vector2D MousePos { get { return mousepos; } }
public Vector2D MouseLastPos { get { return mouselastpos; } }
public Vector2D MouseMapPos { get { return mousemappos; } }
public Vector2D MouseDownPos { get { return mousedownpos; } }
public Vector2D MouseDownMapPos { get { return mousedownmappos; } }
public MouseButtons MouseButtons { get { return mousebuttons; } }
public bool IsMouseInside { get { return mouseinside; } }
public MouseButtons MouseDragging { get { return mousedragging; } }
// Selection
public bool IsSelecting { get { return selecting; } }
public Vector2D SelectionStart { get { return selectstart; } }
public RectangleF SelectionRect { get { return selectionrect; } }
// Panning
public bool IsPanning { get { return panning; } }
// Rendering
public IRenderer2D Renderer { get { return renderer; } }
#endregion
#region ================== Constructor / Disposer
/// <summary>
/// Provides specialized functionality for a classic (2D) Doom Builder editing mode.
/// </summary>
protected ClassicMode()
{
// Initialize
this.renderer = General.Map.Renderer2D;
this.renderer2d = (Renderer2D)General.Map.Renderer2D;
// If the current mode is a ClassicMode, copy mouse properties
ClassicMode oldmode = General.Editing.Mode as ClassicMode;
if(oldmode != null)
{
// Copy mouse properties
mousepos = oldmode.mousepos;
mousemappos = oldmode.mousemappos;
mousedownpos = oldmode.mousedownpos;
mousedownmappos = oldmode.mousedownmappos;
mousebuttons = oldmode.mousebuttons;
mouseinside = oldmode.mouseinside;
mousedragging = oldmode.mousedragging;
}
}
// Disposer
public override void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
// Clean up
// Dispose base
base.Dispose();
}
}
#endregion
#region ================== Scroll / Zoom
// This scrolls the view north
[BeginAction("scrollnorth", BaseAction = true)]
public virtual void ScrollNorth()
{
// Scroll
ScrollBy(0f, 100f / renderer2d.Scale);
}
// This scrolls the view south
[BeginAction("scrollsouth", BaseAction = true)]
public virtual void ScrollSouth()
{
// Scroll
ScrollBy(0f, -100f / renderer2d.Scale);
}
// This scrolls the view west
[BeginAction("scrollwest", BaseAction = true)]
public virtual void ScrollWest()
{
// Scroll
ScrollBy(-100f / renderer2d.Scale, 0f);
}
// This scrolls the view east
[BeginAction("scrolleast", BaseAction = true)]
public virtual void ScrollEast()
{
// Scroll
ScrollBy(100f / renderer2d.Scale, 0f);
}
// This zooms in
[BeginAction("zoomin", BaseAction = true)]
public virtual void ZoomIn()
{
float z = 1.0f + General.Settings.ZoomFactor * 0.1f;
// Zoom
ZoomBy(z);
}
// This zooms out
[BeginAction("zoomout", BaseAction = true)]
public virtual void ZoomOut()
{
float z = 1.0f + General.Settings.ZoomFactor * 0.1f;
// Zoom
ZoomBy(1.0f / z);
}
// This scrolls anywhere
private void ScrollBy(float deltax, float deltay)
{
// Scroll now
renderer2d.PositionView(renderer2d.OffsetX + deltax, renderer2d.OffsetY + deltay);
this.OnViewChanged();
// Redraw
General.MainWindow.RedrawDisplay();
// Determine new unprojected mouse coordinates
mousemappos = renderer2d.DisplayToMap(mousepos);
General.MainWindow.UpdateCoordinates(mousemappos, true);
}
// This sets the view to be centered at x,y
/*private void ScrollTo(float x, float y)
{
// Scroll now
renderer2d.PositionView(x, y);
this.OnViewChanged();
// Redraw
General.MainWindow.RedrawDisplay();
// Determine new unprojected mouse coordinates
mousemappos = renderer2d.DisplayToMap(mousepos);
General.MainWindow.UpdateCoordinates(mousemappos);
}*/
// This zooms
private void ZoomBy(float deltaz)
{
Vector2D zoompos;
// This will be the new zoom scale
float newscale = renderer2d.Scale * deltaz;
// Limit scale
if(newscale > SCALE_MAX) newscale = SCALE_MAX;
if(newscale < SCALE_MIN) newscale = SCALE_MIN;
// Get the dimensions of the display
Vector2D clientsize = new Vector2D(General.Map.Graphics.RenderTarget.ClientSize.Width,
General.Map.Graphics.RenderTarget.ClientSize.Height);
// When mouse is inside display
if(mouseinside)
{
// Zoom into or from mouse position
zoompos = (mousepos / clientsize) - new Vector2D(0.5f, 0.5f);
}
else
{
// Zoom into or from center
zoompos = new Vector2D(0f, 0f);
}
// Calculate view position difference
Vector2D diff = ((clientsize / newscale) - (clientsize / renderer2d.Scale)) * zoompos;
// Zoom now
renderer2d.PositionView(renderer2d.OffsetX - diff.x, renderer2d.OffsetY + diff.y);
renderer2d.ScaleView(newscale);
this.OnViewChanged();
//mxd. Change grid size?
MatchGridSizeToDisplayScale();
// Redraw
General.MainWindow.RedrawDisplay();
// Give a new mousemove event to update coordinates
if(mouseinside) OnMouseMove(new MouseEventArgs(mousebuttons, 0, (int)mousepos.x, (int)mousepos.y, 0));
}
//mxd. This changes current grid size based on current zoom level
internal void MatchGridSizeToDisplayScale()
{
if(!General.Settings.DynamicGridSize) return;
// Get the dimensions of the display
Vector2D clientsize = new Vector2D(General.Map.Graphics.RenderTarget.ClientSize.Width,
General.Map.Graphics.RenderTarget.ClientSize.Height);
Vector2D clientscale = clientsize / renderer2d.Scale;
int targetsize = (int)Math.Ceiling(Math.Min(clientscale.x, clientscale.y) / 32);
// Convert to nearest power of 2
targetsize--;
targetsize |= targetsize >> 1;
targetsize |= targetsize >> 2;
targetsize |= targetsize >> 4;
targetsize |= targetsize >> 8;
targetsize |= targetsize >> 16;
targetsize++;
// Apply changes
General.Map.Grid.SetGridSize(targetsize);
}
// This zooms to a specific level
public void SetZoom(float newscale)
{
// Zoom now
renderer2d.ScaleView(newscale);
this.OnViewChanged();
//mxd. Change grid size?
MatchGridSizeToDisplayScale();
// Redraw
//General.Map.Map.Update();
General.MainWindow.RedrawDisplay();
// Give a new mousemove event to update coordinates
if(mouseinside) OnMouseMove(new MouseEventArgs(mousebuttons, 0, (int)mousepos.x, (int)mousepos.y, 0));
}
// This zooms and scrolls to fit the map in the window
[BeginAction("centerinscreen", BaseAction = true)]
public void CenterInScreen()
{
float left = float.MaxValue;
float top = float.MaxValue;
float right = float.MinValue;
float bottom = float.MinValue;
bool anything = false;
// Go for all vertices
foreach(Vertex v in General.Map.Map.Vertices)
{
// Vertex used?
if(v.Linedefs.Count > 0)
{
// Adjust boundaries by vertices
if(v.Position.x < left) left = v.Position.x;
if(v.Position.x > right) right = v.Position.x;
if(v.Position.y < top) top = v.Position.y;
if(v.Position.y > bottom) bottom = v.Position.y;
anything = true;
}
}
// Not already found something to center in view?
if(!anything)
{
// Go for all things
foreach(Thing t in General.Map.Map.Things)
{
// Adjust boundaries by vertices
if(t.Position.x < left) left = t.Position.x;
if(t.Position.x > right) right = t.Position.x;
if(t.Position.y < top) top = t.Position.y;
if(t.Position.y > bottom) bottom = t.Position.y;
anything = true;
}
}
// Anything found to center in view?
if(anything)
{
RectangleF area = new RectangleF(left, top, (right - left), (bottom - top));
CenterOnArea(area, CENTER_VIEW_PADDING);
}
else
{
// Default view
SetDefaultZoom();
}
}
// This zooms and moves to view the given area
public void CenterOnArea(RectangleF area, float padding)
{
// Add size to the area for better overview
area.Inflate(area.Width * padding, area.Height * padding);
// Calculate scale to view map at
float scalew = General.Map.Graphics.RenderTarget.ClientSize.Width / area.Width;
float scaleh = General.Map.Graphics.RenderTarget.ClientSize.Height / area.Height;
float scale = scalew < scaleh ? scalew : scaleh;
//mxd. Change the view to see the whole map
CenterOnCoordinates(new Vector2D(area.Left + area.Width * 0.5f, area.Top + area.Height * 0.5f), scale);
}
//mxd
public void CenterOnCoordinates(Vector2D offset, float scale)
{
// Change the view
renderer2d.ScaleView(scale);
renderer2d.PositionView(offset.x, offset.y);
this.OnViewChanged();
//mxd. Change grid size?
MatchGridSizeToDisplayScale();
// Redraw
General.MainWindow.RedrawDisplay();
// Give a new mousemove event to update coordinates
if(mouseinside) OnMouseMove(new MouseEventArgs(mousebuttons, 0, (int)mousepos.x, (int)mousepos.y, 0));
}
// This sets up the default view
public void SetDefaultZoom()
{
// View middle of map at 50% zoom
renderer2d.ScaleView(0.5f);
renderer2d.PositionView(0.0f, 0.0f);
this.OnViewChanged();
//mxd. Change grid size?
MatchGridSizeToDisplayScale();
// Redraw
General.MainWindow.RedrawDisplay();
// Give a new mousemove event to update coordinates
if(mouseinside) OnMouseMove(new MouseEventArgs(mousebuttons, 0, (int)mousepos.x, (int)mousepos.y, 0));
}
/// <summary>
/// This is called when the view changes (scroll/zoom), before the display is redrawn.
/// </summary>
protected virtual void OnViewChanged()
{
}
// This enabled automatic panning, if preferred
protected void EnableAutoPanning()
{
if(General.Settings.AutoScrollSpeed > 0)
{
if(!autopanenabled)
{
autopanenabled = true;
General.MainWindow.EnableProcessing();
}
}
}
// This disabls automatic panning
protected void DisableAutoPanning()
{
if(autopanenabled)
{
autopanenabled = false;
General.MainWindow.DisableProcessing();
}
}
#endregion
#region ================== Processing
// Processing
public override void OnProcess(long deltatime)
{
base.OnProcess(deltatime);
if(autopanenabled)
{
Vector2D panamount = new Vector2D();
// How much to pan the view in X?
if(mousepos.x < AUTOPAN_BORDER_SIZE)
panamount.x = -AUTOPAN_BORDER_SIZE + mousepos.x;
else if(mousepos.x > (General.MainWindow.Display.ClientSize.Width - AUTOPAN_BORDER_SIZE))
panamount.x = mousepos.x - (General.MainWindow.Display.ClientSize.Width - AUTOPAN_BORDER_SIZE);
// How much to pan the view in Y?
if(mousepos.y < AUTOPAN_BORDER_SIZE)
panamount.y = AUTOPAN_BORDER_SIZE - mousepos.y;
else if(mousepos.y > (General.MainWindow.Display.ClientSize.Height - AUTOPAN_BORDER_SIZE))
panamount.y = -(mousepos.y - (General.MainWindow.Display.ClientSize.Height - AUTOPAN_BORDER_SIZE));
// Do any panning?
if(panamount.GetManhattanLength() > 0.0f)
{
// Scale and power this for nicer usability
Vector2D pansign = panamount.GetSign();
panamount = (panamount * panamount) * pansign * 0.0001f * General.Settings.AutoScrollSpeed / renderer.Scale;
// Multiply by delta time
panamount.x *= deltatime;
panamount.y *= deltatime;
// Pan the view
ScrollBy(panamount.x, panamount.y);
}
}
}
#endregion
#region ================== Input
// Mouse leaves the display
public override void OnMouseLeave(EventArgs e)
{
// Mouse is outside the display
mouseinside = false;
mousepos = new Vector2D(float.NaN, float.NaN);
mousemappos = mousepos;
mousebuttons = MouseButtons.None;
// Determine new unprojected mouse coordinates
General.MainWindow.UpdateCoordinates(mousemappos, true);
// Let the base class know
base.OnMouseLeave(e);
}
// Mouse moved inside the display
public override void OnMouseMove(MouseEventArgs e)
{
// Record last position
mouseinside = true;
mouselastpos = mousepos;
mousepos = new Vector2D(e.X, e.Y);
mousemappos = renderer2d.DisplayToMap(mousepos);
mousebuttons = e.Button;
// Update labels in main window
General.MainWindow.UpdateCoordinates(mousemappos, true);
// Holding a button?
if(e.Button != MouseButtons.None)
{
// Not dragging?
if(mousedragging == MouseButtons.None)
{
// Check if moved enough pixels for dragging
Vector2D delta = mousedownpos - mousepos;
if((Math.Abs(delta.x) > DRAG_START_MOVE_PIXELS) ||
(Math.Abs(delta.y) > DRAG_START_MOVE_PIXELS))
{
// Dragging starts now
mousedragging = e.Button;
OnDragStart(e);
}
}
}
// Selecting?
if(selecting) OnUpdateMultiSelection();
// Panning?
if(panning) OnUpdateViewPanning();
// Let the base class know
base.OnMouseMove(e);
}
// Mouse button pressed
public override void OnMouseDown(MouseEventArgs e)
{
// Save mouse down position
mousedownpos = mousepos;
mousedownmappos = mousemappos;
//mxd. Looks like in some cases (very detailed maps / slow CPUs) OnMouseUp is not fired
// This is my attempt at fixing this...
if(e.Button == mousedragging) mousedragging = MouseButtons.None;
// Let the base class know
base.OnMouseDown(e);
}
// Mouse button released
public override void OnMouseUp(MouseEventArgs e)
{
// Releasing drag button?
if(e.Button == mousedragging)
{
// No longer dragging
OnDragStop(e);
mousedragging = MouseButtons.None;
}
// Let the base class know
base.OnMouseUp(e);
}
//mxd
public override void OnKeyDown(KeyEventArgs e)
{
// Update marque color when modifier keys are pressed
if(selecting && (e.Control || e.Shift) && marqueSelectionMode != GetMultiSelectionMode())
OnUpdateMultiSelection();
base.OnKeyDown(e);
}
//mxd
public override void OnKeyUp(KeyEventArgs e)
{
// Update marque color when modifier keys are released
if(selecting && (!e.Control || !e.Shift) && marqueSelectionMode != GetMultiSelectionMode())
OnUpdateMultiSelection();
base.OnKeyUp(e);
}
/// <summary>
/// Automatically called when dragging operation starts.
/// </summary>
protected virtual void OnDragStart(MouseEventArgs e)
{
}
/// <summary>
/// Automatically called when dragging operation stops.
/// </summary>
protected virtual void OnDragStop(MouseEventArgs e)
{
}
#endregion
#region ================== Display
// This just refreshes the display
public override void OnPresentDisplay()
{
renderer2d.Present();
}
// This sets the view mode
internal static void SetViewMode(ViewMode mode)
{
General.Map.CRenderer2D.SetViewMode(mode);
General.MainWindow.UpdateInterface();
General.MainWindow.RedrawDisplay();
}
#endregion
#region ================== Methods
/// <summary>
/// Automatically called by the core when this editing mode is engaged.
/// </summary>
public override void OnEngage()
{
//mxd. Clear display overlay
if(renderer.StartOverlay(true))
{
//mxd. Center 2d view on camera position in 3d view
if(General.Settings.GZSynchCameras && !General.Interface.CtrlState
&& General.Editing.PreviousMode != null && General.Editing.PreviousMode.IsSubclassOf(typeof(VisualMode)))
{
Vector2D campos = new Vector2D(General.Map.VisualCamera.Position.x, General.Map.VisualCamera.Position.y);
renderer2d.PositionView(campos.x, campos.y);
}
renderer.Finish();
}
base.OnEngage();
}
/// <summary>
/// Called when the user requests to cancel this editing mode.
/// </summary>
public override void OnCancel()
{
cancelled = true;
base.OnCancel();
}
//mxd
public override bool OnMapTestBegin(bool testFromCurrentPosition)
{
if(testFromCurrentPosition)
{
if(!mouseinside)
{
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't test from current position: mouse is outside editing vindow!");
return false;
}
//find Single Player Start. Should be type 1 in all games
Thing start = null;
foreach(Thing t in General.Map.Map.Things)
{
if(t.SRB2Type == 1)
{
//store thing and position
if(start == null)
{
start = t;
}
else if(t.Index > start.Index)
{
//if there are several Player Start 1 things, GZDoom uses one with the biggest index.
start = t;
}
}
}
if(start == null)
{
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't test from current position: no Player 1 start found!");
return false;
}
//now check if cursor is located inside a sector
Sector s = General.Map.Map.GetSectorByCoordinates(mousemappos);
if(s == null)
{
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't test from current position: cursor is not inside sector!");
return false;
}
//41 = player's height in Doom. Is that so in all other games as well?
if(s.CeilHeight - s.FloorHeight < 41)
{
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't test from current position: sector is too low!");
return false;
}
//store initial position
playerStart = start;
playerStartPosition = start.Position;
//everything should be valid, let's move player start here
start.Move(new Vector3D(mousemappos.x, mousemappos.y, 0));
}
return true;
}
public override void OnMapTestEnd(bool testFromCurrentPosition)
{
if(testFromCurrentPosition)
{
//restore position
playerStart.Move(playerStartPosition);
playerStart = null;
}
}
/// <summary>
/// This is called automatically when the Edit button is pressed.
/// (in Doom Builder 1, this was always the right mousebutton)
/// </summary>
[BeginAction("classicedit", BaseAction = true)]
protected virtual void OnEditBegin()
{
}
/// <summary>
/// This is called automatically when the Edit button is released.
/// (in Doom Builder 1, this was always the right mousebutton)
/// </summary>
[EndAction("classicedit", BaseAction = true)]
protected virtual void OnEditEnd()
{
}
/// <summary>
/// This is called automatically when the Select button is pressed.
/// (in Doom Builder 1, this was always the left mousebutton)
/// </summary>
[BeginAction("classicselect", BaseAction = true)]
protected virtual void OnSelectBegin()
{
selectpressed = true;//mxd
}
/// <summary>
/// This is called automatically when the Select button is released.
/// (in Doom Builder 1, this was always the left mousebutton)
/// </summary>
[EndAction("classicselect", BaseAction = true)]
protected virtual void OnSelectEnd()
{
selectpressed = false;//mxd
if(selecting) OnEndMultiSelection();
}
/// <summary>
/// This is called automatically when a rectangular multi-selection ends.
/// </summary>
protected virtual void OnEndMultiSelection()
{
selecting = false;
General.Hints.ShowHints(this.GetType(), HintsManager.GENERAL);
}
/// <summary>
/// Call this to initiate a rectangular multi-selection.
/// </summary>
protected virtual void StartMultiSelection()
{
selecting = true;
selectstart = mousemappos;
selectionrect = new RectangleF(selectstart.x, selectstart.y, 0, 0);
//mxd
General.Hints.ShowHints(this.GetType(), HintsManager.MULTISELECTION);
}
/// <summary>
/// This is called automatically when a multi-selection is updated.
/// </summary>
protected virtual void OnUpdateMultiSelection()
{
marqueSelectionMode = GetMultiSelectionMode(); //mxd
selectionrect.X = selectstart.x;
selectionrect.Y = selectstart.y;
selectionrect.Width = mousemappos.x - selectstart.x;
selectionrect.Height = mousemappos.y - selectstart.y;
if(selectionrect.Width < 0f)
{
selectionrect.Width = -selectionrect.Width;
selectionrect.X -= selectionrect.Width;
}
if(selectionrect.Height < 0f)
{
selectionrect.Height = -selectionrect.Height;
selectionrect.Y -= selectionrect.Height;
}
}
//mxd
protected virtual MarqueSelectionMode GetMultiSelectionMode()
{
return MarqueSelectionMode.SELECT;
}
/// <summary>
/// Call this to draw the selection on the overlay layer.
/// Must call renderer.StartOverlay first!
/// </summary>
protected virtual void RenderMultiSelection()
{
//mxd
PixelColor marqueColor;
switch(marqueSelectionMode)
{
case MarqueSelectionMode.SELECT:
marqueColor = General.Colors.Selection.WithAlpha(SELECTION_ALPHA);
break;
case MarqueSelectionMode.ADD:
marqueColor = General.Colors.Highlight.WithAlpha(SELECTION_ALPHA);
break;
case MarqueSelectionMode.SUBTRACT:
marqueColor = General.Colors.Selection.WithAlpha(SELECTION_ALPHA).InverseKeepAlpha();
break;
default: //should be Intersect
marqueColor = General.Colors.Highlight.WithAlpha(SELECTION_ALPHA).InverseKeepAlpha();
break;
}
renderer.RenderRectangle(selectionrect, SELECTION_BORDER_SIZE, marqueColor, true);
}
/// <summary>
/// This is called automatically when the mouse is moved while panning
/// </summary>
protected virtual void OnUpdateViewPanning()
{
// We can only drag the map when the mouse pointer is inside
// otherwise we don't have coordinates where to drag the map to
if(mouseinside && !float.IsNaN(mouselastpos.x) && !float.IsNaN(mouselastpos.y))
{
// Get the map coordinates of the last mouse posision (before it moved)
Vector2D lastmappos = renderer2d.DisplayToMap(mouselastpos);
// Do the scroll
ScrollBy(lastmappos.x - mousemappos.x, lastmappos.y - mousemappos.y);
}
}
/// <summary>
/// This selects given map element (mxd)
/// </summary>
public virtual void SelectMapElement(SelectableElement element)
{
element.Selected = true;
}
#endregion
#region ================== Actions
[BeginAction("gridsetup", BaseAction = true)]
protected void ShowGridSetup()
{
GridSetup.ShowGridSetup();
}
[BeginAction("pan_view", BaseAction = true)]
protected virtual void BeginViewPan()
{
panning = true;
}
[EndAction("pan_view", BaseAction = true)]
protected virtual void EndViewPan()
{
panning = false;
}
[BeginAction("viewmodenormal", BaseAction = true)]
protected virtual void ViewModeNormal()
{
SetViewMode(ViewMode.Normal);
}
[BeginAction("viewmodebrightness", BaseAction = true)]
protected virtual void ViewModeBrightness()
{
SetViewMode(ViewMode.Brightness);
}
[BeginAction("viewmodefloors", BaseAction = true)]
protected virtual void ViewModeFloors()
{
SetViewMode(ViewMode.FloorTextures);
}
[BeginAction("viewmodeceilings", BaseAction = true)]
protected virtual void ViewModeCeilings()
{
SetViewMode(ViewMode.CeilingTextures);
}
//mxd
[BeginAction("centeroncoordinates", BaseAction = true)]
protected virtual void CenterOnCoordinates()
{
//show form...
CenterOnCoordinatesForm form = new CenterOnCoordinatesForm();
if(form.ShowDialog() == DialogResult.OK)
{
//center view
renderer2d.PositionView(form.Coordinates.x, form.Coordinates.y);
General.Interface.RedrawDisplay();
}
}
//mxd
[BeginAction("togglehighlight", BaseAction = true)]
protected virtual void ToggleHighlight()
{
General.Settings.UseHighlight = !General.Settings.UseHighlight;
General.Interface.DisplayStatus(StatusType.Action, "Highlight is now " + (General.Settings.UseHighlight ? "ON" : "OFF") + ".");
// Redraw display to show changes
General.Interface.RedrawDisplay();
}
#endregion
}
//mxd
public enum MarqueSelectionMode
{
SELECT,
ADD,
SUBTRACT,
INTERSECT,
}
}