summaryrefslogtreecommitdiff
path: root/plugins/tiletypes.cpp
diff options
context:
space:
mode:
authorJared Adams2012-04-15 08:40:19 -0600
committerJared Adams2012-04-15 08:40:19 -0600
commitf3c7a685f5b6d84bff6193ad289df3cda634a4ee (patch)
treea0b45bbac4b659f0e8f46c51fea67915387b0399 /plugins/tiletypes.cpp
parentc69af6ab9eff10fc59f68d462656caa2dacd266c (diff)
downloaddfhack-f3c7a685f5b6d84bff6193ad289df3cda634a4ee.tar.gz
dfhack-f3c7a685f5b6d84bff6193ad289df3cda634a4ee.tar.bz2
dfhack-f3c7a685f5b6d84bff6193ad289df3cda634a4ee.tar.xz
Make tiletypes more useful
* Paint, filter, and brush state is now saved between calls. * Added 'all' paint option to set material, shape, special, and variant at the same time. * Added tiletypes-here (like liquids here, except is uses the saved brush settings) * Added tiletypes-here-point (like liquids here, always only the tile under the cursor) * Added tiletypes-command: runs tiletypes commands seperated by ';' tokens (affects saved state) * Make the internal workings match liquids a bit more * Give brush objects a descriptor string * Make Core::cheap_tokenise available
Diffstat (limited to 'plugins/tiletypes.cpp')
-rw-r--r--plugins/tiletypes.cpp937
1 files changed, 554 insertions, 383 deletions
diff --git a/plugins/tiletypes.cpp b/plugins/tiletypes.cpp
index 61b4ec8e..41627a85 100644
--- a/plugins/tiletypes.cpp
+++ b/plugins/tiletypes.cpp
@@ -1,4 +1,24 @@
+// Plugin tiletypes
//
+// This plugin allows fine editing of individual game tiles (expect for
+// changing material subtypes).
+//
+// Commands:
+// tiletypes - runs the interractive interpreter
+// tiletypes-command - run the given command
+// (intended to be mapped to a hotkey or used from dfhack-run)
+// tiletypes-here - runs the execute method with the last settings from
+// tiletypes(-command), including brush!
+// (intended to be mapped to a hotkey)
+// tiletypes-here-point - runs the execute method with the last settings from
+// tiletypes(-command), except with a point brush!
+// (intended to be mapped to a hotkey)
+// Options (everything but tiletypes-command):
+// ?, help - print some help
+//
+// Options (tiletypes-command):
+// (anything) - run the given command
+
#include <iostream>
#include <vector>
#include <map>
@@ -25,39 +45,120 @@ using namespace MapExtras;
using namespace DFHack;
using namespace df::enums;
-//zilpin: These two functions were giving me compile errors in VS2008, so I cheated with the C style loop below, just to get it to build.
-//Original code is commented out.
-void tolower(std::string &str)
-{
- //The C++ way...
- //std::transform(str.begin(), str.end(), str.begin(), std::bind2nd(std::ptr_fun(&std::tolower<char> ), std::locale("")));
+CommandHistory tiletypes_hist;
- //The C way...
- for(char *c=(char *)str.c_str(); *c; ++c)
- {
- *c = tolower(*c);
- }
+command_result df_tiletypes (color_ostream &out, vector <string> & parameters);
+command_result df_tiletypes_command (color_ostream &out, vector <string> & parameters);
+command_result df_tiletypes_here (color_ostream &out, vector <string> & parameters);
+command_result df_tiletypes_here_point (color_ostream &out, vector <string> & parameters);
+
+DFHACK_PLUGIN("tiletypes");
+
+DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
+{
+ tiletypes_hist.load("tiletypes.history");
+ commands.push_back(PluginCommand("tiletypes", "Paint map tiles freely, similar to liquids.", df_tiletypes, true));
+ commands.push_back(PluginCommand("tiletypes-command", "Run the given commands (seperated by ' ; '; an empty command is the same as run).", df_tiletypes_command));
+ commands.push_back(PluginCommand("tiletypes-here", "Use the last settings from tiletypes, including brush, at cursor location.", df_tiletypes_here));
+ commands.push_back(PluginCommand("tiletypes-here-point", "Use the last settings from tiletypes, not including brush, at cursor location.", df_tiletypes_here_point));
+ return CR_OK;
}
-void toupper(std::string &str)
+DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
- //std::transform(str.begin(), str.end(), str.begin(), std::bind2nd(std::ptr_fun(&std::toupper<char>), std::locale("")));
- for(char *c=(char *)str.c_str(); *c; ++c)
- {
- *c = toupper(*c);
- }
+ tiletypes_hist.save("tiletypes.history");
+ return CR_OK;
}
-int toint(const std::string &str, int failValue = 0)
+void help( color_ostream & out, std::vector<std::string> &commands, int start, int end)
{
- std::istringstream ss(str);
- int valInt;
- ss >> valInt;
- if (ss.fail())
+ std::string option = commands.size() > start ? commands[start] : "";
+ if (option.empty())
{
- return failValue;
+ out << "Commands:" << std::endl
+ << " quit / q : quit" << std::endl
+ << " filter / f [options] : change filter options" << std::endl
+ << " paint / p [options] : change paint options" << std::endl
+ << " point / p : set point brush" << std::endl
+ << " range / r [w] [h] [z] : set range brush" << std::endl
+ << " block : set block brush" << std::endl
+ << " column : set column brush" << std::endl
+ << " run / (empty) : paint!" << std::endl
+ << std::endl
+ << "Filter/paint options:" << std::endl
+ << " Shape / sh / s: set tile shape information" << std::endl
+ << " Material / mat / m: set tile material information" << std::endl
+ << " Special / sp: set special tile information" << std::endl
+ << " Variant / var / v: set variant tile information" << std::endl
+ << " All / a: set the four above at the same time (no ANY support)" << std::endl
+ << " Designated / d: set designated flag" << std::endl
+ << " Hidden / h: set hidden flag" << std::endl
+ << " Light / l: set light flag" << std::endl
+ << " Subterranean / st: set subterranean flag" << std::endl
+ << " Skyview / sv: set skyview flag" << std::endl
+ << "See help [option] for more information" << std::endl;
+ }
+ else if (option == "shape" || option == "s" ||option == "sh")
+ {
+ out << "Available shapes:" << std::endl
+ << " ANY" << std::endl;
+ FOR_ENUM_ITEMS(tiletype_shape,i)
+ {
+ out << " " << ENUM_KEY_STR(tiletype_shape,i) << std::endl;
+ }
+ }
+ else if (option == "material"|| option == "mat" ||option == "m")
+ {
+ out << "Available materials:" << std::endl
+ << " ANY" << std::endl;
+ FOR_ENUM_ITEMS(tiletype_material,i)
+ {
+ out << " " << ENUM_KEY_STR(tiletype_material,i) << std::endl;
+ }
+ }
+ else if (option == "special" || option == "sp")
+ {
+ out << "Available specials:" << std::endl
+ << " ANY" << std::endl;
+ FOR_ENUM_ITEMS(tiletype_special,i)
+ {
+ out << " " << ENUM_KEY_STR(tiletype_special,i) << std::endl;
+ }
+ }
+ else if (option == "variant" || option == "var" || option == "v")
+ {
+ out << "Available variants:" << std::endl
+ << " ANY" << std::endl;
+ FOR_ENUM_ITEMS(tiletype_variant,i)
+ {
+ out << " " << ENUM_KEY_STR(tiletype_variant,i) << std::endl;
+ }
+ }
+ else if (option == "designated" || option == "d")
+ {
+ out << "Available designated flags:" << std::endl
+ << " ANY, 0, 1" << std::endl;
+ }
+ else if (option == "hidden" || option == "h")
+ {
+ out << "Available hidden flags:" << std::endl
+ << " ANY, 0, 1" << std::endl;
+ }
+ else if (option == "light" || option == "l")
+ {
+ out << "Available light flags:" << std::endl
+ << " ANY, 0, 1" << std::endl;
+ }
+ else if (option == "subterranean" || option == "st")
+ {
+ out << "Available subterranean flags:" << std::endl
+ << " ANY, 0, 1" << std::endl;
+ }
+ else if (option == "skyview" || option == "sv")
+ {
+ out << "Available skyview flags:" << std::endl
+ << " ANY, 0, 1" << std::endl;
}
- return valInt;
}
struct TileType
@@ -217,12 +318,116 @@ std::ostream &operator<<(std::ostream &stream, const TileType &paint)
return stream;
}
-bool processTileType(TileType &paint, const std::string &option, const std::string &value)
+static TileType filter, paint;
+static Brush *brush = new RectangleBrush(1,1);
+
+void printState(color_ostream &out)
{
- std::string val = value;
- toupper(val);
+ out << "Filter: " << filter << std::endl
+ << "Paint: " << paint << std::endl
+ << "Brush: " << brush->str() << std::endl;
+}
+
+//zilpin: These two functions were giving me compile errors in VS2008, so I cheated with the C style loop below, just to get it to build.
+//Original code is commented out.
+void tolower(std::string &str)
+{
+ //The C++ way...
+ //std::transform(str.begin(), str.end(), str.begin(), std::bind2nd(std::ptr_fun(&std::tolower<char> ), std::locale("")));
+
+ //The C way...
+ for(char *c=(char *)str.c_str(); *c; ++c)
+ {
+ *c = tolower(*c);
+ }
+}
+
+void toupper(std::string &str)
+{
+ //std::transform(str.begin(), str.end(), str.begin(), std::bind2nd(std::ptr_fun(&std::toupper<char>), std::locale("")));
+ for(char *c=(char *)str.c_str(); *c; ++c)
+ {
+ *c = toupper(*c);
+ }
+}
+
+int toint(const std::string &str, int failValue = 0)
+{
+ std::istringstream ss(str);
int valInt;
- if (val == "ANY")
+ ss >> valInt;
+ if (ss.fail())
+ {
+ return failValue;
+ }
+ return valInt;
+}
+
+bool tryShape(std::string value, TileType &paint)
+{
+ FOR_ENUM_ITEMS(tiletype_shape,i)
+ {
+ if (value == ENUM_KEY_STR(tiletype_shape,i))
+ {
+ paint.shape = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool tryMaterial(std::string value, TileType &paint)
+{
+ FOR_ENUM_ITEMS(tiletype_material, i)
+ {
+ if (value == ENUM_KEY_STR(tiletype_material,i))
+ {
+ paint.material = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool trySpecial(std::string value, TileType &paint)
+{
+ FOR_ENUM_ITEMS(tiletype_special, i)
+ {
+ if (value == ENUM_KEY_STR(tiletype_special,i))
+ {
+ paint.special = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool tryVariant(std::string value, TileType &paint)
+{
+ FOR_ENUM_ITEMS(tiletype_variant, i)
+ {
+ if (value == ENUM_KEY_STR(tiletype_variant,i))
+ {
+ paint.variant = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool processTileType(color_ostream & out, TileType &paint, std::vector<std::string> &params, int start, int end)
+{
+ if (params.size() < start + 2)
+ {
+ return false;
+ }
+
+ int loc = start;
+ std::string option = params[loc++];
+ std::string value = params[loc++];
+ toupper(value);
+ int valInt;
+ if (value == "ANY")
{
valInt = -1;
}
@@ -241,19 +446,9 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
else
{
- FOR_ENUM_ITEMS(tiletype_shape,i)
+ if (!tryShape(value, paint))
{
- if (val == ENUM_KEY_STR(tiletype_shape,i))
- {
- paint.shape = i;
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- std::cout << "Unknown tile shape: " << value << std::endl;
+ out << "Unknown tile shape: " << value << std::endl;
}
}
}
@@ -266,19 +461,9 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
else
{
- FOR_ENUM_ITEMS(tiletype_material, i)
- {
- if (val == ENUM_KEY_STR(tiletype_material,i))
- {
- paint.material = i;
- found = true;
- break;
- }
- }
-
- if (!found)
+ if (!tryMaterial(value, paint))
{
- std::cout << "Unknown tile material: " << value << std::endl;
+ out << "Unknown tile material: " << value << std::endl;
}
}
}
@@ -291,19 +476,9 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
else
{
- FOR_ENUM_ITEMS(tiletype_special, i)
+ if (!trySpecial(value, paint))
{
- if (val == ENUM_KEY_STR(tiletype_special,i))
- {
- paint.special = i;
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- std::cout << "Unknown tile special: " << value << std::endl;
+ out << "Unknown tile special: " << value << std::endl;
}
}
}
@@ -316,19 +491,9 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
else
{
- FOR_ENUM_ITEMS(tiletype_variant, i)
+ if (!tryVariant(value, paint))
{
- if (val == ENUM_KEY_STR(tiletype_variant,i))
- {
- paint.variant = i;
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- std::cout << "Unknown tile variant: " << value << std::endl;
+ out << "Unknown tile variant: " << value << std::endl;
}
}
}
@@ -341,7 +506,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
else
{
- std::cout << "Unknown designation flag: " << value << std::endl;
+ out << "Unknown designation flag: " << value << std::endl;
}
}
else if (option == "hidden" || option == "h")
@@ -353,7 +518,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
else
{
- std::cout << "Unknown hidden flag: " << value << std::endl;
+ out << "Unknown hidden flag: " << value << std::endl;
}
}
else if (option == "light" || option == "l")
@@ -365,7 +530,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
else
{
- std::cout << "Unknown light flag: " << value << std::endl;
+ out << "Unknown light flag: " << value << std::endl;
}
}
else if (option == "subterranean" || option == "st")
@@ -377,7 +542,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
else
{
- std::cout << "Unknown subterranean flag: " << value << std::endl;
+ out << "Unknown subterranean flag: " << value << std::endl;
}
}
else if (option == "skyview" || option == "sv")
@@ -389,380 +554,386 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
else
{
- std::cout << "Unknown skyview flag: " << value << std::endl;
+ out << "Unknown skyview flag: " << value << std::endl;
+ }
+ }
+ else if (option == "all" || option == "a")
+ {
+ for (; loc < end; loc++)
+ {
+ std::string param = params[loc];
+ toupper(param);
+
+ if (!(tryShape(param, paint) || tryMaterial(param, paint) ||
+ trySpecial(param, paint) || tryVariant(param, paint)))
+ {
+ out << "Unknown description: '" << param << "'" << std::endl;
+ break;
+ }
}
+
+ found = true;
}
else
{
- std::cout << "Unknown option: '" << option << "'" << std::endl;
+ out << "Unknown option: '" << option << "'" << std::endl;
}
return found;
}
-void help( std::ostream & out, const std::string &option)
+command_result executePaintJob(color_ostream &out)
{
- if (option.empty())
+ if (paint.empty())
{
- out << "Commands:" << std::endl
- << " quit / q : quit" << std::endl
- << " filter / f [options] : change filter options" << std::endl
- << " paint / p [options] : change paint options" << std::endl
- << " point / p : set point brush" << std::endl
- << " range / r : set range brush" << std::endl
- << " block : set block brush" << std::endl
- << " column : set column brush" << std::endl
- << std::endl
- << "Filter/paint options:" << std::endl
- << " Shape / sh / s: set tile shape information" << std::endl
- << " Material / mat / m: set tile material information" << std::endl
- << " Special / sp: set special tile information" << std::endl
- << " Variant / var / v: set variant tile information" << std::endl
- << " Designated / d: set designated flag" << std::endl
- << " Hidden / h: set hidden flag" << std::endl
- << " Light / l: set light flag" << std::endl
- << " Subterranean / st: set subterranean flag" << std::endl
- << " Skyview / sv: set skyview flag" << std::endl
- << "See help [option] for more information" << std::endl;
+ out.printerr("Set the paint first.\n");
+ return CR_OK;
}
- else if (option == "shape" || option == "s" ||option == "sh")
+
+ CoreSuspender suspend;
+ uint32_t x_max = 0, y_max = 0, z_max = 0;
+ int32_t x = 0, y = 0, z = 0;
+
+ if (!Maps::IsValid())
{
- out << "Available shapes:" << std::endl
- << " ANY" << std::endl;
- FOR_ENUM_ITEMS(tiletype_shape,i)
- {
- out << " " << ENUM_KEY_STR(tiletype_shape,i) << std::endl;
- }
+ out.printerr("Map is not available!\n");
+ return CR_FAILURE;
}
- else if (option == "material"|| option == "mat" ||option == "m")
+ Maps::getSize(x_max, y_max, z_max);
+
+ if (!Gui::getCursorCoords(x,y,z))
{
- out << "Available materials:" << std::endl
- << " ANY" << std::endl;
- FOR_ENUM_ITEMS(tiletype_material,i)
- {
- out << " " << ENUM_KEY_STR(tiletype_material,i) << std::endl;
- }
+ out.printerr("Can't get cursor coords! Make sure you have a cursor active in DF.\n");
+ return CR_FAILURE;
}
- else if (option == "special" || option == "sp")
+ out.print("Cursor coords: (%d, %d, %d)\n", x, y, z);
+
+ DFHack::DFCoord cursor(x,y,z);
+ MapExtras::MapCache map;
+ coord_vec all_tiles = brush->points(map, cursor);
+ out.print("working...\n");
+
+ for (coord_vec::iterator iter = all_tiles.begin(); iter != all_tiles.end(); ++iter)
{
- out << "Available specials:" << std::endl
- << " ANY" << std::endl;
- FOR_ENUM_ITEMS(tiletype_special,i)
+ const df::tiletype source = map.tiletypeAt(*iter);
+ df::tile_designation des = map.designationAt(*iter);
+
+ if ((filter.shape > -1 && filter.shape != tileShape(source))
+ || (filter.material > -1 && filter.material != tileMaterial(source))
+ || (filter.special > -1 && filter.special != tileSpecial(source))
+ || (filter.variant > -1 && filter.variant != tileVariant(source))
+ || (filter.dig > -1 && (filter.dig != 0) != (des.bits.dig != tile_dig_designation::No))
+ )
{
- out << " " << ENUM_KEY_STR(tiletype_special,i) << std::endl;
+ return CR_OK;
}
- }
- else if (option == "variant" || option == "var" || option == "v")
- {
- out << "Available variants:" << std::endl
- << " ANY" << std::endl;
- FOR_ENUM_ITEMS(tiletype_variant,i)
+
+ df::tiletype_shape shape = paint.shape;
+ if (shape == tiletype_shape::NONE)
{
- out << " " << ENUM_KEY_STR(tiletype_variant,i) << std::endl;
+ shape = tileShape(source);
+ }
+
+ df::tiletype_material material = paint.material;
+ if (material == tiletype_material::NONE)
+ {
+ material = tileMaterial(source);
+ }
+
+ df::tiletype_special special = paint.special;
+ if (special == tiletype_special::NONE)
+ {
+ special = tileSpecial(source);
+ }
+ df::tiletype_variant variant = paint.variant;
+ /*
+ * FIXME: variant should be:
+ * 1. If user variant:
+ * 2. If user variant \belongs target variants
+ * 3. use user variant
+ * 4. Else
+ * 5. use variant 0
+ * 6. If the source variant \belongs target variants
+ * 7 use source variant
+ * 8 ElseIf num target shape/material variants > 1
+ * 9. pick one randomly
+ * 10.Else
+ * 11. use variant 0
+ *
+ * The following variant check has been disabled because it's severely limiting
+ * the usefullness of the tool.
+ */
+ /*
+ if (variant == tiletype_variant::NONE)
+ {
+ variant = tileVariant(source);
+ }
+ */
+ // Remove direction from directionless tiles
+ DFHack::TileDirection direction = tileDirection(source);
+ if (!(material == tiletype_material::RIVER || shape == tiletype_shape::BROOK_BED || shape == tiletype_shape::WALL && (material == tiletype_material::CONSTRUCTION || special == tiletype_special::SMOOTH)))
+ {
+ direction.whole = 0;
+ }
+
+ df::tiletype type = DFHack::findTileType(shape, material, variant, special, direction);
+ // hack for empty space
+ if (shape == tiletype_shape::EMPTY && material == tiletype_material::AIR && variant == tiletype_variant::VAR_1 && special == tiletype_special::NORMAL && direction.whole == 0)
+ {
+ type = tiletype::OpenSpace;
+ }
+ // make sure it's not invalid
+ if(type != tiletype::Void)
+ map.setTiletypeAt(*iter, type);
+
+ if (paint.hidden > -1)
+ {
+ des.bits.hidden = paint.hidden;
+ }
+
+ if (paint.light > -1)
+ {
+ des.bits.light = paint.light;
+ }
+
+ if (paint.subterranean > -1)
+ {
+ des.bits.subterranean = paint.subterranean;
}
+
+ if (paint.skyview > -1)
+ {
+ des.bits.outside = paint.skyview;
+ }
+
+ // Remove liquid from walls, etc
+ if (type != -1 && !DFHack::FlowPassable(type))
+ {
+ des.bits.flow_size = 0;
+ //des.bits.liquid_type = DFHack::liquid_water;
+ //des.bits.water_table = 0;
+ des.bits.flow_forbid = 0;
+ //des.bits.liquid_static = 0;
+ //des.bits.water_stagnant = 0;
+ //des.bits.water_salt = 0;
+ }
+
+ map.setDesignationAt(*iter, des);
}
- else if (option == "designated" || option == "d")
+
+ if (map.WriteAll())
{
- out << "Available designated flags:" << std::endl
- << " ANY, 0, 1" << std::endl;
+ out.print("OK\n");
}
- else if (option == "hidden" || option == "h")
+ else
{
- out << "Available hidden flags:" << std::endl
- << " ANY, 0, 1" << std::endl;
+ out.printerr("Something failed horribly! RUN!\n");
+ return CR_FAILURE;
}
- else if (option == "light" || option == "l")
+}
+
+command_result processCommand(color_ostream &out, std::vector<std::string> &commands, int start, int end, bool & endLoop, bool hasConsole = false)
+{
+ if (commands.size() == start)
{
- out << "Available light flags:" << std::endl
- << " ANY, 0, 1" << std::endl;
+ return executePaintJob(out);
}
- else if (option == "subterranean" || option == "st")
+
+ std::ostringstream ss_o;
+ int loc = start;
+
+ std::string command = commands[loc++];
+ tolower(command);
+
+ if (command == "help" || command == "?")
{
- out << "Available subterranean flags:" << std::endl
- << " ANY, 0, 1" << std::endl;
+ help(out, commands, loc, end);
}
- else if (option == "skyview" || option == "sv")
+ else if (command == "quit" || command == "q")
{
- out << "Available skyview flags:" << std::endl
- << " ANY, 0, 1" << std::endl;
+ endLoop = true;
}
-}
+ else if (command == "filter" || command == "f")
+ {
+ processTileType(out, filter, commands, loc, end);
+ }
+ else if (command == "paint" || (command == "p" && commands.size() > 1))
+ {
+ processTileType(out, paint, commands, loc, end);
+ }
+ else if (command == "point" || command == "p")
+ {
+ delete brush;
+ brush = new RectangleBrush(1,1);
+ }
+ else if (command == "range" || command == "r")
+ {
+ int width = 0, height = 0, z_levels = 0;
-CommandHistory tiletypes_hist;
+ if (commands.size() > loc + 1)
+ {
+ width = toint(commands[loc++]);
+ height = toint(commands[loc++]);
-command_result df_tiletypes (color_ostream &out, vector <string> & parameters);
+ if (commands.size() > loc) {
+ z_levels = toint(commands[loc++]);
+ }
+ }
-DFHACK_PLUGIN("tiletypes");
+ if (width < 1 || height < 1) {
+ if (hasConsole) {
+ Console &con = static_cast<Console&>(out);
+ CommandHistory hist;
-DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
-{
- tiletypes_hist.load("tiletypes.history");
- commands.push_back(PluginCommand("tiletypes", "Paint map tiles freely, similar to liquids.", df_tiletypes, true));
- return CR_OK;
-}
+ ss_o << "Set range width <" << width << "> ";
+ con.lineedit(ss_o.str(),command,hist);
+ width = command == "" ? width : toint(command);
+
+ ss_o.str("");
+ ss_o << "Set range height <" << height << "> ";
+ con.lineedit(ss_o.str(),command,hist);
+ height = command == "" ? height : toint(command);
+
+ ss_o.str("");
+ ss_o << "Set range z-levels <" << z_levels << "> ";
+ con.lineedit(ss_o.str(),command,hist);
+ z_levels = command == "" ? z_levels : toint(command);
+ } else {
+ return CR_WRONG_USAGE;
+ }
+ }
+
+ if (width < 1) width = 1;
+ if (height < 1) height = 1;
+ if (z_levels < 1) z_levels = 1;
+
+ delete brush;
+ brush = new RectangleBrush(width, height, z_levels, 0, 0, 0);
+ }
+ else if (command == "block")
+ {
+ delete brush;
+ brush = new BlockBrush();
+ }
+ else if (command == "column")
+ {
+ delete brush;
+ brush = new ColumnBrush();
+ }
+ else if (command == "run" || command.empty())
+ {
+ executePaintJob(out);
+ }
-DFhackCExport command_result plugin_shutdown ( color_ostream &out )
-{
- tiletypes_hist.save("tiletypes.history");
return CR_OK;
}
-command_result df_tiletypes (color_ostream &out, vector <string> & parameters)
+command_result df_tiletypes (color_ostream &out_, vector <string> & parameters)
{
- uint32_t x_max = 0, y_max = 0, z_max = 0;
- int32_t x = 0, y = 0, z = 0;
-
for(size_t i = 0; i < parameters.size();i++)
{
if(parameters[i] == "help" || parameters[i] == "?")
{
- out.print("This tool allows painting tiles types with a brush, using an optional filter.\n"
- "The tool is interactive, similarly to the liquids tool.\n"
- "Further help is available inside.\n"
+ out_.print("This tool allows painting tiles types with a brush, using an optional filter.\n"
+ "The tool is interactive, similarly to the liquids tool.\n"
+ "Further help is available inside.\n"
);
return CR_OK;
}
}
- if(!out.is_console())
+ if(!out_.is_console())
return CR_FAILURE;
- Console &con = static_cast<Console&>(out);
+ Console &out = static_cast<Console&>(out_);
- TileType filter, paint;
- Brush *brush = new RectangleBrush(1,1);
+ std::vector<std::string> commands;
bool end = false;
- std::string brushname = "point";
- int width = 1, height = 1, z_levels = 1;
- con << "Welcome to the tiletype tool.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl;
- con.printerr("THIS TOOL CAN BE DANGEROUS. YOU'VE BEEN WARNED.\n");
+ out << "Welcome to the tiletype tool.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl;
+ out.printerr("THIS TOOL CAN BE DANGEROUS. YOU'VE BEEN WARNED.\n");
while (!end)
{
- con << "Filter: " << filter << std::endl
- << "Paint: " << paint << std::endl
- << "Brush: " << brushname << std::endl;
+ printState(out);
std::string input = "";
- std::string command = "";
- std::string option = "";
- std::string value = "";
- con.lineedit("tiletypes> ",input,tiletypes_hist);
- tiletypes_hist.add(input);
- std::istringstream ss(input);
- ss >> command >> option >> value;
- tolower(command);
- tolower(option);
+ if (out.lineedit("tiletypes> ",input,tiletypes_hist) == -1)
+ return CR_FAILURE;
- if (command == "help" || command == "?")
- {
- help(con,option);
- }
- else if (command == "quit" || command == "q")
- {
- end = true;
- }
- else if (command == "filter" || command == "f")
- {
- processTileType(filter, option, value);
- }
- else if (command == "paint" || (command == "p" && !option.empty()))
- {
- processTileType(paint, option, value);
- }
- else if (command == "point" || command == "p")
+ commands.clear();
+ Core::cheap_tokenise(input, commands);
+
+ command_result ret = processCommand(out, commands, 0, commands.size(), end, true);
+
+ if (ret != CR_OK)
{
- delete brush;
- brushname = "point";
- brush = new RectangleBrush(1,1);
+ return ret;
}
- else if (command == "range" || command == "r")
- {
- std::stringstream ss;
- CommandHistory hist;
- ss << "Set range width <" << width << "> ";
- con.lineedit(ss.str(),command,hist);
- width = command == "" ? width : toint(command);
- if (width < 1) width = 1;
-
- ss.str("");
- ss << "Set range height <" << height << "> ";
- con.lineedit(ss.str(),command,hist);
- height = command == "" ? height : toint(command);
- if (height < 1) height = 1;
+ }
+ return CR_OK;
+}
- ss.str("");
- ss << "Set range z-levels <" << z_levels << "> ";
- con.lineedit(ss.str(),command,hist);
- z_levels = command == "" ? z_levels : toint(command);
- if (z_levels < 1) z_levels = 1;
+command_result df_tiletypes_command (color_ostream &out, vector <string> & parameters)
+{
+ bool dummy;
+ int start = 0, end = 0;
- delete brush;
- if (width == 1 && height == 1 && z_levels == 1)
- {
- brushname = "point";
- }
- else
- {
- brushname = "range";
+ parameters.push_back(";");
+ for (size_t i = 0; i < parameters.size();i++)
+ {
+ if (parameters[i] == ";") {
+ command_result rv = processCommand(out, parameters, start, end, dummy);
+ if (rv != CR_OK) {
+ return rv;
}
- brush = new RectangleBrush(width, height, z_levels, 0, 0, 0);
+ end++;
+ start = end;
+ } else {
+ end++;
}
- else if (command == "block")
- {
- delete brush;
- brushname = "block";
- brush = new BlockBrush();
- }
- else if (command == "column")
+ }
+
+ return CR_OK;
+}
+
+command_result df_tiletypes_here (color_ostream &out, vector <string> & parameters)
+{
+ for(size_t i = 0; i < parameters.size();i++)
+ {
+ if(parameters[i] == "help" || parameters[i] == "?")
{
- delete brush;
- brushname = "column";
- brush = new ColumnBrush();
+ out << "This command is supposed to be mapped to a hotkey." << endl;
+ out << "It will use the current/last parameters set in tiletypes (including brush settings!)." << endl;
+ return CR_OK;
}
- else if (command.empty())
- {
- if (paint.empty())
- {
- con.printerr("Set the paint first.\n");
- continue;
- }
+ }
- CoreSuspender suspend;
+ out.print("Run tiletypes-here with these parameters: ");
+ printState(out);
- if (!Maps::IsValid())
- {
- con.printerr("Map is not available!\n");
- return CR_FAILURE;
- }
- Maps::getSize(x_max, y_max, z_max);
+ return executePaintJob(out);
+}
- if (!Gui::getCursorCoords(x,y,z))
- {
- con.printerr("Can't get cursor coords! Make sure you have a cursor active in DF.\n");
- return CR_FAILURE;
- }
- con.print("Cursor coords: (%d, %d, %d)\n",x,y,z);
+command_result df_tiletypes_here_point (color_ostream &out, vector <string> & parameters)
+{
+ for(size_t i = 0; i < parameters.size();i++)
+ {
+ if(parameters[i] == "help" || parameters[i] == "?")
+ {
+ out << "This command is supposed to be mapped to a hotkey." << endl;
+ out << "It will use the current/last parameters set in tiletypes (except with a point brush)." << endl;
+ return CR_OK;
+ }
+ }
- DFHack::DFCoord cursor(x,y,z);
- MapExtras::MapCache map;
- coord_vec all_tiles = brush->points(map, cursor);
- con.print("working...\n");
+ Brush *old = brush;
+ brush = new RectangleBrush(1, 1);
- for (coord_vec::iterator iter = all_tiles.begin(); iter != all_tiles.end(); ++iter)
- {
- const df::tiletype source = map.tiletypeAt(*iter);
- df::tile_designation des = map.designationAt(*iter);
-
- if ((filter.shape > -1 && filter.shape != tileShape(source))
- || (filter.material > -1 && filter.material != tileMaterial(source))
- || (filter.special > -1 && filter.special != tileSpecial(source))
- || (filter.variant > -1 && filter.variant != tileVariant(source))
- || (filter.dig > -1 && (filter.dig != 0) != (des.bits.dig != tile_dig_designation::No))
- )
- {
- continue;
- }
-
- df::tiletype_shape shape = paint.shape;
- if (shape == tiletype_shape::NONE)
- {
- shape = tileShape(source);
- }
-
- df::tiletype_material material = paint.material;
- if (material == tiletype_material::NONE)
- {
- material = tileMaterial(source);
- }
-
- df::tiletype_special special = paint.special;
- if (special == tiletype_special::NONE)
- {
- special = tileSpecial(source);
- }
- df::tiletype_variant variant = paint.variant;
- /*
- * FIXME: variant should be:
- * 1. If user variant:
- * 2. If user variant \belongs target variants
- * 3. use user variant
- * 4. Else
- * 5. use variant 0
- * 6. If the source variant \belongs target variants
- * 7 use source variant
- * 8 ElseIf num target shape/material variants > 1
- * 9. pick one randomly
- * 10.Else
- * 11. use variant 0
- *
- * The following variant check has been disabled because it's severely limiting
- * the usefullness of the tool.
- */
- /*
- if (variant == tiletype_variant::NONE)
- {
- variant = tileVariant(source);
- }
- */
- // Remove direction from directionless tiles
- DFHack::TileDirection direction = tileDirection(source);
- if (!(material == tiletype_material::RIVER || shape == tiletype_shape::BROOK_BED || shape == tiletype_shape::WALL && (material == tiletype_material::CONSTRUCTION || special == tiletype_special::SMOOTH))) {
- direction.whole = 0;
- }
-
- df::tiletype type = DFHack::findTileType(shape, material, variant, special, direction);
- // hack for empty space
- if (shape == tiletype_shape::EMPTY && material == tiletype_material::AIR && variant == tiletype_variant::VAR_1 && special == tiletype_special::NORMAL && direction.whole == 0) {
- type = tiletype::OpenSpace;
- }
- // make sure it's not invalid
- if(type != tiletype::Void)
- map.setTiletypeAt(*iter, type);
-
- if (paint.hidden > -1)
- {
- des.bits.hidden = paint.hidden;
- }
-
- if (paint.light > -1)
- {
- des.bits.light = paint.light;
- }
-
- if (paint.subterranean > -1)
- {
- des.bits.subterranean = paint.subterranean;
- }
-
- if (paint.skyview > -1)
- {
- des.bits.outside = paint.skyview;
- }
-
- // Remove liquid from walls, etc
- if (type != -1 && !DFHack::FlowPassable(type))
- {
- des.bits.flow_size = 0;
- //des.bits.liquid_type = DFHack::liquid_water;
- //des.bits.water_table = 0;
- des.bits.flow_forbid = 0;
- //des.bits.liquid_static = 0;
- //des.bits.water_stagnant = 0;
- //des.bits.water_salt = 0;
- }
-
- map.setDesignationAt(*iter, des);
- }
+ out.print("Run tiletypes-here with these parameters: ");
+ printState(out);
- if (map.WriteAll())
- {
- con.print("OK\n");
- }
- else
- {
- con.printerr("Something failed horribly! RUN!\n");
- }
- }
- }
- return CR_OK;
+ command_result rv = executePaintJob(out);
+
+ delete brush;
+ brush = old;
+ return rv;
}