- changed a lot around the actions

- no more mousebutton-specific code in the editing modes (now all bound by actions)
- some progress on the drawing editing mode
This commit is contained in:
codeimp 2008-04-27 12:07:26 +00:00
parent 175f645e5e
commit 4ae985d630
30 changed files with 1468 additions and 767 deletions

BIN
Resources/Icons/Pencil.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

View file

@ -59,6 +59,8 @@
<Compile Include="Config\UniversalFieldInfo.cs" /> <Compile Include="Config\UniversalFieldInfo.cs" />
<Compile Include="Config\UniversalFieldType.cs" /> <Compile Include="Config\UniversalFieldType.cs" />
<Compile Include="Controls\ActionAttribute.cs" /> <Compile Include="Controls\ActionAttribute.cs" />
<Compile Include="Controls\BeginActionAttribute.cs" />
<Compile Include="Controls\EndActionAttribute.cs" />
<Compile Include="Controls\KeyControl.cs" /> <Compile Include="Controls\KeyControl.cs" />
<Compile Include="Controls\MouseInput.cs" /> <Compile Include="Controls\MouseInput.cs" />
<Compile Include="Data\DirectoryReader.cs" /> <Compile Include="Data\DirectoryReader.cs" />

View file

@ -299,26 +299,21 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
} }
} }
// When edit button is released
protected override void EndEdit()
{
// Just return to base mode, Disengage will be called automatically.
General.Map.ChangeMode(basemode);
base.EndEdit();
}
// Mouse moving // Mouse moving
public override void MouseMove(MouseEventArgs e) public override void MouseMove(MouseEventArgs e)
{ {
base.MouseMove(e); base.MouseMove(e);
Update(); Update();
} }
// Mouse button released
public override void MouseUp(MouseEventArgs e)
{
base.MouseUp(e);
// Is the editing button released?
if(e.Button == EditMode.EDIT_BUTTON)
{
// Just return to vertices mode, geometry will be merged on disengage.
General.Map.ChangeMode(basemode);
}
}
// When a key is released // When a key is released
public override void KeyUp(KeyEventArgs e) public override void KeyUp(KeyEventArgs e)
{ {

View file

@ -334,6 +334,15 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
} }
} }
// When edit button is released
protected override void EndEdit()
{
// Just return to vertices mode, geometry will be merged on disengage.
General.Map.ChangeMode(basemode);
base.EndEdit();
}
// Mouse moving // Mouse moving
public override void MouseMove(MouseEventArgs e) public override void MouseMove(MouseEventArgs e)
{ {
@ -341,19 +350,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
Update(); Update();
} }
// Mouse button released
public override void MouseUp(MouseEventArgs e)
{
base.MouseUp(e);
// Is the editing button released?
if(e.Button == EditMode.EDIT_BUTTON)
{
// Just return to vertices mode, geometry will be merged on disengage.
General.Map.ChangeMode(basemode);
}
}
// When a key is released // When a key is released
public override void KeyUp(KeyEventArgs e) public override void KeyUp(KeyEventArgs e)
{ {

View file

@ -31,20 +31,20 @@ using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Geometry;
using System.Drawing; using System.Drawing;
using CodeImp.DoomBuilder.Editing; using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.Controls;
#endregion #endregion
namespace CodeImp.DoomBuilder.BuilderModes.Editing namespace CodeImp.DoomBuilder.BuilderModes.Editing
{ {
[EditMode(SwitchAction = "drawlinesmode", // Action name used to switch to this mode [EditMode(SwitchAction = "drawlinesmode")]
ButtonDesc = "Draw Lines Mode", // Description on the button in toolbar/menu
ButtonImage = "LinesMode.png", // Image resource name for the button
ButtonOrder = int.MinValue + 1)] // Position of the button (lower is more to the left)
public class DrawGeometryMode : ClassicMode public class DrawGeometryMode : ClassicMode
{ {
#region ================== Constants #region ================== Constants
private const float LINE_THICKNESS = 0.6f;
#endregion #endregion
#region ================== Variables #region ================== Variables
@ -110,6 +110,8 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
base.Cancel(); base.Cancel();
// Return to original mode // Return to original mode
Type t = basemode.GetType();
basemode = (EditMode)Activator.CreateInstance(t);
General.Map.ChangeMode(basemode); General.Map.ChangeMode(basemode);
} }
@ -119,12 +121,14 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
base.Disengage(); base.Disengage();
Cursor.Current = Cursors.AppStarting; Cursor.Current = Cursors.AppStarting;
// When not cancelled // When not cancelled and points have been drawn
if(!cancelled) if(!cancelled && (points.Count > 0))
{ {
// Make undo for the draw // Make undo for the draw
General.Map.UndoRedo.CreateUndo("line draw", UndoGroup.None, 0); General.Map.UndoRedo.CreateUndo("line draw", UndoGroup.None, 0);
// Update cached values // Update cached values
General.Map.Map.Update(); General.Map.Map.Update();
@ -143,7 +147,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
protected bool CheckViewChanged() protected bool CheckViewChanged()
{ {
bool viewchanged = false; bool viewchanged = false;
// View changed? // View changed?
if(renderer.OffsetX != lastoffsetx) viewchanged = true; if(renderer.OffsetX != lastoffsetx) viewchanged = true;
if(renderer.OffsetY != lastoffsety) viewchanged = true; if(renderer.OffsetY != lastoffsety) viewchanged = true;
@ -187,10 +191,36 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
snaptonearest = General.Interface.CtrlState; snaptonearest = General.Interface.CtrlState;
Vector2D lastp = new Vector2D(0, 0);
Vector2D curp = GetCurrentPosition();
float vsize = ((float)renderer.VertexSize + 1.0f) / renderer.Scale;
// Render drawing lines // Render drawing lines
if(renderer.StartOverlay(true)) if(renderer.StartOverlay(true))
{ {
RenderSelection(); // Go for all points to draw lines
if(points.Count > 0)
{
// Render lines
lastp = points[0];
for(int i = 1; i < points.Count; i++)
{
renderer.RenderLine(lastp, points[i], LINE_THICKNESS, General.Colors.Selection, true);
lastp = points[i];
}
// Render line to cursor
renderer.RenderLine(lastp, curp, LINE_THICKNESS, General.Colors.Highlight, true);
// Render vertices
for(int i = 0; i < points.Count; i++)
renderer.RenderRectangleFilled(new RectangleF(points[i].x - vsize, points[i].y - vsize, vsize * 2.0f, vsize * 2.0f), General.Colors.Selection, true);
}
// Render vertex at cursor
renderer.RenderRectangleFilled(new RectangleF(curp.x - vsize, curp.y - vsize, vsize * 2.0f, vsize * 2.0f), General.Colors.Highlight, true);
// Done
renderer.Finish(); renderer.Finish();
} }
@ -198,6 +228,57 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
renderer.Present(); renderer.Present();
} }
// This gets the aligned and snapped draw position
private Vector2D GetCurrentPosition()
{
// Snap to nearest?
if(snaptonearest)
{
float vrange = VerticesMode.VERTEX_HIGHLIGHT_RANGE / renderer.Scale;
// Go for all drawn points
foreach(Vector2D v in points)
{
Vector2D delta = mousemappos - v;
if(delta.GetLengthSq() < (vrange * vrange)) return v;
}
// Try the nearest vertex
Vertex nv = General.Map.Map.NearestVertexSquareRange(mousemappos, vrange);
if(nv != null) return nv.Position;
// Try the nearest linedef
Linedef nl = General.Map.Map.NearestLinedefRange(mousemappos, LinedefsMode.LINEDEF_HIGHLIGHT_RANGE / renderer.Scale);
if(nl != null)
{
// Snap to grid?
if(snaptogrid)
{
// Aligned to line and grid
// TODO: Find nearest horzontal and vertical grid intersections and align there
return nl.NearestOnLine(mousemappos);
}
else
{
// Aligned to line
return nl.NearestOnLine(mousemappos);
}
}
}
// Snap to grid?
if(snaptogrid)
{
// Aligned to grid
return General.Map.Grid.SnappedToGrid(mousemappos);
}
else
{
// Normal position
return mousemappos;
}
}
// Mouse moving // Mouse moving
public override void MouseMove(MouseEventArgs e) public override void MouseMove(MouseEventArgs e)
{ {
@ -205,26 +286,46 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
Update(); Update();
} }
// Mouse button released // Drawing a point
public override void MouseUp(MouseEventArgs e) [BeginAction("drawpoint")]
public void DrawPoint()
{ {
base.MouseUp(e); // Mouse inside window?
if(General.Interface.MouseInDisplay)
{
points.Add(GetCurrentPosition());
Update();
}
}
// Remove a point
[BeginAction("removepoint")]
public void RemovePoint()
{
if(points.Count > 0) points.RemoveAt(points.Count - 1);
Update();
}
// Finish drawing
[BeginAction("finishdraw")]
public void FinishDraw()
{
// Just return to base mode, Disengage will be called automatically.
General.Map.ChangeMode(basemode);
} }
// When a key is released // When a key is released
public override void KeyUp(KeyEventArgs e) public override void KeyUp(KeyEventArgs e)
{ {
base.KeyUp(e); base.KeyUp(e);
if(snaptogrid != General.Interface.ShiftState ^ General.Interface.SnapToGrid) Update(); Update();
if(snaptonearest != General.Interface.CtrlState) Update();
} }
// When a key is pressed // When a key is pressed
public override void KeyDown(KeyEventArgs e) public override void KeyDown(KeyEventArgs e)
{ {
base.KeyDown(e); base.KeyDown(e);
if(snaptogrid != General.Interface.ShiftState ^ General.Interface.SnapToGrid) Update(); Update();
if(snaptonearest != General.Interface.CtrlState) Update();
} }
#endregion #endregion

View file

@ -44,7 +44,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
{ {
#region ================== Constants #region ================== Constants
protected const float LINEDEF_HIGHLIGHT_RANGE = 20f; public const float LINEDEF_HIGHLIGHT_RANGE = 20f;
#endregion #endregion
@ -150,7 +150,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
// Render selection // Render selection
if(renderer.StartOverlay(true)) if(renderer.StartOverlay(true))
{ {
RenderSelection(); RenderMultiSelection();
renderer.Finish(); renderer.Finish();
} }
} }
@ -195,39 +195,108 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
General.Interface.HideInfo(); General.Interface.HideInfo();
} }
// This is called wheh selection ends // Selection
protected override void EndSelection() protected override void Select()
{ {
// Go for all lines // Item highlighted?
foreach(Linedef l in General.Map.Map.Linedefs) if((highlighted != null) && !highlighted.IsDisposed)
{ {
l.Selected = ((l.Start.Position.x >= selectionrect.Left) && // Flip selection
(l.Start.Position.y >= selectionrect.Top) && highlighted.Selected = !highlighted.Selected;
(l.Start.Position.x <= selectionrect.Right) &&
(l.Start.Position.y <= selectionrect.Bottom) && // Update display
(l.End.Position.x >= selectionrect.Left) && if(renderer.StartPlotter(false))
(l.End.Position.y >= selectionrect.Top) && {
(l.End.Position.x <= selectionrect.Right) && // Redraw highlight to show selection
(l.End.Position.y <= selectionrect.Bottom)); renderer.PlotLinedef(highlighted, renderer.DetermineLinedefColor(highlighted));
renderer.PlotVertex(highlighted.Start, renderer.DetermineVertexColor(highlighted.Start));
renderer.PlotVertex(highlighted.End, renderer.DetermineVertexColor(highlighted.End));
renderer.Finish();
renderer.Present();
}
} }
else
base.EndSelection(); {
if(renderer.StartOverlay(true)) renderer.Finish(); // Start rectangular selection
General.Interface.RedrawDisplay(); StartMultiSelection();
}
base.Select();
} }
// This is called when the selection is updated // End selection
protected override void UpdateSelection() protected override void EndSelect()
{ {
base.UpdateSelection(); // Not stopping from multiselection?
if(!selecting)
// Render selection
if(renderer.StartOverlay(true))
{ {
RenderSelection(); // Item highlighted?
renderer.Finish(); if((highlighted != null) && !highlighted.IsDisposed)
renderer.Present(); {
// Update display
if(renderer.StartPlotter(false))
{
// Render highlighted item
renderer.PlotLinedef(highlighted, General.Colors.Highlight);
renderer.PlotVertex(highlighted.Start, renderer.DetermineVertexColor(highlighted.Start));
renderer.PlotVertex(highlighted.End, renderer.DetermineVertexColor(highlighted.End));
renderer.Finish();
renderer.Present();
}
}
} }
base.EndSelect();
}
// Start editing
protected override void Edit()
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Highlighted item not selected?
if(!highlighted.Selected)
{
// Make this the only selection
General.Map.Map.ClearSelectedLinedefs();
highlighted.Selected = true;
General.Interface.RedrawDisplay();
}
// Update display
if(renderer.StartPlotter(false))
{
// Redraw highlight to show selection
renderer.PlotLinedef(highlighted, renderer.DetermineLinedefColor(highlighted));
renderer.PlotVertex(highlighted.Start, renderer.DetermineVertexColor(highlighted.Start));
renderer.PlotVertex(highlighted.End, renderer.DetermineVertexColor(highlighted.End));
renderer.Finish();
renderer.Present();
}
}
base.Edit();
}
// Done editing
protected override void EndEdit()
{
// Anything selected?
ICollection<Linedef> selected = General.Map.Map.GetLinedefsSelection(true);
if(selected.Count > 0)
{
// Show line edit dialog
General.Interface.ShowEditLinedefs(selected);
// When a single line was selected, deselect it now
if(selected.Count == 1) General.Map.Map.ClearSelectedLinedefs();
// Update entire display
General.Interface.RedrawDisplay();
}
base.EndEdit();
} }
// Mouse moves // Mouse moves
@ -255,114 +324,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
Highlight(null); Highlight(null);
} }
// Mouse button pressed
public override void MouseDown(MouseEventArgs e)
{
base.MouseDown(e);
// Select button?
if(e.Button == EditMode.SELECT_BUTTON)
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Flip selection
highlighted.Selected = !highlighted.Selected;
// Update display
if(renderer.StartPlotter(false))
{
// Redraw highlight to show selection
renderer.PlotLinedef(highlighted, renderer.DetermineLinedefColor(highlighted));
renderer.PlotVertex(highlighted.Start, renderer.DetermineVertexColor(highlighted.Start));
renderer.PlotVertex(highlighted.End, renderer.DetermineVertexColor(highlighted.End));
renderer.Finish();
renderer.Present();
}
}
else
{
// Start making a selection
StartSelection();
}
}
// Edit button?
else if(e.Button == EditMode.EDIT_BUTTON)
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Highlighted item not selected?
if(!highlighted.Selected)
{
// Make this the only selection
General.Map.Map.ClearSelectedLinedefs();
highlighted.Selected = true;
General.Interface.RedrawDisplay();
}
// Update display
if(renderer.StartPlotter(false))
{
// Redraw highlight to show selection
renderer.PlotLinedef(highlighted, renderer.DetermineLinedefColor(highlighted));
renderer.PlotVertex(highlighted.Start, renderer.DetermineVertexColor(highlighted.Start));
renderer.PlotVertex(highlighted.End, renderer.DetermineVertexColor(highlighted.End));
renderer.Finish();
renderer.Present();
}
}
}
}
// Mouse released
public override void MouseUp(MouseEventArgs e)
{
ICollection<Linedef> selected;
base.MouseUp(e);
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Update display
if(renderer.StartPlotter(false))
{
// Render highlighted item
renderer.PlotLinedef(highlighted, General.Colors.Highlight);
renderer.PlotVertex(highlighted.Start, renderer.DetermineVertexColor(highlighted.Start));
renderer.PlotVertex(highlighted.End, renderer.DetermineVertexColor(highlighted.End));
renderer.Finish();
renderer.Present();
}
// Edit button?
if(e.Button == EditMode.EDIT_BUTTON)
{
// Anything selected?
selected = General.Map.Map.GetLinedefsSelection(true);
if(selected.Count > 0)
{
// Show line edit dialog
General.Interface.ShowEditLinedefs(selected);
// When a single line was selected, deselect it now
if(selected.Count == 1) General.Map.Map.ClearSelectedLinedefs();
// Update entire display
General.Interface.RedrawDisplay();
}
}
}
}
// Mouse wants to drag // Mouse wants to drag
protected override void DragStart(MouseEventArgs e) protected override void DragStart(MouseEventArgs e)
{ {
base.DragStart(e); base.DragStart(e);
// Edit button used? // Edit button used?
if(e.Button == EditMode.EDIT_BUTTON) if(General.Interface.CheckActionActive(null, "classicedit"))
{ {
// Anything highlighted? // Anything highlighted?
if((highlighted != null) && !highlighted.IsDisposed) if((highlighted != null) && !highlighted.IsDisposed)
@ -380,6 +348,45 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
} }
} }
} }
// This is called wheh selection ends
protected override void EndMultiSelection()
{
// Go for all lines
foreach(Linedef l in General.Map.Map.Linedefs)
{
l.Selected = ((l.Start.Position.x >= selectionrect.Left) &&
(l.Start.Position.y >= selectionrect.Top) &&
(l.Start.Position.x <= selectionrect.Right) &&
(l.Start.Position.y <= selectionrect.Bottom) &&
(l.End.Position.x >= selectionrect.Left) &&
(l.End.Position.y >= selectionrect.Top) &&
(l.End.Position.x <= selectionrect.Right) &&
(l.End.Position.y <= selectionrect.Bottom));
}
base.EndMultiSelection();
// Clear overlay
if(renderer.StartOverlay(true)) renderer.Finish();
// Redraw
General.Interface.RedrawDisplay();
}
// This is called when the selection is updated
protected override void UpdateMultiSelection()
{
base.UpdateMultiSelection();
// Render selection
if(renderer.StartOverlay(true))
{
RenderMultiSelection();
renderer.Finish();
renderer.Present();
}
}
#endregion #endregion
} }

