Implement flood-fill tool

This commit is contained in:
2015-09-27 03:15:05 -04:00
parent add0ea48cf
commit 082e3fc9d9
5 changed files with 46 additions and 6 deletions

View File

@@ -4,6 +4,7 @@
#include <cstring>
#include <array>
#include <string>
#include <stack>
#include "scen.global.hpp"
#include "scenario.hpp"
#include "graphtool.hpp"
@@ -68,7 +69,7 @@ rectangle palette_buttons[10][6];
short current_rs_top = 0;
ePalBtn out_buttons[6][10] = {
{PAL_PENCIL, PAL_BRUSH_LG, PAL_BRUSH_SM, PAL_SPRAY_LG, PAL_SPRAY_SM, PAL_ERASER, PAL_DROPPER, PAL_RECT_HOLLOW, PAL_RECT_FILLED, PAL_BLANK},
{PAL_PENCIL, PAL_BRUSH_LG, PAL_BRUSH_SM, PAL_SPRAY_LG, PAL_SPRAY_SM, PAL_ERASER, PAL_DROPPER, PAL_RECT_HOLLOW, PAL_RECT_FILLED, PAL_BUCKET},
{PAL_EDIT_TOWN, PAL_ERASE_TOWN, PAL_BLANK, PAL_BLANK, PAL_EDIT_SIGN, PAL_TEXT_AREA, PAL_WANDER, PAL_CHANGE, PAL_ZOOM, PAL_BLANK},
{PAL_SPEC, PAL_COPY_SPEC, PAL_PASTE_SPEC, PAL_ERASE_SPEC, PAL_EDIT_SPEC, PAL_SPEC_SPOT, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK},
{PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK},
@@ -77,7 +78,7 @@ ePalBtn out_buttons[6][10] = {
};
ePalBtn town_buttons[6][10] = {
{PAL_PENCIL, PAL_BRUSH_LG, PAL_BRUSH_SM, PAL_SPRAY_LG, PAL_SPRAY_SM, PAL_ERASER, PAL_DROPPER, PAL_RECT_HOLLOW, PAL_RECT_FILLED, PAL_BLANK},
{PAL_PENCIL, PAL_BRUSH_LG, PAL_BRUSH_SM, PAL_SPRAY_LG, PAL_SPRAY_SM, PAL_ERASER, PAL_DROPPER, PAL_RECT_HOLLOW, PAL_RECT_FILLED, PAL_BUCKET},
{PAL_ENTER_N, PAL_ENTER_W, PAL_ENTER_S, PAL_ENTER_E, PAL_EDIT_SIGN, PAL_TEXT_AREA, PAL_WANDER, PAL_CHANGE, PAL_ZOOM, PAL_TERRAIN},
{PAL_SPEC, PAL_COPY_SPEC, PAL_PASTE_SPEC, PAL_ERASE_SPEC, PAL_EDIT_SPEC, PAL_SPEC_SPOT, PAL_EDIT_ITEM, PAL_SAME_ITEM, PAL_ERASE_ITEM, PAL_ITEM},
{PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_BLANK, PAL_EDIT_MONST, PAL_SAME_MONST, PAL_ERASE_MONST, PAL_MONST},
@@ -793,6 +794,11 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
change_circle_terrain(spot_hit,2,current_ground,20);
mouse_button_held = true;
break;
case MODE_FLOOD_FILL:
if(mouse_button_held) break;
flood_fill_terrain(spot_hit, current_terrain_type);
mouse_button_held = true;
break;
case MODE_PLACE_ITEM:
// If we just placed this item there, forget it
if(mouse_button_held && store_place_item.loc == spot_hit)
@@ -1289,7 +1295,7 @@ static bool handle_toolpal_action(location cur_point2) {
case PAL_RECT_HOLLOW:
overall_mode = MODE_HOLLOW_RECT;
if(false) // Skip next statement
case PAL_RECT_FILLED:
case PAL_RECT_FILLED:
overall_mode = MODE_FILLED_RECT;
mode_count = 2;
set_cursor(topleft_curs);
@@ -1297,6 +1303,11 @@ static bool handle_toolpal_action(location cur_point2) {
set_string("Fill rectangle (hollow)","Select upper left corner");
else set_string("Fill rectangle (solid)","Select upper left corner");
break;
case PAL_BUCKET:
overall_mode = MODE_FLOOD_FILL;
set_cursor(bucket_curs);
set_string("Flood fill", scenario.ter_types[current_terrain_type].name);
break;
case PAL_ZOOM: // switch view
cur_viewing_mode = (cur_viewing_mode + 1) % 4;
draw_main_screen();
@@ -1874,6 +1885,32 @@ void change_rect_terrain(rectangle r,ter_num_t terrain_type,short probability,bo
}
}
void flood_fill_terrain(location start, ter_num_t terrain_type) {
static const int dx[4] = {0, 1, 0, -1};
static const int dy[4] = {-1, 0, 1, 0};
ter_num_t to_replace = editing_town ? town->terrain(start.x, start.y) : current_terrain->terrain[start.x][start.y];
std::stack<location> to_visit;
std::set<location, loc_compare> visited;
to_visit.push(start);
while(!to_visit.empty()) {
location this_loc = to_visit.top();
to_visit.pop();
visited.insert(this_loc);
for(int i = 0; i < 4; i++) {
location adj_loc = this_loc;
adj_loc.x += dx[i];
adj_loc.y += dy[i];
ter_num_t check = editing_town ? town->terrain(adj_loc.x, adj_loc.y) : current_terrain->terrain[adj_loc.x][adj_loc.y];
if(check == to_replace && !visited.count(adj_loc))
to_visit.push(adj_loc);
}
if(editing_town)
town->terrain(this_loc.x, this_loc.y) = terrain_type;
else current_terrain->terrain[this_loc.x][this_loc.y] = terrain_type;
}
}
void frill_up_terrain() {
short i,j;
ter_num_t terrain_type;

View File

@@ -17,6 +17,7 @@ cTown::cItem edit_item(cTown::cItem item);
void shy_change_circle_terrain(location center,short radius,ter_num_t terrain_type,short probability);
void change_circle_terrain(location center,short radius,ter_num_t terrain_type,short probability);
void change_rect_terrain(rectangle r,ter_num_t terrain_type,short probability,bool hollow);
void flood_fill_terrain(location start, ter_num_t terrain_type);
void frill_up_terrain();
void unfrill_terrain();
void set_terrain(location l,ter_num_t terrain_type);

View File

@@ -41,6 +41,7 @@ enum eScenMode {
MODE_PLACE_EAST_ENTRANCE = 11,
MODE_PLACE_SOUTH_ENTRANCE = 12,
MODE_PLACE_WEST_ENTRANCE = 13,
MODE_FLOOD_FILL = 14,
MODE_PLACE_FORCECAGE = 19,
MODE_PLACE_WEB = 20,
MODE_PLACE_CRATE = 21,
@@ -92,7 +93,7 @@ enum eStrMode {
enum ePalBtn {
PAL_BLANK = -1,
PAL_PENCIL = 0, PAL_BRUSH_LG = 1, PAL_BRUSH_SM = 2, PAL_SPRAY_LG = 3, PAL_SPRAY_SM = 4, PAL_DROPPER = 5, PAL_RECT_HOLLOW = 6, PAL_RECT_FILLED = 7,
PAL_PENCIL = 0, PAL_BRUSH_LG = 1, PAL_BRUSH_SM = 2, PAL_SPRAY_LG = 3, PAL_SPRAY_SM = 4, PAL_DROPPER = 5, PAL_RECT_HOLLOW = 6, PAL_RECT_FILLED = 7, PAL_BUCKET = 8,
PAL_ZOOM = 10, PAL_ERASER = 11, PAL_EDIT_SIGN = 12, PAL_TEXT_AREA = 13, PAL_WANDER = 14, PAL_CHANGE = 15, PAL_ERASE_TOWN = 16, PAL_EDIT_TOWN = 17,
PAL_EDIT_ITEM = 20, PAL_SAME_ITEM = 21, PAL_ERASE_ITEM = 22, PAL_SPEC = 23, PAL_COPY_SPEC = 24, PAL_PASTE_SPEC = 25, PAL_ERASE_SPEC = 26, PAL_EDIT_SPEC = 27,
PAL_EDIT_MONST = 30, PAL_SAME_MONST = 31, PAL_ERASE_MONST = 32, PAL_ENTER_N = 34, PAL_ENTER_W = 35, PAL_ENTER_S = 36, PAL_ENTER_E = 37,

View File

@@ -39,6 +39,7 @@ enum cursor_type {
talk_curs = 21,
key_curs = 22,
look_curs = 23,
bucket_curs,
watch_curs,
text_curs, // Keep this one last
};
@@ -58,14 +59,14 @@ void set_cursor(cursor_type which_curs);
void restore_cursor();
// Filenames for the cursors
static const char*const cursors[25] = {
static const char*const cursors[26] = {
"wand", "eyedropper", "brush", "spraycan",
"eraser", "topleft", "bottomright", "hand",
"NW", "N", "NE",
"W", "wait", "E",
"SW", "S", "SE",
"sword", "boot", "drop", "target",
"talk", "key", "look", "watch",
"talk", "key", "look", "bucket", "watch",
};
#endif