20130313
[gdash.git] / src / cave / object / caveobjectboundaryfill.cpp
blobe14644d60af95b9b016b7ed04e64ed3d724164a7
1 /*
2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "config.h"
19 #include <glib/gi18n.h>
21 #include "fileops/bdcffhelper.hpp"
22 #include "cave/caverendered.hpp"
23 #include "misc/printf.hpp"
24 #include "cave/elementproperties.hpp"
26 #include "cave/object/caveobjectboundaryfill.hpp"
29 std::string CaveBoundaryFill::get_bdcff() const
31 return BdcffFormat("BoundaryFill") << start << fill_element << border_element;
34 CaveBoundaryFill* CaveBoundaryFill::clone_from_bdcff(const std::string &name, std::istream &is) const
36 Coordinate start;
37 GdElementEnum fill, boundary;
38 if (!(is >> start >> fill >> boundary))
39 return NULL;
41 return new CaveBoundaryFill(start, fill, boundary);
44 /// Create a new boundary fill objects.
45 /// @param _start The starting coordinates of the fill.
46 /// @param _border_element This is the element which is drawn on the outline of the area.
47 /// @param _fill_element The inside of the area will be filled with this element.
48 CaveBoundaryFill::CaveBoundaryFill(Coordinate _start, GdElementEnum _fill_element, GdElementEnum _border_element)
49 : CaveFill(GD_FLOODFILL_BORDER, _start, _fill_element),
50 border_element(_border_element)
54 /// Recursive function to fill an area of the cave, until the boundary is reached.
55 /// This function fills the insides of the area recursively with
56 /// the border element (!) - this way it is easy for it to not write
57 /// to a cell twice.
58 /// @param cave The cave to do the drawing in.
59 /// @param x The x coordinate to draw at.
60 /// @param y The y coordinate to draw at.
61 void CaveBoundaryFill::draw_proc(CaveRendered &cave, int x, int y) const
63 /* fill with border so we do not come back */
64 cave.store_rc(x, y, border_element, this);
66 if (x>0 && cave.map(x-1, y)!=border_element) draw_proc(cave, x-1, y);
67 if (y>0 && cave.map(x, y-1)!=border_element) draw_proc(cave, x, y-1);
68 if (x<cave.w-1 && cave.map(x+1, y)!=border_element) draw_proc(cave, x+1, y);
69 if (y<cave.h-1 && cave.map(x, y+1)!=border_element) draw_proc(cave, x, y+1);
72 /// Draw the object.
73 /// First it fills the insides of the area using draw_proc.
74 /// Then it finds its own drawing using the object_order() map of the cave;
75 /// the elements drawn by it are replaced with the fill element.
76 /// @param cave The cave to draw in.
77 /// @param level The level the cave is rendered on.
78 void CaveBoundaryFill::draw(CaveRendered &cave) const
80 /* check bounds */
81 if (start.x<0 || start.y<0 || start.x>=cave.w || start.y>=cave.h)
82 return;
84 /* this procedure fills the area with the border element. */
85 draw_proc(cave, start.x, start.y);
87 /* after the fill, we change all filled cells to the fill_element. */
88 /* we find those by looking at the object_order map, that was filled by draw_proc/store_rc */
89 for (int y=0; y<cave.h; y++)
90 for (int x=0; x<cave.w; x++)
91 if (cave.objects_order(x, y)==this)
92 cave.map(x, y)=fill_element;
95 PropertyDescription const CaveBoundaryFill::descriptor[] = {
96 {"", GD_TAB, 0, N_("Boundary fill")},
97 {"", GD_TYPE_BOOLEAN_LEVELS, 0, N_("Levels"), GetterBase::create_new(&CaveBoundaryFill::seen_on), N_("Levels on which this object is visible.")},
98 {"", GD_TYPE_COORDINATE, 0, N_("Start"), GetterBase::create_new(&CaveBoundaryFill::start), N_("The coordinate to start the fill at."), 0, 127},
99 {"", GD_TYPE_ELEMENT, 0, N_("Border element"), GetterBase::create_new(&CaveBoundaryFill::border_element), N_("This is the border of the fill. The closed area must be bounded by this element.")},
100 {"", GD_TYPE_ELEMENT, 0, N_("Fill element"), GetterBase::create_new(&CaveBoundaryFill::fill_element), N_("This is the element the closed area will be filled with.")},
101 {NULL},
104 PropertyDescription const* CaveBoundaryFill::get_description_array() const
106 return descriptor;
109 std::string CaveBoundaryFill::get_description_markup() const
111 return SPrintf(_("Boundary fill from %d,%d of <b>%s</b>, border <b>%s</b>"))
112 % start.x % start.y % gd_element_properties[fill_element].lowercase_name % gd_element_properties[border_element].lowercase_name;