diff --git a/Source/Plugins/Tilemaps/Editor/CamViewStates/TilemapEditorCamViewState.cs b/Source/Plugins/Tilemaps/Editor/CamViewStates/TilemapEditorCamViewState.cs
index 8fb005e23..2b9173a87 100644
--- a/Source/Plugins/Tilemaps/Editor/CamViewStates/TilemapEditorCamViewState.cs
+++ b/Source/Plugins/Tilemaps/Editor/CamViewStates/TilemapEditorCamViewState.cs
@@ -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
@@ -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();
@@ -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()
@@ -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];
@@ -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;
@@ -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;
@@ -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);
diff --git a/Source/Plugins/Tilemaps/Editor/EditorPlugin.cs b/Source/Plugins/Tilemaps/Editor/EditorPlugin.cs
index 6c6e4d5ff..60bd2c5bb 100644
--- a/Source/Plugins/Tilemaps/Editor/EditorPlugin.cs
+++ b/Source/Plugins/Tilemaps/Editor/EditorPlugin.cs
@@ -187,7 +187,14 @@ public void PopTilePalette()
else
this.pendingLocalTilePalettes--;
}
-
+ ///
+ /// Gets the if there is one, returns null otherwise.
+ ///
+ public TilemapToolSourcePalette PeekTilePalette()
+ {
+ return this.tilePalette;
+ }
+
public TilesetEditor RequestTilesetEditor()
{
// Create a new tileset editor, if no is available right now
diff --git a/Source/Plugins/Tilemaps/Editor/Modules/SourcePaletteTilesetView.cs b/Source/Plugins/Tilemaps/Editor/Modules/SourcePaletteTilesetView.cs
index ad0fdf58b..bb99fa1bc 100644
--- a/Source/Plugins/Tilemaps/Editor/Modules/SourcePaletteTilesetView.cs
+++ b/Source/Plugins/Tilemaps/Editor/Modules/SourcePaletteTilesetView.cs
@@ -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
@@ -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;
@@ -76,6 +88,14 @@ public IReadOnlyGrid 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()
{
@@ -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)
@@ -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()
{
@@ -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,
@@ -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();
}
}
}
\ No newline at end of file
diff --git a/Source/Plugins/Tilemaps/Editor/Modules/TilemapToolSourcePalette.cs b/Source/Plugins/Tilemaps/Editor/Modules/TilemapToolSourcePalette.cs
index b882d7bbd..840e71830 100644
--- a/Source/Plugins/Tilemaps/Editor/Modules/TilemapToolSourcePalette.cs
+++ b/Source/Plugins/Tilemaps/Editor/Modules/TilemapToolSourcePalette.cs
@@ -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 SelectedTileset
{
@@ -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)
@@ -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)