View file

@ -165,7 +165,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
// Render selection // Render selection
if(renderer.StartOverlay(true)) if(renderer.StartOverlay(true))
{ {
RenderSelection(); RenderMultiSelection();
renderer.Finish(); renderer.Finish();
} }
} }
@ -216,61 +216,107 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
General.Interface.HideInfo(); General.Interface.HideInfo();
} }
// This is called wheh selection ends // Selection
protected override void EndSelection() protected override void Select()
{ {
// Go for all lines // Item highlighted?
foreach(Linedef l in General.Map.Map.Linedefs) if((highlighted != null) && !highlighted.IsDisposed)
{ {
l.Selected = ((l.Start.Position.x >= selectionrect.Left) && // Flip selection
(l.Start.Position.y >= selectionrect.Top) && SelectSector(highlighted, !highlighted.Selected);
(l.Start.Position.x <= selectionrect.Right) &&
(l.Start.Position.y <= selectionrect.Bottom) &&
(l.End.Position.x >= selectionrect.Left) &&
(l.End.Position.y >= selectionrect.Top) &&
(l.End.Position.x <= selectionrect.Right) &&
(l.End.Position.y <= selectionrect.Bottom));
}
// Go for all sectors // Update display
foreach(Sector s in General.Map.Map.Sectors) if(renderer.StartPlotter(false))
{
// Go for all sidedefs
bool allselected = true;
foreach(Sidedef sd in s.Sidedefs)
{ {
if(!sd.Line.Selected) // Redraw highlight to show selection
{ renderer.PlotSector(highlighted);
allselected = false; renderer.Finish();
break; renderer.Present();
}
} }
}
// Sector completely selected? else
s.Selected = allselected; {
// Start making a selection
StartMultiSelection();
} }
// Make sure all linedefs reflect selected sectors base.Select();
foreach(Sector s in General.Map.Map.Sectors)
SelectSector(s, s.Selected);
base.EndSelection();
if(renderer.StartOverlay(true)) renderer.Finish();
General.Interface.RedrawDisplay();
} }
// This is called when the selection is updated // End selection
protected override void UpdateSelection() protected override void EndSelect()
{ {
base.UpdateSelection(); // Not stopping from multiselection?
if(!selecting)
// Render selection
if(renderer.StartOverlay(true))
{ {
RenderSelection(); // Item highlighted?
renderer.Finish(); if((highlighted != null) && !highlighted.IsDisposed)
renderer.Present(); {
// Update display
if(renderer.StartPlotter(false))
{
// Render highlighted item
renderer.PlotSector(highlighted, General.Colors.Highlight);
renderer.Finish();
renderer.Present();
}
}
} }
base.EndSelect();
}
// Start editing
protected override void Edit()
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Highlighted item not selected?
if(!highlighted.Selected)
{
// Make this the only selection
General.Map.Map.ClearSelectedSectors();
General.Map.Map.ClearSelectedLinedefs();
SelectSector(highlighted, true);
General.Interface.RedrawDisplay();
}
// Update display
if(renderer.StartPlotter(false))
{
// Redraw highlight to show selection
renderer.PlotSector(highlighted);
renderer.Finish();
renderer.Present();
}
}
base.Edit();
}
// Done editing
protected override void EndEdit()
{
// Anything selected?
ICollection<Sector> selected = General.Map.Map.GetSectorsSelection(true);
if(selected.Count > 0)
{
// Show sector edit dialog
General.Interface.ShowEditSectors(selected);
// When a single sector was selected, deselect it now
if(selected.Count == 1)
{
General.Map.Map.ClearSelectedSectors();
General.Map.Map.ClearSelectedLinedefs();
}
// Update entire display
General.Interface.RedrawDisplay();
}
base.EndEdit();
} }
// Mouse moves // Mouse moves
@ -326,113 +372,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
Highlight(null); Highlight(null);
} }
// Mouse button pressed
public override void MouseDown(MouseEventArgs e)
{
base.MouseDown(e);
// Select button?
if(e.Button == EditMode.SELECT_BUTTON)
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Flip selection
SelectSector(highlighted, !highlighted.Selected);
// Update display
if(renderer.StartPlotter(false))
{
// Redraw highlight to show selection
renderer.PlotSector(highlighted);
renderer.Finish();
renderer.Present();
}
}
else
{
// Start making a selection
StartSelection();
}
}
// Edit button?
else if(e.Button == EditMode.EDIT_BUTTON)
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Highlighted item not selected?
if(!highlighted.Selected)
{
// Make this the only selection
General.Map.Map.ClearSelectedSectors();
General.Map.Map.ClearSelectedLinedefs();
SelectSector(highlighted, true);
General.Interface.RedrawDisplay();
}
// Update display
if(renderer.StartPlotter(false))
{
// Redraw highlight to show selection
renderer.PlotSector(highlighted);
renderer.Finish();
renderer.Present();
}
}
}
}
// Mouse released
public override void MouseUp(MouseEventArgs e)
{
ICollection<Sector> selected;
base.MouseUp(e);
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Update display
if(renderer.StartPlotter(false))
{
// Render highlighted item
renderer.PlotSector(highlighted, General.Colors.Highlight);
renderer.Finish();
renderer.Present();
}
// Edit button?
if(e.Button == EditMode.EDIT_BUTTON)
{
// Anything selected?
selected = General.Map.Map.GetSectorsSelection(true);
if(selected.Count > 0)
{
// Show sector edit dialog
General.Interface.ShowEditSectors(selected);
// When a single sector was selected, deselect it now
if(selected.Count == 1)
{
General.Map.Map.ClearSelectedSectors();
General.Map.Map.ClearSelectedLinedefs();
}
// Update entire display
General.Interface.RedrawDisplay();
}
}
}
}
// Mouse wants to drag // Mouse wants to drag
protected override void DragStart(MouseEventArgs e) protected override void DragStart(MouseEventArgs e)
{ {
base.DragStart(e); base.DragStart(e);
// Edit button used? // Edit button used?
if(e.Button == EditMode.EDIT_BUTTON) if(General.Interface.CheckActionActive(null, "classicedit"))
{ {
// Anything highlighted? // Anything highlighted?
if((highlighted != null) && !highlighted.IsDisposed) if((highlighted != null) && !highlighted.IsDisposed)
@ -450,6 +396,63 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
} }
} }
} }
// This is called wheh selection ends
protected override void EndMultiSelection()
{
// Go for all lines
foreach(Linedef l in General.Map.Map.Linedefs)
{
l.Selected = ((l.Start.Position.x >= selectionrect.Left) &&
(l.Start.Position.y >= selectionrect.Top) &&
(l.Start.Position.x <= selectionrect.Right) &&
(l.Start.Position.y <= selectionrect.Bottom) &&
(l.End.Position.x >= selectionrect.Left) &&
(l.End.Position.y >= selectionrect.Top) &&
(l.End.Position.x <= selectionrect.Right) &&
(l.End.Position.y <= selectionrect.Bottom));
}
// Go for all sectors
foreach(Sector s in General.Map.Map.Sectors)
{
// Go for all sidedefs
bool allselected = true;
foreach(Sidedef sd in s.Sidedefs)
{
if(!sd.Line.Selected)
{
allselected = false;
break;
}
}
// Sector completely selected?
s.Selected = allselected;
}
// Make sure all linedefs reflect selected sectors
foreach(Sector s in General.Map.Map.Sectors)
SelectSector(s, s.Selected);
base.EndMultiSelection();
if(renderer.StartOverlay(true)) renderer.Finish();
General.Interface.RedrawDisplay();
}
// This is called when the selection is updated
protected override void UpdateMultiSelection()
{
base.UpdateMultiSelection();
// Render selection
if(renderer.StartOverlay(true))
{
RenderMultiSelection();
renderer.Finish();
renderer.Present();
}
}
#endregion #endregion
} }

