Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

733 - Add keyboard navigation in tile palette #764

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ private void DeselectToolInInspector()
if (this.selectedTool == null) return;
DualityEditorApp.Deselect(this, new ObjectSelection(new object[] { this.selectedTool.Settings }));
}

protected override string UpdateStatusText()
{
// Display which Tilemap we're currently using
Expand All @@ -630,6 +630,7 @@ protected override void OnEnterState()
DualityEditorApp.ObjectPropertyChanged += this.DualityEditorApp_ObjectPropertyChanged;
DualityEditorApp.UpdatingEngine += this.DualityEditorApp_UpdatingEngine;
Scene.Entered += this.Scene_Entered;
TilemapsEditorPlugin.Instance.TileDrawingSourceChanged += this.TilemapToolSourcePalette_SelectedAreaChanged;

// Initial update
this.UpdateTilemapToolButtons();
Expand Down Expand Up @@ -755,9 +756,9 @@ protected override void OnMouseUp(MouseEventArgs e)
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);

// Hotkeys for switching the currently selected tilemap
if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
if (e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown)
{
Tilemap[] visibleTilemaps =
this.QueryVisibleTilemapRenderers()
Expand All @@ -770,9 +771,9 @@ protected override void OnKeyDown(KeyEventArgs e)

if (visibleTilemaps.Length > 0)
{
if (e.KeyCode == Keys.Down)
if (e.KeyCode == Keys.PageDown)
selectedIndex = (selectedIndex == -1) ? (visibleTilemaps.Length - 1) : Math.Min(selectedIndex + 1, visibleTilemaps.Length - 1);
else if (e.KeyCode == Keys.Up)
else if (e.KeyCode == Keys.PageUp)
selectedIndex = (selectedIndex == -1) ? 0 : Math.Max(selectedIndex - 1, 0);

Tilemap newSelection = visibleTilemaps[selectedIndex];
Expand All @@ -782,7 +783,7 @@ protected override void OnKeyDown(KeyEventArgs e)
e.Handled = true;
return;
}
else if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
else if (e.KeyCode == Keys.Escape)
{
DualityEditorApp.Deselect(this, ObjectSelection.Category.GameObjCmp);
e.Handled = true;
Expand All @@ -805,11 +806,13 @@ protected override void OnKeyDown(KeyEventArgs e)
break;
}
}
TilemapsEditorPlugin.Instance.PeekTilePalette().RaiseKeyDownEvent(e);
}
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);

TilemapsEditorPlugin.Instance.PeekTilePalette().RaiseKeyUpEvent(e);

