Merge remote-tracking branch 'myk002/myk_tiletypes_options' into develop

develop
lethosor 2021-07-22 00:11:03 -04:00
commit eb9ed4a5a5
No known key found for this signature in database
GPG Key ID: 76A269552F4F58C1
5 changed files with 144 additions and 35 deletions

@ -2702,9 +2702,15 @@ For more details, use ``tiletypes help``.
tiletypes-command tiletypes-command
----------------- -----------------
Runs tiletypes commands, separated by ;. This makes it possible to change Runs tiletypes commands, separated by ``;``. This makes it possible to change
tiletypes modes from a hotkey or via dfhack-run. tiletypes modes from a hotkey or via dfhack-run.
Example::
tiletypes-command p any ; p s wall ; p sp normal
This resets the paint filter to unsmoothed walls.
.. _tiletypes-here: .. _tiletypes-here:
tiletypes-here tiletypes-here
@ -2712,6 +2718,16 @@ tiletypes-here
Apply the current tiletypes options at the in-game cursor position, including Apply the current tiletypes options at the in-game cursor position, including
the brush. Can be used from a hotkey. the brush. Can be used from a hotkey.
Options:
:``-c``, ``--cursor <x>,<y>,<z>``:
Use the specified map coordinates instead of the current cursor position. If
this option is specified, then an active game map cursor is not necessary.
:``-h``, ``--help``:
Show command help text.
:``-q``, ``--quiet``:
Suppress non-error status output.
.. _tiletypes-here-point: .. _tiletypes-here-point:
tiletypes-here-point tiletypes-here-point
@ -2719,6 +2735,8 @@ tiletypes-here-point
Apply the current tiletypes options at the in-game cursor position to a single Apply the current tiletypes options at the in-game cursor position to a single
tile. Can be used from a hotkey. tile. Can be used from a hotkey.
This command supports the same options as `tiletypes-here` above.
.. _tubefill: .. _tubefill:
tubefill tubefill

@ -33,6 +33,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
# Future # Future
## Misc Improvements
- `tiletypes-here`, `tiletypes-here-point`: add --cursor and --quiet options to support non-interactive use cases
# 0.47.05-r2 # 0.47.05-r2
## Fixes ## Fixes

@ -167,7 +167,7 @@ if(BUILD_SUPPORTED)
dfhack_plugin(stocks stocks.cpp) dfhack_plugin(stocks stocks.cpp)
dfhack_plugin(strangemood strangemood.cpp) dfhack_plugin(strangemood strangemood.cpp)
dfhack_plugin(tailor tailor.cpp) dfhack_plugin(tailor tailor.cpp)
dfhack_plugin(tiletypes tiletypes.cpp Brushes.h) dfhack_plugin(tiletypes tiletypes.cpp Brushes.h LINK_LIBRARIES lua)
dfhack_plugin(title-folder title-folder.cpp) dfhack_plugin(title-folder title-folder.cpp)
dfhack_plugin(title-version title-version.cpp) dfhack_plugin(title-version title-version.cpp)
dfhack_plugin(trackstop trackstop.cpp) dfhack_plugin(trackstop trackstop.cpp)

@ -0,0 +1,23 @@
local _ENV = mkmodule('plugins.tiletypes')
local argparse = require('argparse')
local utils = require('utils')
local function parse_cursor(opts, arg)
utils.assign(opts.cursor, argparse.coords(arg))
end
function parse_commandline(opts, ...)
local positionals = argparse.processArgsGetopt({...}, {
{'c', 'cursor', hasArg=true,
handler=function(arg) parse_cursor(opts, arg) end},
{'h', 'help', handler=function() opts.help = true end},
{'q', 'quiet', handler=function() opts.quiet = true end},
})
if positionals[1] == 'help' or positionals[1] == '?' then
opts.help = true
end
end
return _ENV