View file

@ -134,7 +134,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
// Render selection // Render selection
if(renderer.StartOverlay(true)) if(renderer.StartOverlay(true))
{ {
RenderSelection(); RenderMultiSelection();
renderer.Finish(); renderer.Finish();
} }
} }
@ -171,35 +171,102 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
General.Interface.HideInfo(); General.Interface.HideInfo();
} }
// This is called wheh selection ends // Selection
protected override void EndSelection() protected override void Select()
{ {
// Go for all things // Item highlighted?
foreach(Thing t in General.Map.Map.Things) if((highlighted != null) && !highlighted.IsDisposed)
{ {
t.Selected = ((t.Position.x >= selectionrect.Left) && // Flip selection
(t.Position.y >= selectionrect.Top) && highlighted.Selected = !highlighted.Selected;
(t.Position.x <= selectionrect.Right) &&
(t.Position.y <= selectionrect.Bottom)); // Update display
if(renderer.StartThings(false))
{
// Redraw highlight to show selection
renderer.RenderThing(highlighted, renderer.DetermineThingColor(highlighted));
renderer.Finish();
renderer.Present();
}
}
else
{
// Start making a selection
StartMultiSelection();
} }
base.EndSelection(); base.Select();
if(renderer.StartOverlay(true)) renderer.Finish();
General.Interface.RedrawDisplay();
} }
// This is called when the selection is updated // End selection
protected override void UpdateSelection() protected override void EndSelect()
{ {
base.UpdateSelection(); // Not ending from a multi-selection?
if(!selecting)
// Render selection
if(renderer.StartOverlay(true))
{ {
RenderSelection(); // Item highlighted?
renderer.Finish(); if((highlighted != null) && !highlighted.IsDisposed)
renderer.Present(); {
// Update display
if(renderer.StartThings(false))
{
// Render highlighted item
renderer.RenderThing(highlighted, General.Colors.Highlight);
renderer.Finish();
renderer.Present();
}
}
} }
base.EndSelect();
}
// Start editing
protected override void Edit()
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Highlighted item not selected?
if(!highlighted.Selected)
{
// Make this the only selection
General.Map.Map.ClearSelectedThings();
highlighted.Selected = true;
General.Interface.RedrawDisplay();
}
// Update display
if(renderer.StartThings(false))
{
// Redraw highlight to show selection
renderer.RenderThing(highlighted, renderer.DetermineThingColor(highlighted));
renderer.Finish();
renderer.Present();
}
}
base.Edit();
}
// Done editing
protected override void EndEdit()
{
// Anything selected?
ICollection<Thing> selected = General.Map.Map.GetThingsSelection(true);
if(selected.Count > 0)
{
// Show thing edit dialog
// TODO
// When a single thing was selected, deselect it now
if(selected.Count == 1) General.Map.Map.ClearSelectedThings();
// Update entire display
General.Interface.RedrawDisplay();
}
base.EndEdit();
} }
// Mouse moves // Mouse moves
@ -227,108 +294,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
Highlight(null); Highlight(null);
} }
// Mouse button pressed
public override void MouseDown(MouseEventArgs e)
{
base.MouseDown(e);
// Select button?
if(e.Button == EditMode.SELECT_BUTTON)
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Flip selection
highlighted.Selected = !highlighted.Selected;
// Update display
if(renderer.StartThings(false))
{
// Redraw highlight to show selection
renderer.RenderThing(highlighted, renderer.DetermineThingColor(highlighted));
renderer.Finish();
renderer.Present();
}
}
else
{
// Start making a selection
StartSelection();
}
}
// Edit button?
else if(e.Button == EditMode.EDIT_BUTTON)
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Highlighted item not selected?
if(!highlighted.Selected)
{
// Make this the only selection
General.Map.Map.ClearSelectedThings();
highlighted.Selected = true;
General.Interface.RedrawDisplay();
}
// Update display
if(renderer.StartThings(false))
{
// Redraw highlight to show selection
renderer.RenderThing(highlighted, renderer.DetermineThingColor(highlighted));
renderer.Finish();
renderer.Present();
}
}
}
}
// Mouse released
public override void MouseUp(MouseEventArgs e)
{
ICollection<Thing> selected;
base.MouseUp(e);
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Update display
if(renderer.StartThings(false))
{
// Render highlighted item
renderer.RenderThing(highlighted, General.Colors.Highlight);
renderer.Finish();
renderer.Present();
}
// Edit button?
if(e.Button == EditMode.EDIT_BUTTON)
{
// Anything selected?
selected = General.Map.Map.GetThingsSelection(true);
if(selected.Count > 0)
{
// Show thing edit dialog
// TODO
// When a single thing was selected, deselect it now
if(selected.Count == 1) General.Map.Map.ClearSelectedThings();
// Update entire display
General.Interface.RedrawDisplay();
}
}
}
}
// Mouse wants to drag // Mouse wants to drag
protected override void DragStart(MouseEventArgs e) protected override void DragStart(MouseEventArgs e)
{ {
base.DragStart(e); base.DragStart(e);
// Edit button used? // Edit button used?
if(e.Button == EditMode.EDIT_BUTTON) if(General.Interface.CheckActionActive(null, "classicedit"))
{ {
// Anything highlighted? // Anything highlighted?
if((highlighted != null) && !highlighted.IsDisposed) if((highlighted != null) && !highlighted.IsDisposed)
@ -346,6 +318,41 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
} }
} }
} }
// This is called wheh selection ends
protected override void EndMultiSelection()
{
// Go for all things
foreach(Thing t in General.Map.Map.Things)
{
t.Selected = ((t.Position.x >= selectionrect.Left) &&
(t.Position.y >= selectionrect.Top) &&
(t.Position.x <= selectionrect.Right) &&
(t.Position.y <= selectionrect.Bottom));
}
base.EndMultiSelection();
// Clear overlay
if(renderer.StartOverlay(true)) renderer.Finish();
// Redraw
General.Interface.RedrawDisplay();
}
// This is called when the selection is updated
protected override void UpdateMultiSelection()
{
base.UpdateMultiSelection();
// Render selection
if(renderer.StartOverlay(true))
{
RenderMultiSelection();
renderer.Finish();
renderer.Present();
}
}
#endregion #endregion
} }

View file

@ -150,7 +150,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
// Render selection // Render selection
if(renderer.StartOverlay(true)) if(renderer.StartOverlay(true))
{ {
RenderSelection(); RenderMultiSelection();
renderer.Finish(); renderer.Finish();
} }
} }
@ -186,36 +186,65 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
else else
General.Interface.HideInfo(); General.Interface.HideInfo();
} }
// This is called wheh selection ends // Selection
protected override void EndSelection() protected override void Select()
{ {
// Go for all vertices // Item highlighted?
foreach(Vertex v in General.Map.Map.Vertices) if((highlighted != null) && !highlighted.IsDisposed)
{ {
v.Selected = ((v.Position.x >= selectionrect.Left) && // Flip selection
(v.Position.y >= selectionrect.Top) && highlighted.Selected = !highlighted.Selected;
(v.Position.x <= selectionrect.Right) &&
(v.Position.y <= selectionrect.Bottom)); // Redraw highlight to show selection
if(renderer.StartPlotter(false))
{
renderer.PlotVertex(highlighted, renderer.DetermineVertexColor(highlighted));
renderer.Finish();
renderer.Present();
}
}
else
{
// Start making a selection
StartMultiSelection();
} }
base.EndSelection(); base.Select();
if(renderer.StartOverlay(true)) renderer.Finish();
General.Interface.RedrawDisplay();
} }
// This is called when the selection is updated // End selection
protected override void UpdateSelection() protected override void EndSelect()
{ {
base.UpdateSelection(); // Not stopping from multiselection?
if(!selecting)
// Render selection
if(renderer.StartOverlay(true))
{ {
RenderSelection(); // Item highlighted?
renderer.Finish(); if((highlighted != null) && !highlighted.IsDisposed)
renderer.Present(); {
// Render highlighted item
if(renderer.StartPlotter(false))
{
renderer.PlotVertex(highlighted, ColorCollection.HIGHLIGHT);
renderer.Finish();
renderer.Present();
}
}
} }
base.EndSelect();
}
// Start editing
protected override void Edit()
{
base.Edit();
}
// Done editing
protected override void EndEdit()
{
base.EndEdit();
} }
// Mouse moves // Mouse moves
@ -242,54 +271,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
// Highlight nothing // Highlight nothing
Highlight(null); Highlight(null);
} }
// Mouse button pressed
public override void MouseDown(MouseEventArgs e)
{
base.MouseDown(e);
// Which button is used?
if(e.Button == EditMode.SELECT_BUTTON)
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Flip selection
highlighted.Selected = !highlighted.Selected;
// Redraw highlight to show selection
if(renderer.StartPlotter(false))
{
renderer.PlotVertex(highlighted, renderer.DetermineVertexColor(highlighted));
renderer.Finish();
renderer.Present();
}
}
else
{
// Start making a selection
StartSelection();
}
}
}
// Mouse released
public override void MouseUp(MouseEventArgs e)
{
base.MouseUp(e);
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Render highlighted item
if(renderer.StartPlotter(false))
{
renderer.PlotVertex(highlighted, ColorCollection.HIGHLIGHT);
renderer.Finish();
renderer.Present();
}
}
}
// Mouse wants to drag // Mouse wants to drag
protected override void DragStart(MouseEventArgs e) protected override void DragStart(MouseEventArgs e)
@ -297,7 +278,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
base.DragStart(e); base.DragStart(e);
// Edit button used? // Edit button used?
if(e.Button == EditMode.EDIT_BUTTON) if(General.Interface.CheckActionActive(null, "classicedit"))
{ {
// Anything highlighted? // Anything highlighted?
if((highlighted != null) && !highlighted.IsDisposed) if((highlighted != null) && !highlighted.IsDisposed)
@ -315,6 +296,41 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
} }
} }
} }
// This is called wheh selection ends
protected override void EndMultiSelection()
{
// Go for all vertices
foreach(Vertex v in General.Map.Map.Vertices)
{
v.Selected = ((v.Position.x >= selectionrect.Left) &&
(v.Position.y >= selectionrect.Top) &&
(v.Position.x <= selectionrect.Right) &&
(v.Position.y <= selectionrect.Bottom));
}
base.EndMultiSelection();
// Clear overlay
if(renderer.StartOverlay(true)) renderer.Finish();
// Redraw
General.Interface.RedrawDisplay();
}
// This is called when the selection is updated
protected override void UpdateMultiSelection()
{
base.UpdateMultiSelection();
// Render selection
if(renderer.StartOverlay(true))
{
RenderMultiSelection();
renderer.Finish();
renderer.Present();
}
}
#endregion #endregion
} }

View file