if (this.overrideTool != null && this.overrideTool.OverrideKey == e.KeyCode)
{
this.OverrideTool = null;
Expand Down Expand Up @@ -1041,6 +1044,12 @@ private void Scene_Entered(object sender, EventArgs e)
{
this.UpdateActionToolButtons();
}
private void TilemapToolSourcePalette_SelectedAreaChanged(object sender, EventArgs e)
{
this.activeTool.UpdatePreview();
this.Invalidate();
}

private void actionToolButton_Click(object sender, EventArgs e)
{
TilemapActionEntry clickedEntry = this.actions.FirstOrDefault(entry => entry.ToolButton == sender);
Expand Down
9 changes: 8 additions & 1 deletion Source/Plugins/Tilemaps/Editor/EditorPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,14 @@ public void PopTilePalette()
else
this.pendingLocalTilePalettes--;
}

/// <summary>
/// Gets the <see cref="TilemapToolSourcePalette"/> if there is one, returns null otherwise.
/// </summary>
public TilemapToolSourcePalette PeekTilePalette()
{
return this.tilePalette;
}

public TilesetEditor RequestTilesetEditor()
{
// Create a new tileset editor, if no is available right now
Expand Down
189 changes: 182 additions & 7 deletions Source/Plugins/Tilemaps/Editor/Modules/SourcePaletteTilesetView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

using Duality.Input;
using Duality.Resources;
using Duality.Plugins.Tilemaps;
using MouseEventArgs = System.Windows.Forms.MouseEventArgs;


namespace Duality.Editor.Plugins.Tilemaps
Expand All @@ -21,6 +22,17 @@ public class SourcePaletteTilesetView : TilesetView
private bool isUserScrolling = false;
private int lastMouseX = -1;
private int lastMouseY = -1;
private SelectionSide activeSelectionSide = SelectionSide.None;

private enum SelectionSide
{
None,
Right,
Left,
Up,
Down
}


public event EventHandler SelectedAreaChanged = null;
public event EventHandler SelectedAreaEditingFinished = null;
Expand Down Expand Up @@ -76,6 +88,14 @@ public IReadOnlyGrid<Tile> SelectedTiles
get { return this.selectedTiles; }
}

internal void RaiseKeyDownEvent(KeyEventArgs e)
{
this.OnKeyDown(e);
}
internal void RaiseKeyUpEvent(KeyEventArgs e)
{
this.OnKeyUp(e);
}

protected override void OnTilesetChanged()
{
Expand Down Expand Up @@ -203,7 +223,7 @@ protected override void OnPaintTiles(PaintEventArgs e)
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left && Control.ModifierKeys == Keys.Shift && !this.isUserScrolling)
if (e.Button == MouseButtons.Left && ModifierKeys == Keys.Shift && !this.isUserScrolling)
{
int tileIndex = this.PickTileIndexAt(e.X, e.Y);
if (tileIndex != -1)
Expand Down Expand Up @@ -333,6 +353,90 @@ protected override void OnMouseLeave(EventArgs e)
this.InvalidateTile(this.HoveredTileIndex, 5);
base.OnMouseLeave(e);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);

if (Control.ModifierKeys == Keys.Shift)
{
switch (e.KeyCode)
{
case Keys.Up when this.activeSelectionSide == SelectionSide.Down:
this.ShrinkSelectedArea(0, -1);
break;
case Keys.Up:
this.ExpandSelectedArea(0, -1);
this.activeSelectionSide = SelectionSide.Up;
break;
case Keys.Down when this.activeSelectionSide == SelectionSide.Up:
this.ShrinkSelectedArea(0, 1);
break;
case Keys.Down:
this.ExpandSelectedArea(0, 1);
this.activeSelectionSide = SelectionSide.Down;
break;
case Keys.Left when this.activeSelectionSide == SelectionSide.Right:
this.ShrinkSelectedArea(-1, 0);
break;
case Keys.Left:
this.ExpandSelectedArea(-1, 0);
this.activeSelectionSide = SelectionSide.Left;
break;
case Keys.Right when this.activeSelectionSide == SelectionSide.Left:
this.ShrinkSelectedArea(1, 0);
break;
case Keys.Right:
this.ExpandSelectedArea(1, 0);
this.activeSelectionSide = SelectionSide.Right;
break;
}
}
else
{
if (e.KeyCode == Keys.Up)
{
this.TranslateSelectedArea(0, -1);
}
if (e.KeyCode == Keys.Down)
{
this.TranslateSelectedArea(0, 1);
}
if (e.KeyCode == Keys.Left)
{
this.TranslateSelectedArea(-1, 0);
}
if (e.KeyCode == Keys.Right)
{
this.TranslateSelectedArea(1, 0);
}
this.activeSelectionSide = SelectionSide.None;
}
}

protected override void OnKeyUp(KeyEventArgs e)
{
if (e.KeyCode == Keys.ShiftKey)
{
this.activeSelectionSide = SelectionSide.None;
}
}
protected override bool IsInputKey(Keys keyData)
{
switch (keyData)
{
case Keys.Right:
case Keys.Left:
case Keys.Up:
case Keys.Down:
case Keys.Shift:
case Keys.Shift | Keys.Right:
case Keys.Shift | Keys.Left:
case Keys.Shift | Keys.Up:
case Keys.Shift | Keys.Down:
return true;
}
return base.IsInputKey(keyData);
}

private void UpdateSelectedTiles()
{
Expand All @@ -344,7 +448,7 @@ private void UpdateSelectedTiles()
// none to choose from. Keep the default-initialized ones we got above.
Tileset tileset = this.TargetTileset.Res;
if (tileset == null) return;

// Determine a tile rect based on the current selection inside the Tileset.
Point selectedDisplayedPos = this.GetDisplayedTilePos(
this.selectedArea.X,
Expand All @@ -367,16 +471,87 @@ private void UpdateSelectedTiles()
}
}
}
private void InitializeSelectedArea()
{
Rectangle rect = new Rectangle(0, 0, 1, 1);
this.SelectedArea = rect;
this.RaiseSelectedAreaEditingFinished();
}

