mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-13 02:52:37 +00:00
(svn r21497) -Codechange: prepare the viewport selection mechanism for selecting diagonally
This commit is contained in:
parent
2e9108afe9
commit
959308a243
@ -616,6 +616,15 @@ static void ResetLandscapeConfirmationCallback(Window *w, bool confirmed)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether we are currently dragging diagonally.
|
||||||
|
* @returns True iff we are selecting a diagonal rectangle for an action that supports it, otherwise false.
|
||||||
|
*/
|
||||||
|
bool IsDraggingDiagonal()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct ScenarioEditorLandscapeGenerationWindow : Window {
|
struct ScenarioEditorLandscapeGenerationWindow : Window {
|
||||||
ScenarioEditorLandscapeGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
|
ScenarioEditorLandscapeGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "window_type.h"
|
#include "window_type.h"
|
||||||
|
|
||||||
|
bool IsDraggingDiagonal();
|
||||||
|
|
||||||
Window *ShowTerraformToolbar(Window *link = NULL);
|
Window *ShowTerraformToolbar(Window *link = NULL);
|
||||||
Window *ShowEditorTerraformToolbar();
|
Window *ShowEditorTerraformToolbar();
|
||||||
|
|
||||||
|
@ -49,10 +49,12 @@ struct TileHighlightData {
|
|||||||
Point size; ///< Size, in tile "units", of the white/red selection area.
|
Point size; ///< Size, in tile "units", of the white/red selection area.
|
||||||
Point offs; ///< Offset, in tile "units", for the blue coverage area from the selected area's northern tile.
|
Point offs; ///< Offset, in tile "units", for the blue coverage area from the selected area's northern tile.
|
||||||
Point outersize; ///< Size, in tile "units", of the blue coverage area excluding the side of the selected area.
|
Point outersize; ///< Size, in tile "units", of the blue coverage area excluding the side of the selected area.
|
||||||
|
bool diagonal; ///< Whether the dragged area is a 45 degrees rotated rectangle.
|
||||||
|
|
||||||
Point new_pos; ///< New value for \a pos; used to determine whether to redraw the selection.
|
Point new_pos; ///< New value for \a pos; used to determine whether to redraw the selection.
|
||||||
Point new_size; ///< New value for \a size; used to determine whether to redraw the selection.
|
Point new_size; ///< New value for \a size; used to determine whether to redraw the selection.
|
||||||
Point new_outersize; ///< New value for \a outersize; used to determine whether to redraw the selection.
|
Point new_outersize; ///< New value for \a outersize; used to determine whether to redraw the selection.
|
||||||
|
bool new_diagonal; ///< New value for \a diagonal; used to determine whether to redraw the selection.
|
||||||
byte dirty; ///< Whether the build station window needs to redraw due to the changed selection.
|
byte dirty; ///< Whether the build station window needs to redraw due to the changed selection.
|
||||||
|
|
||||||
Point selstart; ///< The location where the dragging started.
|
Point selstart; ///< The location where the dragging started.
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "window_func.h"
|
#include "window_func.h"
|
||||||
#include "tilehighlight_func.h"
|
#include "tilehighlight_func.h"
|
||||||
#include "window_gui.h"
|
#include "window_gui.h"
|
||||||
|
#include "terraform_gui.h"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
@ -753,6 +754,38 @@ void EndSpriteCombine()
|
|||||||
_vd.combine_sprites = SPRITE_COMBINE_NONE;
|
_vd.combine_sprites = SPRITE_COMBINE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the parameter "check" is inside the interval between
|
||||||
|
* begin and end, including both begin and end.
|
||||||
|
* @note Whether \c begin or \c end is the biggest does not matter.
|
||||||
|
* This method will account for that.
|
||||||
|
* @param begin The begin of the interval.
|
||||||
|
* @param end The end of the interval.
|
||||||
|
* @param check The value to check.
|
||||||
|
*/
|
||||||
|
static bool IsInRangeInclusive(int begin, int end, int check)
|
||||||
|
{
|
||||||
|
if (begin > end) Swap(begin, end);
|
||||||
|
return begin <= check && check <= end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a point is inside the selected a diagonal rectangle given by _thd.size and _thd.pos
|
||||||
|
* @param x The x coordinate of the point to be checked.
|
||||||
|
* @param y The y coordinate of the point to be checked.
|
||||||
|
* @return True if the point is inside the rectangle, else false.
|
||||||
|
*/
|
||||||
|
bool IsInsideRotatedRectangle(int x, int y)
|
||||||
|
{
|
||||||
|
int dist_a = (_thd.size.x + _thd.size.y); // Rotated coordinate system for selected rectangle.
|
||||||
|
int dist_b = (_thd.size.x - _thd.size.y); // We don't have to divide by 2. It's all relative!
|
||||||
|
int a = ((x - _thd.pos.x) + (y - _thd.pos.y)); // Rotated coordinate system for the point under scrutiny.
|
||||||
|
int b = ((x - _thd.pos.x) - (y - _thd.pos.y));
|
||||||
|
|
||||||
|
/* Check if a and b are between 0 and dist_a or dist_b respectively. */
|
||||||
|
return IsInRangeInclusive(dist_a, 0, a) && IsInRangeInclusive(dist_b, 0, b);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a child sprite to a parent sprite.
|
* Add a child sprite to a parent sprite.
|
||||||
*
|
*
|
||||||
@ -940,6 +973,29 @@ static void DrawTileSelection(const TileInfo *ti)
|
|||||||
/* no selection active? */
|
/* no selection active? */
|
||||||
if (_thd.drawstyle == 0) return;
|
if (_thd.drawstyle == 0) return;
|
||||||
|
|
||||||
|
if (_thd.diagonal) { // We're drawing a 45 degrees rotated (diagonal) rectangle
|
||||||
|
if (IsInsideRotatedRectangle((int)ti->x, (int)ti->y)) {
|
||||||
|
if (_thd.drawstyle & HT_RECT) { // Highlighting a square (clear land)
|
||||||
|
/* Don't mark tiles outside the map. */
|
||||||
|
if (!IsValidTile(ti->tile)) return;
|
||||||
|
|
||||||
|
SpriteID image = SPR_SELECT_TILE + SlopeToSpriteOffset(ti->tileh);
|
||||||
|
DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : PAL_NONE, ti, 7, FOUNDATION_PART_NORMAL);
|
||||||
|
} else { // Highlighting a dot (level land)
|
||||||
|
/* Figure out the Z coordinate for the single dot. */
|
||||||
|
byte z = ti->z;
|
||||||
|
if (ti->tileh & SLOPE_N) {
|
||||||
|
z += TILE_HEIGHT;
|
||||||
|
if (!(ti->tileh & SLOPE_S) && (ti->tileh & SLOPE_STEEP)) {
|
||||||
|
z += TILE_HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddTileSpriteToDraw(_cur_dpi->zoom != 2 ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti->x, ti->y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Inside the inner area? */
|
/* Inside the inner area? */
|
||||||
if (IsInsideBS(ti->x, _thd.pos.x, _thd.size.x) &&
|
if (IsInsideBS(ti->x, _thd.pos.x, _thd.size.x) &&
|
||||||
IsInsideBS(ti->y, _thd.pos.y, _thd.size.y)) {
|
IsInsideBS(ti->y, _thd.pos.y, _thd.size.y)) {
|
||||||
@ -1621,12 +1677,13 @@ void MarkTileDirtyByTile(TileIndex tile)
|
|||||||
*/
|
*/
|
||||||
static void SetSelectionTilesDirty()
|
static void SetSelectionTilesDirty()
|
||||||
{
|
{
|
||||||
int x_start = _thd.pos.x;
|
|
||||||
int y_start = _thd.pos.y;
|
|
||||||
|
|
||||||
int x_size = _thd.size.x;
|
int x_size = _thd.size.x;
|
||||||
int y_size = _thd.size.y;
|
int y_size = _thd.size.y;
|
||||||
|
|
||||||
|
if (!_thd.diagonal) { // Selecting in a straigth rectangle (or a single square)
|
||||||
|
int x_start = _thd.pos.x;
|
||||||
|
int y_start = _thd.pos.y;
|
||||||
|
|
||||||
if (_thd.outersize.x != 0) {
|
if (_thd.outersize.x != 0) {
|
||||||
x_size += _thd.outersize.x;
|
x_size += _thd.outersize.x;
|
||||||
x_start += _thd.offs.x;
|
x_start += _thd.offs.x;
|
||||||
@ -1703,6 +1760,24 @@ static void SetSelectionTilesDirty()
|
|||||||
bot_x -= TILE_SIZE;
|
bot_x -= TILE_SIZE;
|
||||||
}
|
}
|
||||||
} while (bot_x >= top_x);
|
} while (bot_x >= top_x);
|
||||||
|
} else { // Selecting in a 45 degrees rotated (diagonal) rectangle.
|
||||||
|
/* a_size, b_size describe a rectangle with rotated coordinates */
|
||||||
|
int a_size = x_size + y_size, b_size = x_size - y_size;
|
||||||
|
|
||||||
|
int interval_a = a_size < 0 ? -TILE_SIZE : TILE_SIZE;
|
||||||
|
int interval_b = b_size < 0 ? -TILE_SIZE : TILE_SIZE;
|
||||||
|
|
||||||
|
for (int a = -interval_a; a != a_size + interval_a; a += interval_a) {
|
||||||
|
for (int b = -interval_b; b != b_size + interval_b; b += interval_b) {
|
||||||
|
uint x = (_thd.pos.x + (a + b) / 2) / TILE_SIZE;
|
||||||
|
uint y = (_thd.pos.y + (a - b) / 2) / TILE_SIZE;
|
||||||
|
|
||||||
|
if (x < MapMaxX() && y < MapMaxY()) {
|
||||||
|
MarkTileDirtyByTile(TileXY(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1963,6 +2038,7 @@ void UpdateTileSelection()
|
|||||||
int y1;
|
int y1;
|
||||||
|
|
||||||
_thd.new_drawstyle = HT_NONE;
|
_thd.new_drawstyle = HT_NONE;
|
||||||
|
_thd.new_diagonal = false;
|
||||||
|
|
||||||
if (_thd.place_mode == HT_SPECIAL) {
|
if (_thd.place_mode == HT_SPECIAL) {
|
||||||
x1 = _thd.selend.x;
|
x1 = _thd.selend.x;
|
||||||
@ -1973,12 +2049,20 @@ void UpdateTileSelection()
|
|||||||
x1 &= ~TILE_UNIT_MASK;
|
x1 &= ~TILE_UNIT_MASK;
|
||||||
y1 &= ~TILE_UNIT_MASK;
|
y1 &= ~TILE_UNIT_MASK;
|
||||||
|
|
||||||
|
if (IsDraggingDiagonal()) {
|
||||||
|
_thd.new_diagonal = true;
|
||||||
|
} else {
|
||||||
if (x1 >= x2) Swap(x1, x2);
|
if (x1 >= x2) Swap(x1, x2);
|
||||||
if (y1 >= y2) Swap(y1, y2);
|
if (y1 >= y2) Swap(y1, y2);
|
||||||
|
}
|
||||||
_thd.new_pos.x = x1;
|
_thd.new_pos.x = x1;
|
||||||
_thd.new_pos.y = y1;
|
_thd.new_pos.y = y1;
|
||||||
_thd.new_size.x = x2 - x1 + TILE_SIZE;
|
_thd.new_size.x = x2 - x1;
|
||||||
_thd.new_size.y = y2 - y1 + TILE_SIZE;
|
_thd.new_size.y = y2 - y1;
|
||||||
|
if (!_thd.new_diagonal) {
|
||||||
|
_thd.new_size.x += TILE_SIZE;
|
||||||
|
_thd.new_size.y += TILE_SIZE;
|
||||||
|
}
|
||||||
_thd.new_drawstyle = _thd.next_drawstyle;
|
_thd.new_drawstyle = _thd.next_drawstyle;
|
||||||
}
|
}
|
||||||
} else if ((_thd.place_mode & HT_DRAG_MASK) != HT_NONE) {
|
} else if ((_thd.place_mode & HT_DRAG_MASK) != HT_NONE) {
|
||||||
@ -2033,7 +2117,8 @@ void UpdateTileSelection()
|
|||||||
_thd.pos.x != _thd.new_pos.x || _thd.pos.y != _thd.new_pos.y ||
|
_thd.pos.x != _thd.new_pos.x || _thd.pos.y != _thd.new_pos.y ||
|
||||||
_thd.size.x != _thd.new_size.x || _thd.size.y != _thd.new_size.y ||
|
_thd.size.x != _thd.new_size.x || _thd.size.y != _thd.new_size.y ||
|
||||||
_thd.outersize.x != _thd.new_outersize.x ||
|
_thd.outersize.x != _thd.new_outersize.x ||
|
||||||
_thd.outersize.y != _thd.new_outersize.y) {
|
_thd.outersize.y != _thd.new_outersize.y ||
|
||||||
|
_thd.diagonal != _thd.new_diagonal) {
|
||||||
/* clear the old selection? */
|
/* clear the old selection? */
|
||||||
if (_thd.drawstyle) SetSelectionTilesDirty();
|
if (_thd.drawstyle) SetSelectionTilesDirty();
|
||||||
|
|
||||||
@ -2041,6 +2126,7 @@ void UpdateTileSelection()
|
|||||||
_thd.pos = _thd.new_pos;
|
_thd.pos = _thd.new_pos;
|
||||||
_thd.size = _thd.new_size;
|
_thd.size = _thd.new_size;
|
||||||
_thd.outersize = _thd.new_outersize;
|
_thd.outersize = _thd.new_outersize;
|
||||||
|
_thd.diagonal = _thd.new_diagonal;
|
||||||
_thd.dirty = 0xff;
|
_thd.dirty = 0xff;
|
||||||
|
|
||||||
/* draw the new selection? */
|
/* draw the new selection? */
|
||||||
|
Loading…
Reference in New Issue
Block a user