@ -2,8 +2,21 @@
Doom Builder Actions Configuration Doom Builder Actions Configuration
\******************************************/ \******************************************/
// This just defines which actions there are and what description they have // This just defines which actions there are, what description they have and
// The source code will bind to these actions with delegates (function pointers) // some behaviour options. The Doom Builder core will bind to these actions
// with delegates (function pointers) where you use the BeginAction and
// EndAction attributes.
// Behaviour options:
//
// allowkeys: Allows the user to bind standard keys to this action.
// allowmouse: Allows the user to bind mouse buttons to this action.
// allowscroll: Allows the user to bind the scrollwheel to this action.
// disregardshift: This action will be triggered regardless if Shift or Control are used.
// repeat: BeginAction will be called for automatic key repetition.
//
// allowkeys and allowmouse are true by default, the others are false by default.
//
verticesmode verticesmode
{ {
@ -43,8 +56,36 @@ thingsmode
drawlinesmode drawlinesmode
{ {
title = "Edit: Draw Lines"; title = "2D: Draw Lines";
description = "Starts drawing lines."; description = "Starts drawing lines. See the Drawing category for actions available during drawing mode.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
}
drawpoint
{
title = "Drawing: Draws Vertex";
description = "Draws a vertex at the mousecursor position.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
disregardshift = true;
}
removepoint
{
title = "Drawing: Remove Previous Vertex";
description = "Removes the previously drawn vertex from the drawing session.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
}
finishdraw
{
title = "Drawing: Finish Drawing";
description = "Finishes the drawing and creates the geometry.";
allowkeys = true; allowkeys = true;
allowmouse = true; allowmouse = true;
allowscroll = true; allowscroll = true;

View file

@ -232,8 +232,8 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
base.MouseDown(e); base.MouseDown(e);
bool front, back; bool front, back;
// Which button is used? // Edit button is used?
if(e.Button == EditMode.SELECT_BUTTON) if(General.Interface.CheckActionActive(null, "classicedit"))
{ {
// Item highlighted? // Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed) if((highlighted != null) && !highlighted.IsDisposed)
@ -272,8 +272,8 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
// Item highlighted? // Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed) if((highlighted != null) && !highlighted.IsDisposed)
{ {
// Which button is used? // Edit button is used?
if(e.Button == EditMode.SELECT_BUTTON) if(General.Interface.CheckActionActive(null, "classicedit"))
{ {
// Anything selected? // Anything selected?
selected = General.Map.Map.GetSectorsSelection(true); selected = General.Map.Map.GetSectorsSelection(true);

View file

@ -39,14 +39,18 @@ namespace CodeImp.DoomBuilder.Controls
// Shortcut key // Shortcut key
private int key; private int key;
private int keymask;
// Shortcut options // Shortcut options
private bool allowkeys; private bool allowkeys;
private bool allowmouse; private bool allowmouse;
private bool allowscroll; private bool allowscroll;
private bool disregardshift;
private bool repeat;
// Delegate // Delegate
private List<ActionDelegate> delegates; private List<ActionDelegate> begindelegates;
private List<ActionDelegate> enddelegates;
#endregion #endregion
@ -57,9 +61,12 @@ namespace CodeImp.DoomBuilder.Controls
public string Title { get { return title; } } public string Title { get { return title; } }
public string Description { get { return description; } } public string Description { get { return description; } }
public int ShortcutKey { get { return key; } } public int ShortcutKey { get { return key; } }
public int ShortcutMask { get { return keymask; } }
public bool AllowKeys { get { return allowkeys; } } public bool AllowKeys { get { return allowkeys; } }
public bool AllowMouse { get { return allowmouse; } } public bool AllowMouse { get { return allowmouse; } }
public bool AllowScroll { get { return allowscroll; } } public bool AllowScroll { get { return allowscroll; } }
public bool DisregardShift { get { return disregardshift; } }
public bool Repeat { get { return repeat; } }
#endregion #endregion
@ -67,18 +74,32 @@ namespace CodeImp.DoomBuilder.Controls
// Constructor // Constructor
public Action(string name, string shortname, string title, string description, int key, public Action(string name, string shortname, string title, string description, int key,
bool allowkeys, bool allowmouse, bool allowscroll) bool allowkeys, bool allowmouse, bool allowscroll, bool disregardshift, bool repeat)
{ {
// Initialize // Initialize
this.name = name; this.name = name;
this.shortname = shortname; this.shortname = shortname;
this.title = title; this.title = title;
this.description = description; this.description = description;
this.delegates = new List<ActionDelegate>(); this.begindelegates = new List<ActionDelegate>();
this.enddelegates = new List<ActionDelegate>();
this.allowkeys = allowkeys; this.allowkeys = allowkeys;
this.allowmouse = allowmouse; this.allowmouse = allowmouse;
this.allowscroll = allowscroll; this.allowscroll = allowscroll;
this.key = key; this.disregardshift = disregardshift;
this.repeat = repeat;
if(disregardshift)
{
keymask = (int)Keys.Shift | (int)Keys.Control;
keymask = ~keymask;
}
else
{
keymask = ~0;
}
this.key = key & keymask;
} }
// Destructor // Destructor
@ -166,42 +187,71 @@ namespace CodeImp.DoomBuilder.Controls
public void SetShortcutKey(int key) public void SetShortcutKey(int key)
{ {
// Make it so. // Make it so.
this.key = key; this.key = key & keymask;
} }
// This binds a delegate to this action // This binds a delegate to this action
public void Bind(ActionDelegate method) public void BindBegin(ActionDelegate method)
{ {
delegates.Add(method); begindelegates.Add(method);
} }
// This removes a delegate from this action // This removes a delegate from this action
public void Unbind(ActionDelegate method) public void UnbindBegin(ActionDelegate method)
{ {
delegates.Remove(method); begindelegates.Remove(method);
}
// This binds a delegate to this action
public void BindEnd(ActionDelegate method)
{
enddelegates.Add(method);
}
// This removes a delegate from this action
public void UnbindEnd(ActionDelegate method)
{
enddelegates.Remove(method);
} }
// This raises events for this action // This raises events for this action
public void Invoke() public void Begin()
{ {
List<ActionDelegate> delegateslist; List<ActionDelegate> delegateslist;
// No method bound? // Method bound?
if(delegates.Count == 0) if(begindelegates.Count > 0)
{
// Ignore this since keys can also be handled through KeyDown and KeyUp in editing modes
//General.WriteLogLine("Called action '" + name + "' has no methods bound");
}
else
{ {
// Copy delegates list // Copy delegates list
delegateslist = new List<ActionDelegate>(delegates); delegateslist = new List<ActionDelegate>(begindelegates);
// Invoke all the delegates // Invoke all the delegates
foreach(ActionDelegate ad in delegateslist) ad.Invoke(); foreach(ActionDelegate ad in delegateslist) ad.Invoke();
} }
} }
// This raises events for this action
public void End()
{
List<ActionDelegate> delegateslist;
// Method bound?
if(enddelegates.Count > 0)
{
// Copy delegates list
delegateslist = new List<ActionDelegate>(enddelegates);
// Invoke all the delegates
foreach(ActionDelegate ad in delegateslist) ad.Invoke();
}
}
// This checks if the action qualifies for a key combination
public bool KeyMatches(int pressedkey)
{
return (key == (pressedkey & keymask));
}
#endregion #endregion
} }
} }

View file

@ -30,15 +30,15 @@ namespace CodeImp.DoomBuilder.Controls
/// <summary> /// <summary>
/// This binds a method to an action. /// This binds a method to an action.
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited=true, AllowMultiple=true)] [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class ActionAttribute : Attribute public class ActionAttribute : Attribute
{ {
#region ================== Variables #region ================== Variables
// The action to bind to // The action to bind to
private string action; protected string action;
private bool baseaction; protected bool baseaction;
#endregion #endregion
#region ================== Properties #region ================== Properties
@ -47,6 +47,7 @@ namespace CodeImp.DoomBuilder.Controls
/// Set to true to indicate this is a core Doom Builder action when used within a plugin. /// Set to true to indicate this is a core Doom Builder action when used within a plugin.
/// </summary> /// </summary>
public bool BaseAction { get { return baseaction; } set { baseaction = value; } } public bool BaseAction { get { return baseaction; } set { baseaction = value; } }
internal string ActionName { get { return action; } }
#endregion #endregion
@ -71,19 +72,15 @@ namespace CodeImp.DoomBuilder.Controls
public string GetFullActionName(Assembly asm) public string GetFullActionName(Assembly asm)
{ {
string asmname; string asmname;
if(baseaction) if(baseaction)
asmname = General.ThisAssembly.GetName().Name.ToLowerInvariant(); asmname = General.ThisAssembly.GetName().Name.ToLowerInvariant();
else else
asmname = asm.GetName().Name.ToLowerInvariant(); asmname = asm.GetName().Name.ToLowerInvariant();
return asmname + "_" + action; return asmname + "_" + action;
} }
#endregion
#region ================== Static Methods
// This makes the proper name // This makes the proper name
public string GetFullActionName(Assembly asm, bool baseaction, string actionname) public string GetFullActionName(Assembly asm, bool baseaction, string actionname)
{ {
@ -97,134 +94,6 @@ namespace CodeImp.DoomBuilder.Controls
return asmname + "_" + actionname; return asmname + "_" + actionname;
} }
// This binds all methods marked with this attribute
internal static void BindMethods(Type type)
{
// Bind static methods
BindMethods(null, type);
}
// This binds all methods marked with this attribute
internal static void BindMethods(object obj)
{
// Bind instance methods
BindMethods(obj, obj.GetType());
}
// This binds all methods marked with this attribute
private static void BindMethods(object obj, Type type)
{
MethodInfo[] methods;
ActionAttribute[] attrs;
ActionDelegate del;
string actionname;
if(obj == null)
General.WriteLogLine("Binding static action methods for class " + type.Name + "...");
else
General.WriteLogLine("Binding action methods for " + type.Name + " object...");
// Go for all methods on obj
methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
foreach(MethodInfo m in methods)
{
// Check if the method has this attribute
attrs = (ActionAttribute[])m.GetCustomAttributes(typeof(ActionAttribute), true);
// Go for all attributes
foreach(ActionAttribute a in attrs)
{
// Create a delegate for this method
del = (ActionDelegate)Delegate.CreateDelegate(typeof(ActionDelegate), obj, m);
// Make proper name
actionname = a.GetFullActionName(type.Assembly);
// Bind method to action
if(General.Actions.Exists(actionname))
General.Actions[actionname].Bind(del);
else
throw new ArgumentException("Could not bind " + m.ReflectedType.Name + "." + m.Name + " to action \"" + actionname + "\", that action does not exist! Refer to, or edit Actions.cfg for all available application actions.");
}
}
}
// This binds a delegate manually
internal static void BindDelegate(Assembly asm, ActionDelegate d, ActionAttribute a)
{
string actionname;
// Make proper name
actionname = a.GetFullActionName(asm);
// Bind delegate to action
if(General.Actions.Exists(actionname))
General.Actions[actionname].Bind(d);
else
General.WriteLogLine("WARNING: Could not bind delegate for " + d.Method.Name + " to action \"" + a.action + "\" (" + actionname + "), that action does not exist! Refer to, or edit Actions.cfg for all available application actions.");
}
// This unbinds all methods marked with this attribute
internal static void UnbindMethods(Type type)
{
// Unbind static methods
UnbindMethods(null, type);
}
// This unbinds all methods marked with this attribute
internal static void UnbindMethods(object obj)
{
// Unbind instance methods
UnbindMethods(obj, obj.GetType());
}
// This unbinds all methods marked with this attribute
private static void UnbindMethods(object obj, Type type)
{
MethodInfo[] methods;
ActionAttribute[] attrs;
ActionDelegate del;
string actionname;
if(obj == null)
General.WriteLogLine("Unbinding static action methods for class " + type.Name + "...");
else
General.WriteLogLine("Unbinding action methods for " + type.Name + " object...");
// Go for all methods on obj
methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
foreach(MethodInfo m in methods)
{
// Check if the method has this attribute
attrs = (ActionAttribute[])m.GetCustomAttributes(typeof(ActionAttribute), true);
// Go for all attributes
foreach(ActionAttribute a in attrs)
{
// Create a delegate for this method
del = (ActionDelegate)Delegate.CreateDelegate(typeof(ActionDelegate), obj, m);
// Make proper name
actionname = a.GetFullActionName(type.Assembly);
// Unbind method from action
General.Actions[actionname].Unbind(del);
}
}
}
// This unbinds a delegate manually
internal static void UnbindDelegate(Assembly asm, ActionDelegate d, ActionAttribute a)
{
string actionname;
// Make proper name
actionname = a.GetFullActionName(asm);
// Unbind delegate to action
General.Actions[actionname].Unbind(d);
}
#endregion #endregion
} }
} }

View file

@ -26,6 +26,7 @@ using System.IO;
using CodeImp.DoomBuilder.IO; using CodeImp.DoomBuilder.IO;
using System.Collections; using System.Collections;
using System.Reflection; using System.Reflection;
using System.Windows.Forms;
#endregion #endregion
@ -44,6 +45,13 @@ namespace CodeImp.DoomBuilder.Controls
// Actions // Actions
private Dictionary<string, Action> actions; private Dictionary<string, Action> actions;
// Keys state
private int modifiers;
private List<int> pressedkeys;
// Begun actions
private List<Action> activeactions;
// Disposing // Disposing
private bool isdisposed = false; private bool isdisposed = false;
@ -64,7 +72,9 @@ namespace CodeImp.DoomBuilder.Controls
// Initialize // Initialize
General.WriteLogLine("Starting action manager..."); General.WriteLogLine("Starting action manager...");
actions = new Dictionary<string, Action>(); actions = new Dictionary<string, Action>();
pressedkeys = new List<int>();
activeactions = new List<Action>();
// Load all actions in this assembly // Load all actions in this assembly
LoadActions(General.ThisAssembly); LoadActions(General.ThisAssembly);
@ -96,7 +106,7 @@ namespace CodeImp.DoomBuilder.Controls
StreamReader actionsreader; StreamReader actionsreader;
Configuration cfg; Configuration cfg;
string name, title, desc, shortname; string name, title, desc, shortname;
bool amouse, akeys, ascroll, debugonly; bool amouse, akeys, ascroll, debugonly, noshift, repeat;
string[] resnames; string[] resnames;
AssemblyName asmname = asm.GetName(); AssemblyName asmname = asm.GetName();
@ -127,16 +137,18 @@ namespace CodeImp.DoomBuilder.Controls
name = asmname.Name.ToLowerInvariant() + "_" + shortname; name = asmname.Name.ToLowerInvariant() + "_" + shortname;
title = cfg.ReadSetting(a.Key + ".title", "[" + name + "]"); title = cfg.ReadSetting(a.Key + ".title", "[" + name + "]");
desc = cfg.ReadSetting(a.Key + ".description", ""); desc = cfg.ReadSetting(a.Key + ".description", "");
akeys = cfg.ReadSetting(a.Key + ".allowkeys", false); akeys = cfg.ReadSetting(a.Key + ".allowkeys", true);
amouse = cfg.ReadSetting(a.Key + ".allowmouse", false); amouse = cfg.ReadSetting(a.Key + ".allowmouse", true);
ascroll = cfg.ReadSetting(a.Key + ".allowscroll", false); ascroll = cfg.ReadSetting(a.Key + ".allowscroll", false);
noshift = cfg.ReadSetting(a.Key + ".disregardshift", false);
repeat = cfg.ReadSetting(a.Key + ".repeat", false);
debugonly = cfg.ReadSetting(a.Key + ".debugonly", false); debugonly = cfg.ReadSetting(a.Key + ".debugonly", false);
// Check if action should be included // Check if action should be included
if(General.DebugBuild || !debugonly) if(General.DebugBuild || !debugonly)
{ {
// Create an action // Create an action
CreateAction(name, shortname, title, desc, akeys, amouse, ascroll); CreateAction(name, shortname, title, desc, akeys, amouse, ascroll, noshift, repeat);
} }
} }
} }
@ -144,7 +156,7 @@ namespace CodeImp.DoomBuilder.Controls
} }
// This manually creates an action // This manually creates an action
private void CreateAction(string name, string shortname, string title, string desc, bool allowkeys, bool allowmouse, bool allowscroll) private void CreateAction(string name, string shortname, string title, string desc, bool allowkeys, bool allowmouse, bool allowscroll, bool disregardshift, bool repeat)
{ {
// Action does not exist yet? // Action does not exist yet?
if(!actions.ContainsKey(name)) if(!actions.ContainsKey(name))
@ -153,7 +165,7 @@ namespace CodeImp.DoomBuilder.Controls
int key = General.Settings.ReadSetting("shortcuts." + name, 0); int key = General.Settings.ReadSetting("shortcuts." + name, 0);
// Create an action // Create an action
actions.Add(name, new Action(name, shortname, title, desc, key, allowkeys, allowmouse, allowscroll)); actions.Add(name, new Action(name, shortname, title, desc, key, allowkeys, allowmouse, allowscroll, disregardshift, repeat));
} }
else else
{ {
@ -161,6 +173,196 @@ namespace CodeImp.DoomBuilder.Controls
General.WriteLogLine("WARNING: Action '" + name + "' already exists. Action names must be unique!"); General.WriteLogLine("WARNING: Action '" + name + "' already exists. Action names must be unique!");
} }
} }
// This binds all methods marked with this attribute
internal void BindMethods(Type type)
{
// Bind static methods
BindMethods(null, type);
}
// This binds all methods marked with this attribute
internal void BindMethods(object obj)
{
// Bind instance methods
BindMethods(obj, obj.GetType());
}
// This binds all methods marked with this attribute
private void BindMethods(object obj, Type type)
{
MethodInfo[] methods;
ActionAttribute[] attrs;
ActionDelegate del;
string actionname;
if(obj == null)
General.WriteLogLine("Binding static action methods for class " + type.Name + "...");
else
General.WriteLogLine("Binding action methods for " + type.Name + " object...");
// Go for all methods on obj
methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
foreach(MethodInfo m in methods)
{
// Check if the method has this attribute
attrs = (ActionAttribute[])m.GetCustomAttributes(typeof(BeginActionAttribute), true);
// Go for all attributes
foreach(ActionAttribute a in attrs)
{
// Create a delegate for this method
del = (ActionDelegate)Delegate.CreateDelegate(typeof(ActionDelegate), obj, m);
// Make proper name
actionname = a.GetFullActionName(type.Assembly);
// Bind method to action
if(Exists(actionname))
actions[actionname].BindBegin(del);
else
throw new ArgumentException("Could not bind " + m.ReflectedType.Name + "." + m.Name + " to action \"" + actionname + "\", that action does not exist! Refer to, or edit Actions.cfg for all available application actions.");
}
// Check if the method has this attribute
attrs = (ActionAttribute[])m.GetCustomAttributes(typeof(EndActionAttribute), true);
// Go for all attributes
foreach(ActionAttribute a in attrs)
{
// Create a delegate for this method
del = (ActionDelegate)Delegate.CreateDelegate(typeof(ActionDelegate), obj, m);
// Make proper name
actionname = a.GetFullActionName(type.Assembly);
// Bind method to action
if(Exists(actionname))
actions[actionname].BindEnd(del);
else
throw new ArgumentException("Could not bind " + m.ReflectedType.Name + "." + m.Name + " to action \"" + actionname + "\", that action does not exist! Refer to, or edit Actions.cfg for all available application actions.");
}
}
}
// This binds a delegate manually
internal void BindBeginDelegate(Assembly asm, ActionDelegate d, BeginActionAttribute a)
{
string actionname;
// Make proper name
actionname = a.GetFullActionName(asm);
// Bind delegate to action
if(Exists(actionname))
actions[actionname].BindBegin(d);
else
General.WriteLogLine("WARNING: Could not bind delegate for " + d.Method.Name + " to action \"" + a.ActionName + "\" (" + actionname + "), that action does not exist! Refer to, or edit Actions.cfg for all available application actions.");
}
// This binds a delegate manually
internal void BindEndDelegate(Assembly asm, ActionDelegate d, EndActionAttribute a)
{
string actionname;
// Make proper name
actionname = a.GetFullActionName(asm);
// Bind delegate to action
if(Exists(actionname))
actions[actionname].BindEnd(d);
else
General.WriteLogLine("WARNING: Could not bind delegate for " + d.Method.Name + " to action \"" + a.ActionName + "\" (" + actionname + "), that action does not exist! Refer to, or edit Actions.cfg for all available application actions.");
}
// This unbinds all methods marked with this attribute
internal void UnbindMethods(Type type)
{
// Unbind static methods
UnbindMethods(null, type);
}
// This unbinds all methods marked with this attribute
internal void UnbindMethods(object obj)
{
// Unbind instance methods
UnbindMethods(obj, obj.GetType());
}
// This unbinds all methods marked with this attribute
private void UnbindMethods(object obj, Type type)
{
MethodInfo[] methods;
ActionAttribute[] attrs;
ActionDelegate del;
string actionname;
if(obj == null)
General.WriteLogLine("Unbinding static action methods for class " + type.Name + "...");
else
General.WriteLogLine("Unbinding action methods for " + type.Name + " object...");
// Go for all methods on obj
methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
foreach(MethodInfo m in methods)
{
// Check if the method has this attribute
attrs = (ActionAttribute[])m.GetCustomAttributes(typeof(BeginActionAttribute), true);
// Go for all attributes
foreach(ActionAttribute a in attrs)
{
// Create a delegate for this method
del = (ActionDelegate)Delegate.CreateDelegate(typeof(ActionDelegate), obj, m);
// Make proper name
actionname = a.GetFullActionName(type.Assembly);
// Unbind method from action
actions[actionname].UnbindBegin(del);
}
// Check if the method has this attribute
attrs = (ActionAttribute[])m.GetCustomAttributes(typeof(EndActionAttribute), true);
// Go for all attributes
foreach(ActionAttribute a in attrs)
{
// Create a delegate for this method
del = (ActionDelegate)Delegate.CreateDelegate(typeof(ActionDelegate), obj, m);
// Make proper name
actionname = a.GetFullActionName(type.Assembly);
// Unbind method from action
actions[actionname].UnbindEnd(del);
}
}
}
// This unbinds a delegate manually
internal void UnbindBeginDelegate(Assembly asm, ActionDelegate d, BeginActionAttribute a)
{
string actionname;
// Make proper name
actionname = a.GetFullActionName(asm);
// Unbind delegate to action
actions[actionname].UnbindBegin(d);
}
// This unbinds a delegate manually
internal void UnbindEndDelegate(Assembly asm, ActionDelegate d, EndActionAttribute a)
{
string actionname;
// Make proper name
actionname = a.GetFullActionName(asm);
// Unbind delegate to action
actions[actionname].UnbindEnd(d);
}
// This checks if a given action exists // This checks if a given action exists
public bool Exists(string action) public bool Exists(string action)
@ -190,7 +392,21 @@ namespace CodeImp.DoomBuilder.Controls
#endregion #endregion
#region ================== Shortcut Keys #region ================== Shortcut Keys
// This checks if a given action is active
public bool CheckActionActive(Assembly asm, string actionname)
{
// Find active action
string fullname = asm.GetName().Name.ToLowerInvariant() + "_" + actionname;
foreach(Action a in activeactions)
{
if(a.Name == fullname) return true;
}
// No such active action
return false;
}
// Removes all shortcut keys // Removes all shortcut keys
public void RemoveShortcutKeys() public void RemoveShortcutKeys()
{ {
@ -199,23 +415,95 @@ namespace CodeImp.DoomBuilder.Controls
a.Value.SetShortcutKey(0); a.Value.SetShortcutKey(0);
} }
// This notifies a key has been pressed
public void KeyPressed(int key)
{
int strippedkey = key & ~((int)Keys.Alt | (int)Keys.Shift | (int)Keys.Control);
if((strippedkey == (int)Keys.ShiftKey) || (strippedkey == (int)Keys.ControlKey)) key = strippedkey;
bool repeat = pressedkeys.Contains(strippedkey);
// Invoke event
BeginActionByKey(key, repeat);
Action[] acts = GetActionsByKey(key);
foreach(Action a in acts) if(!activeactions.Contains(a)) activeactions.Add(a);
// Update pressed keys
if(!repeat) pressedkeys.Add(strippedkey);
}
// This notifies a key has been released
public void KeyReleased(int key)
{
int strippedkey = key & ~((int)Keys.Alt | (int)Keys.Shift | (int)Keys.Control);
List<Action> keepactions = new List<Action>();
// Update pressed keys
if(pressedkeys.Contains(strippedkey)) pressedkeys.Remove(strippedkey);
// End actions that no longer match
EndActiveActions();
}
// This updates the modifiers
public void UpdateModifiers(int mods)
{
// Update modifiers
modifiers = mods;
// End actions that no longer match
EndActiveActions();
}
// This will call the associated actions for a keypress // This will call the associated actions for a keypress
public void InvokeByKey(int key) private void BeginActionByKey(int key, bool repeated)
{ {
// Go for all actions // Go for all actions
foreach(KeyValuePair<string, Action> a in actions) foreach(KeyValuePair<string, Action> a in actions)
{ {
// This action is associated with this key? // This action is associated with this key?
if(a.Value.ShortcutKey == key) if(a.Value.KeyMatches(key) && (a.Value.Repeat || !repeated))
{ {
// Invoke action // Invoke action
a.Value.Invoke(); a.Value.Begin();
} }
} }
} }
// This will end active actions for which the pressed keys do not match
private void EndActiveActions()
{
List<Action> keepactions = new List<Action>();
// Go for all active actions
foreach(Action a in activeactions)
{
// Go for all pressed keys
bool stillactive = false;
foreach(int k in pressedkeys)
{
if((k == (int)Keys.ShiftKey) || (k == (int)Keys.ControlKey))
stillactive |= a.KeyMatches(k);
else
stillactive |= a.KeyMatches(k | modifiers);
}
// End the action if no longer matches any of the keys
if(!stillactive)
{
a.End();
}
else
{
keepactions.Add(a);
}
}
// Update list of activate actions
activeactions = keepactions;
}
// This returns all action names for a given key // This returns all action names for a given key
public string[] GetActionsByKey(int key) public string[] GetActionNamesByKey(int key)
{ {
List<string> actionnames = new List<string>(); List<string> actionnames = new List<string>();
@ -223,7 +511,7 @@ namespace CodeImp.DoomBuilder.Controls
foreach(KeyValuePair<string, Action> a in actions) foreach(KeyValuePair<string, Action> a in actions)
{ {
// This action is associated with this key? // This action is associated with this key?
if(a.Value.ShortcutKey == key) if(a.Value.KeyMatches(key))
{ {
// List short name // List short name
actionnames.Add(a.Value.ShortName); actionnames.Add(a.Value.ShortName);
@ -233,6 +521,26 @@ namespace CodeImp.DoomBuilder.Controls
// Return result; // Return result;
return actionnames.ToArray(); return actionnames.ToArray();
} }
// This returns all action names for a given key
public Action[] GetActionsByKey(int key)
{
List<Action> actionnames = new List<Action>();
// Go for all actions
foreach(KeyValuePair<string, Action> a in actions)
{
// This action is associated with this key?
if(a.Value.KeyMatches(key))
{
// List short name
actionnames.Add(a.Value);
}
}
// Return result;
return actionnames.ToArray();
}
#endregion #endregion
} }

View file

@ -0,0 +1,43 @@
#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.ComponentModel;
using System.Drawing;
using System.Text;
using System.Reflection;
#endregion
namespace CodeImp.DoomBuilder.Controls
{
/// <summary>
/// This binds a method to an action which is then called when the action is started.
/// </summary>
public class BeginActionAttribute : ActionAttribute
{
/// <summary>
/// This binds a method to an action which is then called when the action is started.
/// </summary>
/// <param name="action">The action name as defined in Actions.cfg resource.</param>
public BeginActionAttribute(string action) : base(action)
{
}
}
}

View file

@ -0,0 +1,43 @@
#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.ComponentModel;
using System.Drawing;
using System.Text;
using System.Reflection;
#endregion
namespace CodeImp.DoomBuilder.Controls
{
/// <summary>
/// This binds a method to an action which is then called when the action is stopped.
/// </summary>
public class EndActionAttribute : ActionAttribute
{
/// <summary>
/// This binds a method to an action which is then called when the action is stopped.
/// </summary>
/// <param name="action">The action name as defined in Actions.cfg resource.</param>
public EndActionAttribute(string action) : base(action)
{
}
}
}

View file

@ -109,7 +109,7 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Scroll / Zoom #region ================== Scroll / Zoom
// This scrolls the view north // This scrolls the view north
[Action("scrollnorth", BaseAction = true)] [BeginAction("scrollnorth", BaseAction = true)]
public virtual void ScrollNorth() public virtual void ScrollNorth()
{ {
// Scroll // Scroll
@ -117,7 +117,7 @@ namespace CodeImp.DoomBuilder.Editing
} }
// This scrolls the view south // This scrolls the view south
[Action("scrollsouth", BaseAction = true)] [BeginAction("scrollsouth", BaseAction = true)]
public virtual void ScrollSouth() public virtual void ScrollSouth()
{ {
// Scroll // Scroll
@ -125,7 +125,7 @@ namespace CodeImp.DoomBuilder.Editing
} }
// This scrolls the view west // This scrolls the view west
[Action("scrollwest", BaseAction = true)] [BeginAction("scrollwest", BaseAction = true)]
public virtual void ScrollWest() public virtual void ScrollWest()
{ {
// Scroll // Scroll
@ -133,7 +133,7 @@ namespace CodeImp.DoomBuilder.Editing
} }
// This scrolls the view east // This scrolls the view east
[Action("scrolleast", BaseAction = true)] [BeginAction("scrolleast", BaseAction = true)]
public virtual void ScrollEast() public virtual void ScrollEast()
{ {
// Scroll // Scroll
@ -141,7 +141,7 @@ namespace CodeImp.DoomBuilder.Editing
} }
// This zooms in // This zooms in
[Action("zoomin", BaseAction = true)] [BeginAction("zoomin", BaseAction = true)]
public virtual void ZoomIn() public virtual void ZoomIn()
{ {
// Zoom // Zoom
@ -149,7 +149,7 @@ namespace CodeImp.DoomBuilder.Editing
} }
// This zooms out // This zooms out
[Action("zoomout", BaseAction = true)] [BeginAction("zoomout", BaseAction = true)]
public virtual void ZoomOut() public virtual void ZoomOut()
{ {
// Zoom // Zoom
@ -232,7 +232,7 @@ namespace CodeImp.DoomBuilder.Editing
} }
// This zooms and scrolls to fit the map in the window // This zooms and scrolls to fit the map in the window
[Action("centerinscreen", BaseAction = true)] [BeginAction("centerinscreen", BaseAction = true)]
public void CenterInScreen() public void CenterInScreen()
{ {
float left = float.MaxValue; float left = float.MaxValue;
@ -318,8 +318,7 @@ namespace CodeImp.DoomBuilder.Editing
General.MainWindow.UpdateCoordinates(mousemappos); General.MainWindow.UpdateCoordinates(mousemappos);
// Holding a button? // Holding a button?
if((e.Button == EditMode.EDIT_BUTTON) || if(e.Button != MouseButtons.None)
(e.Button == EditMode.SELECT_BUTTON))
{ {
// Not dragging? // Not dragging?
if(mousedragging == MouseButtons.None) if(mousedragging == MouseButtons.None)
@ -337,7 +336,7 @@ namespace CodeImp.DoomBuilder.Editing
} }
// Selecting? // Selecting?
if(selecting) UpdateSelection(); if(selecting) UpdateMultiSelection();
// Let the base class know // Let the base class know
base.MouseMove(e); base.MouseMove(e);
@ -364,24 +363,23 @@ namespace CodeImp.DoomBuilder.Editing
DragStop(e); DragStop(e);
mousedragging = MouseButtons.None; mousedragging = MouseButtons.None;
} }
// Selection stops
if(selecting) EndSelection();
// Let the base class know // Let the base class know
base.MouseUp(e); base.MouseUp(e);
} }
// This is called when the mouse is moved enough pixels and holding one or more buttons /// <summary>
/// Automatically called when dragging operation starts.
/// </summary>
protected virtual void DragStart(MouseEventArgs e) protected virtual void DragStart(MouseEventArgs e)
{ {
} }
// This is called when a drag is ended because the mouse buton is released /// <summary>
/// Automatically called when dragging operation stops.
/// </summary>
protected virtual void DragStop(MouseEventArgs e) protected virtual void DragStop(MouseEventArgs e)
{ {
} }
#endregion #endregion
@ -398,23 +396,85 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Methods #region ================== Methods
// Cancelling /// <summary>
/// Automatically called by the core when this editing mode is engaged.
/// </summary>
public override void Engage()
{
// Clear display overlay
renderer.StartOverlay(true);
renderer.Finish();
base.Engage();
}
/// <summary>
/// Called when the user requests to cancel this editing mode.
/// </summary>
public override void Cancel() public override void Cancel()
{ {
cancelled = true; cancelled = true;
base.Cancel(); base.Cancel();
} }
// This starts a selection /// <summary>
protected virtual void StartSelection() /// 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 Edit()
{
}
/// <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 EndEdit()
{
}
/// <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 Select()
{
}
/// <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 EndSelect()
{
if(selecting) EndMultiSelection();
}
/// <summary>
/// This is called automatically when a rectangular multi-selection ends.
/// </summary>
protected virtual void EndMultiSelection()
{
selecting = false;
}
/// <summary>
/// Call this to initiate a rectangular multi-selection.
/// </summary>
protected virtual void StartMultiSelection()
{ {
selecting = true; selecting = true;
selectstart = mousemappos; selectstart = mousemappos;
selectionrect = new RectangleF(selectstart.x, selectstart.y, 0, 0); selectionrect = new RectangleF(selectstart.x, selectstart.y, 0, 0);
} }
// This updates a selection /// <summary>
protected virtual void UpdateSelection() /// This is called automatically when a multi-selection is updated.
/// </summary>
protected virtual void UpdateMultiSelection()
{ {
selectionrect.X = selectstart.x; selectionrect.X = selectstart.x;
selectionrect.Y = selectstart.y; selectionrect.Y = selectstart.y;
@ -434,15 +494,11 @@ namespace CodeImp.DoomBuilder.Editing
} }
} }
// This is called when a selection is released /// <summary>
protected virtual void EndSelection() /// Call this to draw the selection on the overlay layer.
{ /// Must call renderer.StartOverlay first!
selecting = false; /// </summary>
} protected virtual void RenderMultiSelection()
// This draws the selection on the overlay layer
// Must call renderer.StartOverlay first!
protected virtual void RenderSelection()
{ {
renderer.RenderRectangle(selectionrect, SELECTION_BORDER_SIZE, renderer.RenderRectangle(selectionrect, SELECTION_BORDER_SIZE,
General.Colors.Highlight.WithAlpha(SELECTION_ALPHA), true); General.Colors.Highlight.WithAlpha(SELECTION_ALPHA), true);

View file

@ -44,8 +44,6 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Constants #region ================== Constants
public const int DRAG_START_MOVE_PIXELS = 5; public const int DRAG_START_MOVE_PIXELS = 5;
public const MouseButtons EDIT_BUTTON = MouseButtons.Right;
public const MouseButtons SELECT_BUTTON = MouseButtons.Left;
#endregion #endregion
@ -133,18 +131,18 @@ namespace CodeImp.DoomBuilder.Editing
public virtual void Engage() public virtual void Engage()
{ {
// Bind any methods // Bind any methods
ActionAttribute.BindMethods(this); General.Actions.BindMethods(this);
} }
// Mode disengages // Mode disengages
public virtual void Disengage() public virtual void Disengage()
{ {
// Unbind any methods // Unbind any methods
ActionAttribute.UnbindMethods(this); General.Actions.UnbindMethods(this);
} }
// This forces the mode to cancel and return to the "parent" mode // This forces the mode to cancel and return to the "parent" mode
[Action("cancelmode", BaseAction = true)] [BeginAction("cancelmode", BaseAction = true)]
public virtual void Cancel() { } public virtual void Cancel() { }
// Optional interface methods // Optional interface methods

View file

@ -46,7 +46,7 @@ namespace CodeImp.DoomBuilder.Editing
private bool configspecific; private bool configspecific;
// Mode switching // Mode switching
private ActionAttribute switchactionattr = null; private BeginActionAttribute switchactionattr = null;
private ActionDelegate switchactiondel = null; private ActionDelegate switchactiondel = null;
// Mode button // Mode button
@ -61,7 +61,7 @@ namespace CodeImp.DoomBuilder.Editing
public Plugin Plugin { get { return plugin; } } public Plugin Plugin { get { return plugin; } }
public Type Type { get { return type; } } public Type Type { get { return type; } }
public ActionAttribute SwitchAction { get { return switchactionattr; } } public BeginActionAttribute SwitchAction { get { return switchactionattr; } }
public Image ButtonImage { get { return buttonimage; } } public Image ButtonImage { get { return buttonimage; } }
public string ButtonDesc { get { return buttondesc; } } public string ButtonDesc { get { return buttondesc; } }
public bool ConfigSpecific { get { return configspecific; } } public bool ConfigSpecific { get { return configspecific; } }
@ -81,11 +81,11 @@ namespace CodeImp.DoomBuilder.Editing
// Make switch action info // Make switch action info
if((attr.SwitchAction != null) && (attr.SwitchAction.Length > 0)) if((attr.SwitchAction != null) && (attr.SwitchAction.Length > 0))
{ {
switchactionattr = new ActionAttribute(attr.SwitchAction); switchactionattr = new BeginActionAttribute(attr.SwitchAction);
switchactiondel = new ActionDelegate(SwitchToMode); switchactiondel = new ActionDelegate(SwitchToMode);
// Bind switch action // Bind switch action
ActionAttribute.BindDelegate(plugin.Assembly, switchactiondel, switchactionattr); General.Actions.BindBeginDelegate(plugin.Assembly, switchactiondel, switchactionattr);
} }
// Make button info // Make button info
@ -108,7 +108,7 @@ namespace CodeImp.DoomBuilder.Editing
public void Dispose() public void Dispose()
{ {
// Unbind switch action // Unbind switch action
if(switchactiondel != null) ActionAttribute.UnbindDelegate(plugin.Assembly, switchactiondel, switchactionattr); if(switchactiondel != null) General.Actions.UnbindBeginDelegate(plugin.Assembly, switchactiondel, switchactionattr);
buttonimage.Dispose(); buttonimage.Dispose();
buttonimagestream.Dispose(); buttonimagestream.Dispose();

View file

@ -78,7 +78,7 @@ namespace CodeImp.DoomBuilder.Editing
redos = new List<UndoSnapshot>(General.Settings.UndoLevels + 1); redos = new List<UndoSnapshot>(General.Settings.UndoLevels + 1);
// Bind any methods // Bind any methods
ActionAttribute.BindMethods(this); General.Actions.BindMethods(this);
// We have no destructor // We have no destructor
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
@ -91,7 +91,7 @@ namespace CodeImp.DoomBuilder.Editing
if(!isdisposed) if(!isdisposed)
{ {
// Unbind any methods // Unbind any methods
ActionAttribute.UnbindMethods(this); General.Actions.UnbindMethods(this);
// Clean up // Clean up
ClearUndos(); ClearUndos();
@ -199,7 +199,7 @@ namespace CodeImp.DoomBuilder.Editing
} }
// This performs an undo // This performs an undo
[Action("undo")] [BeginAction("undo")]
public void PerformUndo() public void PerformUndo()
{ {
UndoSnapshot u, r; UndoSnapshot u, r;
@ -235,7 +235,7 @@ namespace CodeImp.DoomBuilder.Editing
} }
// This performs a redo // This performs a redo
[Action("redo")] [BeginAction("redo")]
public void PerformRedo() public void PerformRedo()
{ {
UndoSnapshot u, r; UndoSnapshot u, r;

View file

@ -184,6 +184,7 @@ namespace CodeImp.DoomBuilder.Editing
base.KeyDown(e); base.KeyDown(e);
/* WRONG
// Get the actions for this key // Get the actions for this key
actions = General.Actions.GetActionsByKey((int)e.KeyData); actions = General.Actions.GetActionsByKey((int)e.KeyData);
foreach(string a in actions) foreach(string a in actions)
@ -197,6 +198,7 @@ namespace CodeImp.DoomBuilder.Editing
case "moveright": keyright = true; break; case "moveright": keyright = true; break;
} }
} }
*/
} }
// Key up // Key up
@ -206,6 +208,7 @@ namespace CodeImp.DoomBuilder.Editing
base.KeyUp(e); base.KeyUp(e);
/* WRONG
// Get the actions for this key // Get the actions for this key
actions = General.Actions.GetActionsByKey((int)e.KeyData); actions = General.Actions.GetActionsByKey((int)e.KeyData);
foreach(string a in actions) foreach(string a in actions)
@ -219,6 +222,7 @@ namespace CodeImp.DoomBuilder.Editing
case "moveright": keyright = false; break; case "moveright": keyright = false; break;
} }
} }
*/
} }
#endregion #endregion

View file

@ -436,7 +436,7 @@ namespace CodeImp.DoomBuilder
actions = new ActionManager(); actions = new ActionManager();
// Bind static methods to actions // Bind static methods to actions
ActionAttribute.BindMethods(typeof(General)); General.Actions.BindMethods(typeof(General));
// Create main window // Create main window
General.WriteLogLine("Loading main interface window..."); General.WriteLogLine("Loading main interface window...");
@ -504,7 +504,7 @@ namespace CodeImp.DoomBuilder
General.WriteLogLine("Termination requested"); General.WriteLogLine("Termination requested");
// Unbind static methods from actions // Unbind static methods from actions
ActionAttribute.UnbindMethods(typeof(General)); General.Actions.UnbindMethods(typeof(General));
// Clean up // Clean up
if(map != null) map.Dispose(); if(map != null) map.Dispose();
@ -545,7 +545,7 @@ namespace CodeImp.DoomBuilder
#region ================== Management #region ================== Management
// This creates a new map // This creates a new map
[Action("newmap")] [BeginAction("newmap")]
internal static void NewMap() internal static void NewMap()
{ {
MapOptions newoptions = new MapOptions(); MapOptions newoptions = new MapOptions();
@ -594,7 +594,7 @@ namespace CodeImp.DoomBuilder
} }
// This closes the current map // This closes the current map
[Action("closemap")] [BeginAction("closemap")]
internal static void CloseMap() internal static void CloseMap()
{ {
// Ask the user to save changes (if any) // Ask the user to save changes (if any)
@ -622,7 +622,7 @@ namespace CodeImp.DoomBuilder
} }
// This loads a map from file // This loads a map from file
[Action("openmap")] [BeginAction("openmap")]
internal static void OpenMap() internal static void OpenMap()
{ {
OpenFileDialog openfile; OpenFileDialog openfile;
@ -694,7 +694,7 @@ namespace CodeImp.DoomBuilder
} }
// This saves the current map // This saves the current map
[Action("savemap")] [BeginAction("savemap")]
internal static void SaveMap() internal static void SaveMap()
{ {
// Check if a wad file is known // Check if a wad file is known
@ -724,7 +724,7 @@ namespace CodeImp.DoomBuilder
} }
// This saves the current map as a different file // This saves the current map as a different file
[Action("savemapas")] [BeginAction("savemapas")]
internal static void SaveMapAs() internal static void SaveMapAs()
{ {
SaveFileDialog savefile; SaveFileDialog savefile;
@ -1011,7 +1011,7 @@ namespace CodeImp.DoomBuilder
#endregion #endregion
[Action("testaction")] [BeginAction("testaction")]
internal static void TestAction() internal static void TestAction()
{ {
TextureBrowserForm t = new TextureBrowserForm(); TextureBrowserForm t = new TextureBrowserForm();

View file

@ -114,7 +114,7 @@ namespace CodeImp.DoomBuilder
{ {
// We have no destructor // We have no destructor
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
// Basic objects // Basic objects
grid = new GridSetup(); grid = new GridSetup();
undoredo = new UndoManager(); undoredo = new UndoManager();
@ -130,7 +130,7 @@ namespace CodeImp.DoomBuilder
ChangeMode((EditMode)null); ChangeMode((EditMode)null);
// Unbind any methods // Unbind any methods
ActionAttribute.UnbindMethods(this); General.Actions.UnbindMethods(this);
// Dispose // Dispose
if(undoredo != null) undoredo.Dispose(); if(undoredo != null) undoredo.Dispose();
@ -222,7 +222,7 @@ namespace CodeImp.DoomBuilder
data.Load(configinfo.Resources, options.Resources); data.Load(configinfo.Resources, options.Resources);
// Bind any methods // Bind any methods
ActionAttribute.BindMethods(this); General.Actions.BindMethods(this);
// Set default mode // Set default mode
ChangeMode("VerticesMode"); ChangeMode("VerticesMode");
@ -309,7 +309,7 @@ namespace CodeImp.DoomBuilder
data.Load(configinfo.Resources, options.Resources, maplocation); data.Load(configinfo.Resources, options.Resources, maplocation);
// Bind any methods // Bind any methods
ActionAttribute.BindMethods(this); General.Actions.BindMethods(this);
// Set default mode // Set default mode
ChangeMode("VerticesMode"); ChangeMode("VerticesMode");
@ -877,7 +877,7 @@ namespace CodeImp.DoomBuilder
#region ================== Methods #region ================== Methods
// This clears the selection // This clears the selection
[Action("clearselection")] [BeginAction("clearselection")]
public void ClearSelection() public void ClearSelection()
{ {
// Clear selection // Clear selection
@ -900,7 +900,7 @@ namespace CodeImp.DoomBuilder
} }
// This reloads resources // This reloads resources
[Action("reloadresources")] [BeginAction("reloadresources")]
internal void ReloadResources() internal void ReloadResources()
{ {
DataLocation maplocation; DataLocation maplocation;
@ -946,7 +946,7 @@ namespace CodeImp.DoomBuilder
} }
// Game Configuration action // Game Configuration action
[Action("mapoptions")] [BeginAction("mapoptions")]
internal void ShowMapOptions() internal void ShowMapOptions()
{ {
// Show map options dialog // Show map options dialog

View file

@ -65,5 +65,6 @@ namespace CodeImp.DoomBuilder.Interface
void SetProcessorState(bool on); void SetProcessorState(bool on);
void StartExclusiveMouseInput(); void StartExclusiveMouseInput();
void StopExclusiveMouseInput(); void StopExclusiveMouseInput();
bool CheckActionActive(Assembly assembly, string actionname);
} }
} }

View file

@ -30,6 +30,8 @@ using CodeImp.DoomBuilder.Editing;
using System.Collections; using System.Collections;
using System.IO; using System.IO;
using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Map;
using System.Reflection;
using CodeImp.DoomBuilder.Plugins;
#endregion #endregion
@ -102,7 +104,7 @@ namespace CodeImp.DoomBuilder.Interface
buttongrid.DropDownDirection = ToolStripDropDownDirection.AboveLeft; buttongrid.DropDownDirection = ToolStripDropDownDirection.AboveLeft;
// Bind any methods // Bind any methods
ActionAttribute.BindMethods(this); General.Actions.BindMethods(this);
// Apply shortcut keys // Apply shortcut keys
ApplyShortcutKeys(); ApplyShortcutKeys();
@ -154,7 +156,7 @@ namespace CodeImp.DoomBuilder.Interface
this.Update(); this.Update();
asmname = General.ThisAssembly.GetName().Name.ToLowerInvariant(); asmname = General.ThisAssembly.GetName().Name.ToLowerInvariant();
General.Actions[asmname + "_" + (sender as ToolStripItem).Tag.ToString()].Invoke(); General.Actions[asmname + "_" + (sender as ToolStripItem).Tag.ToString()].Begin();
this.Update(); this.Update();
} }
@ -227,7 +229,7 @@ namespace CodeImp.DoomBuilder.Interface
SetProcessorState(false); SetProcessorState(false);
// Unbind methods // Unbind methods
ActionAttribute.UnbindMethods(this); General.Actions.UnbindMethods(this);
// Determine window state to save // Determine window state to save
if(this.WindowState != FormWindowState.Minimized) if(this.WindowState != FormWindowState.Minimized)
@ -467,7 +469,7 @@ namespace CodeImp.DoomBuilder.Interface
} }
// This shows the grid setup dialog // This shows the grid setup dialog
[Action("gridsetup")] [BeginAction("gridsetup")]
internal void ShowGridSetup() internal void ShowGridSetup()
{ {
// Only when a map is open // Only when a map is open
@ -573,7 +575,7 @@ namespace CodeImp.DoomBuilder.Interface
this.Update(); this.Update();
modeinfo = (EditModeInfo)((sender as ToolStripItem).Tag); modeinfo = (EditModeInfo)((sender as ToolStripItem).Tag);
General.Actions[modeinfo.SwitchAction.GetFullActionName(modeinfo.Plugin.Assembly)].Invoke(); General.Actions[modeinfo.SwitchAction.GetFullActionName(modeinfo.Plugin.Assembly)].Begin();
this.Update(); this.Update();
} }
@ -671,7 +673,26 @@ namespace CodeImp.DoomBuilder.Interface
private void display_MouseDoubleClick(object sender, MouseEventArgs e) { if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.MouseDoubleClick(e); } private void display_MouseDoubleClick(object sender, MouseEventArgs e) { if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.MouseDoubleClick(e); }
// Mouse down // Mouse down
private void display_MouseDown(object sender, MouseEventArgs e) { if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.MouseDown(e); } private void display_MouseDown(object sender, MouseEventArgs e)
{
int key = 0;
// Create key
switch(e.Button)
{
case MouseButtons.Left: key = (int)Keys.LButton; break;
case MouseButtons.Middle: key = (int)Keys.MButton; break;
case MouseButtons.Right: key = (int)Keys.RButton; break;
case MouseButtons.XButton1: key = (int)Keys.XButton1; break;
case MouseButtons.XButton2: key = (int)Keys.XButton2; break;
}
// Invoke any actions associated with this key
General.Actions.KeyPressed(key);
// Invoke on editing mode
if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.MouseDown(e);
}
// Mouse enters // Mouse enters
private void display_MouseEnter(object sender, EventArgs e) private void display_MouseEnter(object sender, EventArgs e)
@ -694,12 +715,40 @@ namespace CodeImp.DoomBuilder.Interface
} }
// Mouse up // Mouse up
private void display_MouseUp(object sender, MouseEventArgs e) { if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.MouseUp(e); } private void display_MouseUp(object sender, MouseEventArgs e)
{
int key = 0;
// Create key
switch(e.Button)
{
case MouseButtons.Left: key = (int)Keys.LButton; break;
case MouseButtons.Middle: key = (int)Keys.MButton; break;
case MouseButtons.Right: key = (int)Keys.RButton; break;
case MouseButtons.XButton1: key = (int)Keys.XButton1; break;
case MouseButtons.XButton2: key = (int)Keys.XButton2; break;
}
// Invoke any actions associated with this key
General.Actions.KeyReleased(key);
// Invoke on editing mode
if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.MouseUp(e);
}
#endregion #endregion
#region ================== Input #region ================== Input
// This checks if a given action is active
public bool CheckActionActive(Assembly assembly, string actionname)
{
if(assembly == null)
return General.Actions.CheckActionActive(General.ThisAssembly, actionname);
else
return General.Actions.CheckActionActive(assembly, actionname);
}
// This requests exclusive mouse input // This requests exclusive mouse input
public void StartExclusiveMouseInput() public void StartExclusiveMouseInput()
{ {
@ -739,26 +788,21 @@ namespace CodeImp.DoomBuilder.Interface
// When the mouse wheel is changed // When the mouse wheel is changed
protected override void OnMouseWheel(MouseEventArgs e) protected override void OnMouseWheel(MouseEventArgs e)
{ {
int mod = 0;
// Create modifiers
if(alt) mod |= (int)Keys.Alt;
if(shift) mod |= (int)Keys.Shift;
if(ctrl) mod |= (int)Keys.Control;
// Scrollwheel up? // Scrollwheel up?
if(e.Delta > 0) if(e.Delta > 0)
{ {
// Invoke actions for scrollwheel // Invoke actions for scrollwheel
//for(int i = 0; i < e.Delta; i += 120) //for(int i = 0; i < e.Delta; i += 120)
General.Actions.InvokeByKey(mod | (int)SpecialKeys.MScrollUp); General.Actions.KeyPressed((int)SpecialKeys.MScrollUp);
General.Actions.KeyReleased((int)SpecialKeys.MScrollUp);
} }
// Scrollwheel down? // Scrollwheel down?
else if(e.Delta < 0) else if(e.Delta < 0)
{ {
// Invoke actions for scrollwheel // Invoke actions for scrollwheel
//for(int i = 0; i > e.Delta; i -= 120) //for(int i = 0; i > e.Delta; i -= 120)
General.Actions.InvokeByKey(mod | (int)SpecialKeys.MScrollDown); General.Actions.KeyPressed((int)SpecialKeys.MScrollDown);
General.Actions.KeyReleased((int)SpecialKeys.MScrollDown);
} }
// Let the base know // Let the base know
@ -768,13 +812,19 @@ namespace CodeImp.DoomBuilder.Interface
// When a key is pressed // When a key is pressed
private void MainForm_KeyDown(object sender, KeyEventArgs e) private void MainForm_KeyDown(object sender, KeyEventArgs e)
{ {
int mod = 0;
// Keep key modifiers // Keep key modifiers
alt = e.Alt; alt = e.Alt;
shift = e.Shift; shift = e.Shift;
ctrl = e.Control; ctrl = e.Control;
if(alt) mod |= (int)Keys.Alt;
if(shift) mod |= (int)Keys.Shift;
if(ctrl) mod |= (int)Keys.Control;
// Invoke any actions associated with this key // Invoke any actions associated with this key
General.Actions.InvokeByKey((int)e.KeyData); General.Actions.UpdateModifiers(mod);
General.Actions.KeyPressed((int)e.KeyData);
// Invoke on editing mode // Invoke on editing mode
if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.KeyDown(e); if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.KeyDown(e);
@ -783,10 +833,19 @@ namespace CodeImp.DoomBuilder.Interface
// When a key is released // When a key is released
private void MainForm_KeyUp(object sender, KeyEventArgs e) private void MainForm_KeyUp(object sender, KeyEventArgs e)
{ {
int mod = 0;
// Keep key modifiers // Keep key modifiers
alt = e.Alt; alt = e.Alt;
shift = e.Shift; shift = e.Shift;
ctrl = e.Control; ctrl = e.Control;
if(alt) mod |= (int)Keys.Alt;
if(shift) mod |= (int)Keys.Shift;
if(ctrl) mod |= (int)Keys.Control;
// Invoke any actions associated with this key
General.Actions.UpdateModifiers(mod);
General.Actions.KeyReleased((int)e.KeyData);
// Invoke on editing mode // Invoke on editing mode
if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.KeyUp(e); if((General.Map != null) && (General.Map.Mode != null)) General.Map.Mode.KeyUp(e);
@ -1035,7 +1094,7 @@ namespace CodeImp.DoomBuilder.Interface
} }
// Action to toggle snap to grid // Action to toggle snap to grid
[Action("togglesnap")] [BeginAction("togglesnap")]
internal void ToggleSnapToGrid() internal void ToggleSnapToGrid()
{ {
buttonsnaptogrid.Checked = !buttonsnaptogrid.Checked; buttonsnaptogrid.Checked = !buttonsnaptogrid.Checked;
@ -1043,7 +1102,7 @@ namespace CodeImp.DoomBuilder.Interface
} }
// Action to toggle auto merge // Action to toggle auto merge
[Action("toggleautomerge")] [BeginAction("toggleautomerge")]
internal void ToggleAutoMerge() internal void ToggleAutoMerge()
{ {
buttonautomerge.Checked = !buttonautomerge.Checked; buttonautomerge.Checked = !buttonautomerge.Checked;
@ -1078,7 +1137,7 @@ namespace CodeImp.DoomBuilder.Interface
} }
// Game Configuration action // Game Configuration action
[Action("configuration")] [BeginAction("configuration")]
internal void ShowConfiguration() internal void ShowConfiguration()
{ {
// Show configuration dialog // Show configuration dialog
@ -1100,7 +1159,7 @@ namespace CodeImp.DoomBuilder.Interface
} }
// Preferences action // Preferences action
[Action("preferences")] [BeginAction("preferences")]
internal void ShowPreferences() internal void ShowPreferences()
{ {
// Show preferences dialog // Show preferences dialog

View file

@ -319,6 +319,14 @@ namespace CodeImp.DoomBuilder.Map
} }
} }
// This returns the closest coordinates ON the line
public Vector2D NearestOnLine(Vector2D pos)
{
float u = Line2D.GetNearestOnLine(start.Position, end.Position, pos);
if(u < 0f) u = 0f; else if(u > 1f) u = 1f;
return Line2D.GetCoordinatesAt(start.Position, end.Position, u);
}
// This returns the shortest distance from given coordinates to line // This returns the shortest distance from given coordinates to line
public float SafeDistanceToSq(Vector2D p, bool bounded) public float SafeDistanceToSq(Vector2D p, bool bounded)
{ {

View file

@ -23,6 +23,7 @@ using System.Globalization;
using System.Text; using System.Text;
using System.IO; using System.IO;
using CodeImp.DoomBuilder.Editing; using CodeImp.DoomBuilder.Editing;
using System.Reflection;
#endregion #endregion
@ -159,6 +160,19 @@ namespace CodeImp.DoomBuilder.Plugins
} }
} }
// This returns a plugin by assembly, or null when plugin cannot be found
public Plugin FindPluginByAssembly(Assembly assembly)
{
// Go for all plugins the find the one with matching assembly
foreach(Plugin p in plugins)
{
if(p.Assembly == assembly) return p;
}
// Nothing found
return null;
}
#endregion #endregion
} }
} }

