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.
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
37 GdElementEnum fill
, boundary
;
38 if (!(is
>> start
>> fill
>> boundary
))
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
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);
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
81 if (start
.x
<0 || start
.y
<0 || start
.x
>=cave
.w
|| start
.y
>=cave
.h
)
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.")},
104 PropertyDescription
const* CaveBoundaryFill::get_description_array() const
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
;