private void RaiseSelectedAreaEditingFinished()
{
if (this.SelectedAreaEditingFinished != null)
this.SelectedAreaEditingFinished(this, EventArgs.Empty);
this.SelectedAreaEditingFinished?.Invoke(this, EventArgs.Empty);
}
private void RaiseSelectedAreaChanged()
{
if (this.SelectedAreaChanged != null)
this.SelectedAreaChanged(this, EventArgs.Empty);
this.SelectedAreaChanged?.Invoke(this, EventArgs.Empty);
}
private void TranslateSelectedArea(int offsetX, int offsetY)
{
if (this.selectedArea.IsEmpty)
{
this.InitializeSelectedArea();
return;
}

Rectangle prevSelectedArea = this.SelectedArea;

int newX = MathF.Clamp(prevSelectedArea.X + offsetX, 0, this.DisplayedTileCount.X - prevSelectedArea.Width);
int newY = MathF.Clamp(prevSelectedArea.Y + offsetY, 0, this.DisplayedTileCount.Y - prevSelectedArea.Height);

this.SelectedArea = new Rectangle(newX, newY, prevSelectedArea.Width, prevSelectedArea.Height);
this.RaiseSelectedAreaEditingFinished();
this.Invalidate();
}
private void ExpandSelectedArea(int diffX, int diffY)
{
if (this.selectedArea.IsEmpty)
{
this.InitializeSelectedArea();
return;
}

Rectangle prevSelectedArea = this.SelectedArea;

int newX = MathF.Max(prevSelectedArea.X + MathF.Min(diffX, 0), 0);
int newY = MathF.Max(prevSelectedArea.Y + MathF.Min(diffY, 0), 0);

int newWidth = prevSelectedArea.Width + MathF.Max(diffX, 0);
newWidth = MathF.Min(newWidth, this.DisplayedTileCount.X - prevSelectedArea.X);
newWidth += prevSelectedArea.X - newX;

int newHeight = prevSelectedArea.Height + MathF.Max(diffY, 0);
newHeight = MathF.Min(newHeight, this.DisplayedTileCount.Y - prevSelectedArea.Y);
newHeight += prevSelectedArea.Y - newY;

this.SelectedArea = new Rectangle(newX, newY, newWidth, newHeight);
this.RaiseSelectedAreaEditingFinished();
this.Invalidate();
}
private void ShrinkSelectedArea(int diffX, int diffY)
{
if (this.selectedArea.IsEmpty)
{
this.InitializeSelectedArea();
return;
}

Rectangle prevSelectedArea = this.SelectedArea;

int newX = MathF.Min(prevSelectedArea.X + MathF.Max(diffX, 0),
prevSelectedArea.X + prevSelectedArea.Width - 1);
int newY = MathF.Min(prevSelectedArea.Y + MathF.Max(diffY, 0),
prevSelectedArea.Y + prevSelectedArea.Height - 1);

int newWidth = MathF.Max(prevSelectedArea.Width + MathF.Min(diffX, 0), 1);
newWidth -= newX - prevSelectedArea.X;

int newHeight = MathF.Max(prevSelectedArea.Height + MathF.Min(diffY, 0), 1);
newHeight -= newY - prevSelectedArea.Y;

this.SelectedArea = new Rectangle(newX, newY, newWidth, newHeight);
this.RaiseSelectedAreaEditingFinished();
this.Invalidate();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public partial class TilemapToolSourcePalette : DockContent
private bool globalEventsSubscribed = false;
private TilesetView.TileIndexDrawMode tileIndexDrawMode = TilesetView.TileIndexDrawMode.Never;

public event EventHandler SelectedAreaChanged;

private ContentRef<Tileset> SelectedTileset
{
Expand All @@ -42,6 +43,18 @@ public TilemapToolSourcePalette()
this.InitializeComponent();
this.mainToolStrip.Renderer = new Duality.Editor.Controls.ToolStrip.DualitorToolStripProfessionalRenderer();
this.ApplyTileIndexDrawMode();

this.tilesetView.SelectedAreaChanged += this.SourcePaletteTilesetView_SelectedAreaChanged;
}

public void RaiseKeyDownEvent(KeyEventArgs e)
{
this.tilesetView.RaiseKeyDownEvent(e);
}

public void RaiseKeyUpEvent(KeyEventArgs e)
{
this.tilesetView.RaiseKeyUpEvent(e);
}

internal void SaveUserData(XElement node)
Expand Down Expand Up @@ -139,7 +152,12 @@ protected override void OnClosed(EventArgs e)
base.OnClosed(e);
this.OnBecameInvisible();
}


private void SourcePaletteTilesetView_SelectedAreaChanged(object sender, EventArgs e)
{
this.SelectedAreaChanged?.Invoke(this, e);
}

private void OnBecameVisible()
{
if (!this.globalEventsSubscribed)
Expand Down