View file

@ -45,7 +45,8 @@ namespace CodeImp.DoomBuilder.Rendering
float OffsetX { get; } float OffsetX { get; }
float OffsetY { get; } float OffsetY { get; }
float Scale { get; } float Scale { get; }
int VertexSize { get; }
// Color methods // Color methods
PixelColor DetermineLinedefColor(Linedef l); PixelColor DetermineLinedefColor(Linedef l);
PixelColor DetermineThingColor(Thing t); PixelColor DetermineThingColor(Thing t);
@ -72,6 +73,7 @@ namespace CodeImp.DoomBuilder.Rendering
void RenderThingSet(ICollection<Thing> things); void RenderThingSet(ICollection<Thing> things);
void RenderRectangle(RectangleF rect, float bordersize, PixelColor c, bool transformrect); void RenderRectangle(RectangleF rect, float bordersize, PixelColor c, bool transformrect);
void RenderRectangleFilled(RectangleF rect, PixelColor c, bool transformrect); void RenderRectangleFilled(RectangleF rect, PixelColor c, bool transformrect);
void RenderLine(Vector2D start, Vector2D end, float thickness, PixelColor c, bool transformcoords);
void RenderText(string text, Vector2D pos, PixelColor c, bool transformpos); void RenderText(string text, Vector2D pos, PixelColor c, bool transformpos);
void RenderTextCentered(string text, Vector2D pos, PixelColor c, bool transformpos); void RenderTextCentered(string text, Vector2D pos, PixelColor c, bool transformpos);
} }