@ -33,7 +33,10 @@ using std::set;
#include "Console.h" #include "Console.h"
#include "Core.h" #include "Core.h"
#include "DataDefs.h"
#include "DataIdentity.h"
#include "Export.h" #include "Export.h"
#include "LuaTools.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "TileTypes.h" #include "TileTypes.h"
@ -53,6 +56,25 @@ using namespace df::enums;
DFHACK_PLUGIN("tiletypes"); DFHACK_PLUGIN("tiletypes");
REQUIRE_GLOBAL(world); REQUIRE_GLOBAL(world);
struct tiletypes_options {
// whether to display help
bool help = false;
bool quiet = false;
// if set, then use this position instead of the active game cursor
df::coord cursor;
static struct_identity _identity;
};
static const struct_field_info tiletypes_options_fields[] = {
{ struct_field_info::PRIMITIVE, "help", offsetof(tiletypes_options, help), &df::identity_traits<bool>::identity, 0, 0 },
{ struct_field_info::PRIMITIVE, "quiet", offsetof(tiletypes_options, quiet), &df::identity_traits<bool>::identity, 0, 0 },
{ struct_field_info::SUBSTRUCT, "cursor", offsetof(tiletypes_options, cursor), &df::coord::_identity, 0, 0 },
{ struct_field_info::END }
};
struct_identity tiletypes_options::_identity(sizeof(tiletypes_options), &df::allocator_fn<tiletypes_options>, NULL, "tiletypes_options", NULL, tiletypes_options_fields);
CommandHistory tiletypes_hist; CommandHistory tiletypes_hist;
command_result df_tiletypes (color_ostream &out, vector <string> & parameters); command_result df_tiletypes (color_ostream &out, vector <string> & parameters);
@ -713,7 +735,8 @@ bool processTileType(color_ostream & out, TileType &paint, std::vector<std::stri
return found; return found;
} }
command_result executePaintJob(color_ostream &out) command_result executePaintJob(color_ostream &out,
const tiletypes_options &opts)
{ {
if (paint.empty()) if (paint.empty())
{ {
@ -722,27 +745,39 @@ command_result executePaintJob(color_ostream &out)
} }
CoreSuspender suspend; CoreSuspender suspend;
uint32_t x_max = 0, y_max = 0, z_max = 0;
int32_t x = 0, y = 0, z = 0;
if (!Maps::IsValid()) if (!Maps::IsValid())
{ {
out.printerr("Map is not available!\n"); out.printerr("Map is not available!\n");
return CR_FAILURE; return CR_FAILURE;
} }
uint32_t x_max = 0, y_max = 0, z_max = 0;
Maps::getSize(x_max, y_max, z_max); Maps::getSize(x_max, y_max, z_max);
if (!Gui::getCursorCoords(x,y,z)) df::coord cursor;
if (Maps::isValidTilePos(opts.cursor))
{ {
out.printerr("Can't get cursor coords! Make sure you have a cursor active in DF.\n"); cursor = opts.cursor;
return CR_FAILURE; }
else
{
cursor = Gui::getCursorPos();
if (!cursor.isValid())
{
out.printerr("Can't get cursor coords! Make sure you have a cursor active in DF or specify the --cursor option.\n");
return CR_FAILURE;
}
} }
out.print("Cursor coords: (%d, %d, %d)\n", x, y, z);
DFHack::DFCoord cursor(x,y,z); if (!opts.quiet)
out.print("Cursor coords: (%d, %d, %d)\n",
cursor.x, cursor.y, cursor.z);
MapExtras::MapCache map; MapExtras::MapCache map;
coord_vec all_tiles = brush->points(map, cursor); coord_vec all_tiles = brush->points(map, cursor);
out.print("working...\n"); if (!opts.quiet)
out.print("working...\n");
// Force the game to recompute its walkability cache // Force the game to recompute its walkability cache
world->reindex_pathfinding = true; world->reindex_pathfinding = true;
@ -877,12 +912,13 @@ command_result executePaintJob(color_ostream &out)
if (failures > 0) if (failures > 0)
out.printerr("Could not update %d tiles of %zu.\n", failures, all_tiles.size()); out.printerr("Could not update %d tiles of %zu.\n", failures, all_tiles.size());
else else if (!opts.quiet)
out.print("Processed %zu tiles.\n", all_tiles.size()); out.print("Processed %zu tiles.\n", all_tiles.size());
if (map.WriteAll()) if (map.WriteAll())
{ {
out.print("OK\n"); if (!opts.quiet)
out.print("OK\n");
return CR_OK; return CR_OK;
} }
else else
@ -894,9 +930,10 @@ command_result executePaintJob(color_ostream &out)
command_result processCommand(color_ostream &out, std::vector<std::string> &commands, int start, int end, bool & endLoop, bool hasConsole = false) command_result processCommand(color_ostream &out, std::vector<std::string> &commands, int start, int end, bool & endLoop, bool hasConsole = false)
{ {
tiletypes_options opts;
if (commands.size() == size_t(start)) if (commands.size() == size_t(start))
{ {
return executePaintJob(out); return executePaintJob(out, opts);
} }
int loc = start; int loc = start;
@ -951,7 +988,7 @@ command_result processCommand(color_ostream &out, std::vector<std::string> &comm
} }
else if (command == "run" || command.empty()) else if (command == "run" || command.empty())
{ {
executePaintJob(out); executePaintJob(out, opts);
} }
return CR_OK; return CR_OK;
@ -1028,43 +1065,71 @@ command_result df_tiletypes_command (color_ostream &out, vector <string> & param
return CR_OK; return CR_OK;
} }
static bool get_options(color_ostream &out,
tiletypes_options &opts,
const vector<string> &parameters)
{
auto L = Lua::Core::State;
Lua::StackUnwinder top(L);
if (!lua_checkstack(L, parameters.size() + 2) ||
!Lua::PushModulePublic(
out, L, "plugins.tiletypes", "parse_commandline"))
{
out.printerr("Failed to load tiletypes Lua code\n");
return false;
}
Lua::Push(L, &opts);
for (const string &param : parameters)
Lua::Push(L, param);
if (!Lua::SafeCall(out, L, parameters.size() + 1, 0))
return false;
return true;
}
command_result df_tiletypes_here (color_ostream &out, vector <string> & parameters) command_result df_tiletypes_here (color_ostream &out, vector <string> & parameters)
{ {
for(size_t i = 0; i < parameters.size();i++) tiletypes_options opts;
if (!get_options(out, opts, parameters) || opts.help)
{ {
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 (including brush settings!)." << endl;
out << "This command is supposed to be mapped to a hotkey." << endl; return opts.help ? CR_OK : CR_FAILURE;
out << "It will use the current/last parameters set in tiletypes (including brush settings!)." << endl;
return CR_OK;
}
} }
out.print("Run tiletypes-here with these parameters: "); if (!opts.quiet)
printState(out); {
out.print("Run tiletypes-here with these parameters: ");
printState(out);
}
return executePaintJob(out); return executePaintJob(out, opts);
} }
command_result df_tiletypes_here_point (color_ostream &out, vector <string> & parameters) command_result df_tiletypes_here_point (color_ostream &out, vector <string> & parameters)
{ {
for(size_t i = 0; i < parameters.size();i++) tiletypes_options opts;
if (!get_options(out, opts, parameters) || opts.help)
{ {
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;
out << "This command is supposed to be mapped to a hotkey." << endl; return opts.help ? CR_OK : CR_FAILURE;
out << "It will use the current/last parameters set in tiletypes (except with a point brush)." << endl;
return CR_OK;
}
} }
Brush *old = brush; Brush *old = brush;
brush = new RectangleBrush(1, 1); brush = new RectangleBrush(1, 1);
out.print("Run tiletypes-here with these parameters: "); if (!opts.quiet)
printState(out); {
out.print("Run tiletypes-here-point with these parameters: ");
printState(out);
}
command_result rv = executePaintJob(out); command_result rv = executePaintJob(out, opts);
delete brush; delete brush;
brush = old; brush = old;