summaryrefslogtreecommitdiff
path: root/plugins/Brushes.h
diff options
context:
space:
mode:
authorPetr Mrázek2012-03-24 00:13:16 +0100
committerPetr Mrázek2012-03-24 00:13:16 +0100
commitaddb5c87aa73fa08258923444a031e011f2e8a50 (patch)
tree246dca11f301b840c4d5c438ee8c67248af4980f /plugins/Brushes.h
parent078caf363f693a8f7744de85a0539de4f68346cc (diff)
downloaddfhack-addb5c87aa73fa08258923444a031e011f2e8a50.tar.gz
dfhack-addb5c87aa73fa08258923444a031e011f2e8a50.tar.bz2
dfhack-addb5c87aa73fa08258923444a031e011f2e8a50.tar.xz
liquids vs liquidsgo: FIGHT!
liquidsgo WINS, renamed to liquids to not confuse users.
Diffstat (limited to 'plugins/Brushes.h')
-rw-r--r--plugins/Brushes.h178
1 files changed, 178 insertions, 0 deletions
diff --git a/plugins/Brushes.h b/plugins/Brushes.h
new file mode 100644
index 00000000..73c3a05a
--- /dev/null
+++ b/plugins/Brushes.h
@@ -0,0 +1,178 @@
+#pragma once
+
+typedef vector <df::coord> coord_vec;
+class Brush
+{
+public:
+ virtual ~Brush(){};
+ virtual coord_vec points(MapExtras::MapCache & mc,DFHack::DFCoord start) = 0;
+};
+/**
+ * generic 3D rectangle brush. you can specify the dimensions of
+ * the rectangle and optionally which tile is its 'center'
+ */
+class RectangleBrush : public Brush
+{
+public:
+ RectangleBrush(int x, int y, int z = 1, int centerx = -1, int centery = -1, int centerz = -1)
+ {
+ if(centerx == -1)
+ cx_ = x/2;
+ else
+ cx_ = centerx;
+ if(centery == -1)
+ cy_ = y/2;
+ else
+ cy_ = centery;
+ if(centerz == -1)
+ cz_ = z/2;
+ else
+ cz_ = centerz;
+ x_ = x;
+ y_ = y;
+ z_ = z;
+ };
+ coord_vec points(MapExtras::MapCache & mc, DFHack::DFCoord start)
+ {
+ coord_vec v;
+ DFHack::DFCoord iterstart(start.x - cx_, start.y - cy_, start.z - cz_);
+ DFHack::DFCoord iter = iterstart;
+ for(int xi = 0; xi < x_; xi++)
+ {
+ for(int yi = 0; yi < y_; yi++)
+ {
+ for(int zi = 0; zi < z_; zi++)
+ {
+ if(mc.testCoord(iter))
+ v.push_back(iter);
+ iter.z++;
+ }
+ iter.z = iterstart.z;
+ iter.y++;
+ }
+ iter.y = iterstart.y;
+ iter.x ++;
+ }
+ return v;
+ };
+ ~RectangleBrush(){};
+private:
+ int x_, y_, z_;
+ int cx_, cy_, cz_;
+};
+
+/**
+ * stupid block brush, legacy. use when you want to apply something to a whole DF map block.
+ */
+class BlockBrush : public Brush
+{
+public:
+ BlockBrush(){};
+ ~BlockBrush(){};
+ coord_vec points(MapExtras::MapCache & mc, DFHack::DFCoord start)
+ {
+ coord_vec v;
+ DFHack::DFCoord blockc = start / 16;
+ DFHack::DFCoord iterc = blockc * 16;
+ if( !mc.testCoord(start) )
+ return v;
+ auto starty = iterc.y;
+ for(int xi = 0; xi < 16; xi++)
+ {
+ for(int yi = 0; yi < 16; yi++)
+ {
+ v.push_back(iterc);
+ iterc.y++;
+ }
+ iterc.y = starty;
+ iterc.x ++;
+ }
+ return v;
+ };
+};
+
+/**
+ * Column from a position through open space tiles
+ * example: create a column of magma
+ */
+class ColumnBrush : public Brush
+{
+public:
+ ColumnBrush(){};
+ ~ColumnBrush(){};
+ coord_vec points(MapExtras::MapCache & mc, DFHack::DFCoord start)
+ {
+ coord_vec v;
+ bool juststarted = true;
+ while (mc.testCoord(start))
+ {
+ df::tiletype tt = mc.tiletypeAt(start);
+ if(DFHack::LowPassable(tt) || juststarted && DFHack::HighPassable(tt))
+ {
+ v.push_back(start);
+ juststarted = false;
+ start.z++;
+ }
+ else break;
+ }
+ return v;
+ };
+};
+
+/**
+ * Flood-fill water tiles from cursor (for wclean)
+ * example: remove salt flag from a river
+ */
+class FloodBrush : public Brush
+{
+public:
+ FloodBrush(Core *c){c_ = c;};
+ ~FloodBrush(){};
+ coord_vec points(MapExtras::MapCache & mc, DFHack::DFCoord start)
+ {
+ coord_vec v;
+
+ std::stack<DFCoord> to_flood;
+ to_flood.push(start);
+
+ std::set<DFCoord> seen;
+
+ while (!to_flood.empty()) {
+ DFCoord xy = to_flood.top();
+ to_flood.pop();
+
+ df::tile_designation des = mc.designationAt(xy);
+
+ if (seen.find(xy) == seen.end()
+ && des.bits.flow_size
+ && des.bits.liquid_type == tile_liquid::Water) {
+ v.push_back(xy);
+ seen.insert(xy);
+
+ maybeFlood(DFCoord(xy.x - 1, xy.y, xy.z), to_flood, mc);
+ maybeFlood(DFCoord(xy.x + 1, xy.y, xy.z), to_flood, mc);
+ maybeFlood(DFCoord(xy.x, xy.y - 1, xy.z), to_flood, mc);
+ maybeFlood(DFCoord(xy.x, xy.y + 1, xy.z), to_flood, mc);
+
+ df::tiletype tt = mc.tiletypeAt(xy);
+ if (LowPassable(tt))
+ {
+ maybeFlood(DFCoord(xy.x, xy.y, xy.z - 1), to_flood, mc);
+ }
+ if (HighPassable(tt))
+ {
+ maybeFlood(DFCoord(xy.x, xy.y, xy.z + 1), to_flood, mc);
+ }
+ }
+ }
+
+ return v;
+ }
+private:
+ void maybeFlood(DFCoord c, std::stack<DFCoord> &to_flood, MapExtras::MapCache &mc) {
+ if (mc.testCoord(c)) {
+ to_flood.push(c);
+ }
+ }
+ Core *c_;
+};