View file

@ -61,7 +61,7 @@ namespace CodeImp.DoomBuilder.Rendering
private const byte DOUBLESIDED_LINE_ALPHA = 130; private const byte DOUBLESIDED_LINE_ALPHA = 130;
private const float FSAA_PLOTTER_BLEND_FACTOR = 0.6f; private const float FSAA_PLOTTER_BLEND_FACTOR = 0.6f;
private const float FSAA_OVERLAY_BLEND_FACTOR = 0.2f; private const float FSAA_OVERLAY_BLEND_FACTOR = 0.6f;
private const float THING_ARROW_SIZE = 1.5f; private const float THING_ARROW_SIZE = 1.5f;
private const float THING_ARROW_SHRINK = 2f; private const float THING_ARROW_SHRINK = 2f;
private const float THING_CIRCLE_SIZE = 1f; private const float THING_CIRCLE_SIZE = 1f;
@ -137,6 +137,7 @@ namespace CodeImp.DoomBuilder.Rendering
public float OffsetX { get { return offsetx; } } public float OffsetX { get { return offsetx; } }
public float OffsetY { get { return offsety; } } public float OffsetY { get { return offsety; } }
public float Scale { get { return scale; } } public float Scale { get { return scale; } }
public int VertexSize { get { return vertexsize; } }
#endregion #endregion
@ -1181,6 +1182,59 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Shaders.Color2D.End(); graphics.Shaders.Color2D.End();
} }
// This renders a line with given color
public void RenderLine(Vector2D start, Vector2D end, float thickness, PixelColor c, bool transformcoords)
{
FlatVertex[] verts = new FlatVertex[4];
// Calculate positions
if(transformcoords)
{
start = start.GetTransformed(translatex, translatey, scale, -scale);
end = end.GetTransformed(translatex, translatey, scale, -scale);
}
// Calculate offsets
Vector2D delta = end - start;
Vector2D dn = delta.GetNormal() * thickness;
// Make vertices
verts[0].x = start.x - dn.x + dn.y;
verts[0].y = start.y - dn.y - dn.x;
verts[0].z = 0.0f;
verts[0].w = 1.0f;
verts[0].c = c.ToInt();
verts[1].x = start.x - dn.x - dn.y;
verts[1].y = start.y - dn.y + dn.x;
verts[1].z = 0.0f;
verts[1].w = 1.0f;
verts[1].c = c.ToInt();
verts[2].x = end.x + dn.x + dn.y;
verts[2].y = end.y + dn.y - dn.x;
verts[2].z = 0.0f;
verts[2].w = 1.0f;
verts[2].c = c.ToInt();
verts[3].x = end.x + dn.x - dn.y;
verts[3].y = end.y + dn.y + dn.x;
verts[3].z = 0.0f;
verts[3].w = 1.0f;
verts[3].c = c.ToInt();
// Set renderstates for rendering
graphics.Device.SetRenderState(RenderState.CullMode, Cull.None);
graphics.Device.SetRenderState(RenderState.ZEnable, false);
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, false);
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false);
graphics.Device.SetRenderState(RenderState.TextureFactor, -1);
// Draw
graphics.Shaders.Color2D.Begin();
graphics.Shaders.Color2D.BeginPass(0);
graphics.Device.DrawUserPrimitives<FlatVertex>(PrimitiveType.TriangleStrip, 0, 2, verts);
graphics.Shaders.Color2D.EndPass();
graphics.Shaders.Color2D.End();
}
#endregion #endregion
#region ================== Geometry #region ================== Geometry

View file

@ -113,6 +113,24 @@ cancelmode
allowscroll = true; allowscroll = true;
} }
classicselect
{
title = "2D: Select";
description = "Selects the highlighted item. Also allows selection by drawing a rectangle.";
allowkeys = true;
allowmouse = true;
allowscroll = false;
}
classicedit
{
title = "2D: Edit";
description = "Edits the properties of the selected items or drags the selected items. Also initiates drawing or inserts new things when no selection is made.";
allowkeys = true;
allowmouse = true;
allowscroll = false;
}
scrollwest scrollwest
{ {
title = "2D: Scroll West"; title = "2D: Scroll West";
@ -120,6 +138,7 @@ scrollwest
allowkeys = true; allowkeys = true;
allowmouse = true; allowmouse = true;
allowscroll = true; allowscroll = true;
repeat = true;
} }
scrolleast scrolleast
@ -129,6 +148,7 @@ scrolleast
allowkeys = true; allowkeys = true;
allowmouse = true; allowmouse = true;
allowscroll = true; allowscroll = true;
repeat = true;
} }
scrollnorth scrollnorth
@ -138,6 +158,7 @@ scrollnorth
allowkeys = true; allowkeys = true;
allowmouse = true; allowmouse = true;
allowscroll = true; allowscroll = true;
repeat = true;
} }
scrollsouth scrollsouth
@ -147,6 +168,7 @@ scrollsouth
allowkeys = true; allowkeys = true;
allowmouse = true; allowmouse = true;
allowscroll = true; allowscroll = true;
repeat = true;
} }
zoomin zoomin
@ -156,6 +178,7 @@ zoomin
allowkeys = true; allowkeys = true;
allowmouse = true; allowmouse = true;
allowscroll = true; allowscroll = true;
repeat = true;
} }
zoomout zoomout
@ -165,6 +188,7 @@ zoomout
allowkeys = true; allowkeys = true;
allowmouse = true; allowmouse = true;
allowscroll = true; allowscroll = true;
repeat = true;
} }
centerinscreen centerinscreen