|
|
|
@ -21,9 +21,20 @@
|
|
|
|
|
#include "df/ui.h"
|
|
|
|
|
#include "df/ui_build_selector.h"
|
|
|
|
|
#include "df/viewscreen_dwarfmodest.h"
|
|
|
|
|
#include "df/items_other_id.h"
|
|
|
|
|
#include "df/job.h"
|
|
|
|
|
#include "df/world.h"
|
|
|
|
|
#include "df/building_constructionst.h"
|
|
|
|
|
|
|
|
|
|
#include "modules/Gui.h"
|
|
|
|
|
#include "modules/Screen.h"
|
|
|
|
|
#include "modules/Items.h"
|
|
|
|
|
#include "modules/Constructions.h"
|
|
|
|
|
#include "modules/Buildings.h"
|
|
|
|
|
#include "modules/Maps.h"
|
|
|
|
|
|
|
|
|
|
#include "TileTypes.h"
|
|
|
|
|
#include "df/job_item.h"
|
|
|
|
|
|
|
|
|
|
using std::map;
|
|
|
|
|
using std::string;
|
|
|
|
@ -64,6 +75,21 @@ static bool auto_choose_materials = true;
|
|
|
|
|
static bool auto_choose_attempted = true;
|
|
|
|
|
static bool revert_to_last_used_type = false;
|
|
|
|
|
|
|
|
|
|
struct point
|
|
|
|
|
{
|
|
|
|
|
int32_t x, y, z;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static enum t_box_select_mode {SELECT_FIRST, SELECT_SECOND, SELECT_MATERIALS, AUTOSELECT_MATERIALS} box_select_mode = SELECT_FIRST;
|
|
|
|
|
static point box_first, box_second;
|
|
|
|
|
static bool box_select_enabled = false;
|
|
|
|
|
static bool show_box_selection = true;
|
|
|
|
|
static bool hollow_selection = false;
|
|
|
|
|
#define SELECTION_IGNORE_TICKS 10
|
|
|
|
|
static int ignore_selection = SELECTION_IGNORE_TICKS;
|
|
|
|
|
static deque<df::item*> box_select_materials;
|
|
|
|
|
static vector<df::coord> building_sites;
|
|
|
|
|
|
|
|
|
|
static command_result automaterial_cmd(color_ostream &out, vector <string> & parameters)
|
|
|
|
|
{
|
|
|
|
|
return CR_OK;
|
|
|
|
@ -95,6 +121,10 @@ void OutputHotkeyString(int &x, int &y, const char *text, const char *hotkey, bo
|
|
|
|
|
OutputString(color, x, y, display, newline, left_margin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static string int_to_string(int i)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<ostringstream*>( &(ostringstream() << i))->str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool in_material_choice_stage()
|
|
|
|
|
{
|
|
|
|
@ -137,7 +167,7 @@ static inline MaterialDescriptor &get_last_used_material()
|
|
|
|
|
return last_used_material[ui_build_selector->building_subtype];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_last_used_material(MaterialDescriptor &matetial)
|
|
|
|
|
static void set_last_used_material(const MaterialDescriptor &matetial)
|
|
|
|
|
{
|
|
|
|
|
last_used_material[ui_build_selector->building_subtype] = matetial;
|
|
|
|
|
}
|
|
|
|
@ -150,7 +180,7 @@ static MaterialDescriptor &get_last_moved_material()
|
|
|
|
|
return last_moved_material[ui_build_selector->building_subtype];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_last_moved_material(MaterialDescriptor &matetial)
|
|
|
|
|
static void set_last_moved_material(const MaterialDescriptor &matetial)
|
|
|
|
|
{
|
|
|
|
|
last_moved_material[ui_build_selector->building_subtype] = matetial;
|
|
|
|
|
}
|
|
|
|
@ -240,12 +270,86 @@ static bool check_autoselect(MaterialDescriptor &material, bool toggle)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cancel_box_selection()
|
|
|
|
|
{
|
|
|
|
|
if (box_select_mode == SELECT_FIRST)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
box_select_mode = SELECT_FIRST;
|
|
|
|
|
box_select_materials.clear();
|
|
|
|
|
if (!show_box_selection)
|
|
|
|
|
Gui::setDesignationCoords(-1, -1, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool is_valid_building_site(df::coord &pos)
|
|
|
|
|
{
|
|
|
|
|
auto ttype = Maps::getTileType(pos);
|
|
|
|
|
if (!ttype ||
|
|
|
|
|
*ttype == tiletype::Tree ||
|
|
|
|
|
tileMaterial(*ttype) == tiletype_material::CONSTRUCTION ||
|
|
|
|
|
tileMaterial(*ttype) == tiletype_material::AIR ||
|
|
|
|
|
tileMaterial(*ttype) == tiletype_material::CAMPFIRE ||
|
|
|
|
|
tileMaterial(*ttype) == tiletype_material::FIRE ||
|
|
|
|
|
tileMaterial(*ttype) == tiletype_material::MAGMA ||
|
|
|
|
|
tileMaterial(*ttype) == tiletype_material::DRIFTWOOD ||
|
|
|
|
|
tileMaterial(*ttype) == tiletype_material::POOL ||
|
|
|
|
|
tileMaterial(*ttype) == tiletype_material::BROOK ||
|
|
|
|
|
tileMaterial(*ttype) == tiletype_material::RIVER
|
|
|
|
|
)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto current = Buildings::findAtTile(pos);
|
|
|
|
|
if (current)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
df::coord2d size(1,1);
|
|
|
|
|
return Buildings::checkFreeTiles(pos, size, NULL, false, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool designate_new_construction(df::coord &pos, df::construction_type &type, df::item *item)
|
|
|
|
|
{
|
|
|
|
|
auto newinst = Buildings::allocInstance(pos, building_type::Construction, type);
|
|
|
|
|
if (!newinst)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
vector<df::item*> items;
|
|
|
|
|
items.push_back(item);
|
|
|
|
|
|
|
|
|
|
if (!Buildings::constructWithItems(newinst, items))
|
|
|
|
|
{
|
|
|
|
|
delete newinst;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct jobutils_hook : public df::viewscreen_dwarfmodest
|
|
|
|
|
{
|
|
|
|
|
typedef df::viewscreen_dwarfmodest interpose_base;
|
|
|
|
|
|
|
|
|
|
void send_key(const df::interface_key &key)
|
|
|
|
|
{
|
|
|
|
|
set< df::interface_key > keys;
|
|
|
|
|
keys.insert(key);
|
|
|
|
|
this->feed(&keys);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool select_material_at_index(size_t i)
|
|
|
|
|
{
|
|
|
|
|
ui_build_selector->sel_index = i;
|
|
|
|
|
std::set< df::interface_key > keys;
|
|
|
|
|
keys.insert(df::interface_key::SELECT_ALL);
|
|
|
|
|
this->feed(&keys);
|
|
|
|
|
return !in_material_choice_stage();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool choose_materials()
|
|
|
|
|
{
|
|
|
|
|
if (!auto_choose_materials || get_curr_constr_prefs().size() == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
size_t size = ui_build_selector->choices.size();
|
|
|
|
|
for (size_t i = 0; i < size; i++)
|
|
|
|
|
{
|
|
|
|
@ -253,31 +357,241 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest
|
|
|
|
|
size_t j;
|
|
|
|
|
if (is_material_in_autoselect(j, material))
|
|
|
|
|
{
|
|
|
|
|
ui_build_selector->sel_index = i;
|
|
|
|
|
std::set< df::interface_key > keys;
|
|
|
|
|
keys.insert(df::interface_key::SELECT_ALL);
|
|
|
|
|
this->feed(&keys);
|
|
|
|
|
if (!in_material_choice_stage())
|
|
|
|
|
return true;
|
|
|
|
|
return select_material_at_index(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input))
|
|
|
|
|
bool populate_box_materials(vector<MaterialDescriptor> &gen_materials)
|
|
|
|
|
{
|
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
|
|
if (gen_materials.size() == 0)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
if (ui_build_selector->is_grouped)
|
|
|
|
|
send_key(interface_key::BUILDING_EXPAND_CONTRACT);
|
|
|
|
|
|
|
|
|
|
size_t size = ui_build_selector->choices.size();
|
|
|
|
|
vector<MaterialDescriptor>::iterator gen_material;
|
|
|
|
|
for (size_t i = 0; i < size; i++)
|
|
|
|
|
{
|
|
|
|
|
if (VIRTUAL_CAST_VAR(spec, df::build_req_choice_specst, ui_build_selector->choices[i]))
|
|
|
|
|
{
|
|
|
|
|
for (gen_material = gen_materials.begin(); gen_material != gen_materials.end(); gen_material++)
|
|
|
|
|
{
|
|
|
|
|
if (gen_material->item_type == spec->candidate->getType() &&
|
|
|
|
|
gen_material->item_subtype == spec->candidate->getSubtype() &&
|
|
|
|
|
gen_material->type == spec->candidate->getActualMaterial() &&
|
|
|
|
|
gen_material->index == spec->candidate->getActualMaterialIndex())
|
|
|
|
|
{
|
|
|
|
|
box_select_materials.push_back(spec->candidate);
|
|
|
|
|
result = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
send_key(interface_key::BUILDING_EXPAND_CONTRACT);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void draw_box_selection()
|
|
|
|
|
{
|
|
|
|
|
if (!box_select_enabled)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
df::coord vport = Gui::getViewportPos();
|
|
|
|
|
|
|
|
|
|
//Even if selection drawing is disabled, paint a green cursor as we can place box selection anywhere
|
|
|
|
|
|
|
|
|
|
if (box_select_mode == SELECT_FIRST || (!show_box_selection && box_select_mode == SELECT_SECOND))
|
|
|
|
|
{
|
|
|
|
|
int32_t x, y, z;
|
|
|
|
|
|
|
|
|
|
if (!Gui::getCursorCoords(x, y, z))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
x = x - vport.x + 1;
|
|
|
|
|
y = y - vport.y + 1;
|
|
|
|
|
OutputString(COLOR_GREEN, x, y, "X");
|
|
|
|
|
}
|
|
|
|
|
else if (show_box_selection && box_select_mode == SELECT_SECOND)
|
|
|
|
|
{
|
|
|
|
|
if (!Gui::getCursorCoords(box_second.x, box_second.y, box_second.z))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
int32_t xD = (box_second.x > box_first.x) ? 1 : -1;
|
|
|
|
|
int32_t yD = (box_second.y > box_first.y) ? 1 : -1;
|
|
|
|
|
for (int32_t xB = box_first.x; (xD > 0) ? (xB <= box_second.x) : (xB >= box_second.x); xB += xD)
|
|
|
|
|
{
|
|
|
|
|
for (int32_t yB = box_first.y; (yD > 0) ? (yB <= box_second.y) : (yB >= box_second.y); yB += yD)
|
|
|
|
|
{
|
|
|
|
|
if (hollow_selection && !(xB == box_first.x || xB == box_second.x || yB == box_first.y || yB == box_second.y))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
int8_t color = (xB == box_second.x && yB == box_second.y) ? COLOR_GREEN : COLOR_BROWN;
|
|
|
|
|
|
|
|
|
|
int32_t x = xB - vport.x + 1;
|
|
|
|
|
int32_t y = yB - vport.y + 1;
|
|
|
|
|
OutputString(color, x, y, "X");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (show_box_selection && box_select_mode == SELECT_MATERIALS)
|
|
|
|
|
{
|
|
|
|
|
for (vector<df::coord>::iterator it = building_sites.begin(); it != building_sites.end(); it++)
|
|
|
|
|
{
|
|
|
|
|
int32_t x = it->x - vport.x + 1;
|
|
|
|
|
int32_t y = it->y - vport.y + 1;
|
|
|
|
|
OutputString(COLOR_GREEN, x, y, "X");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void find_valid_building_sites()
|
|
|
|
|
{
|
|
|
|
|
building_sites.clear();
|
|
|
|
|
|
|
|
|
|
int xD = (box_second.x > box_first.x) ? 1 : -1;
|
|
|
|
|
int yD = (box_second.y > box_first.y) ? 1 : -1;
|
|
|
|
|
for (int32_t xB = box_first.x; (xD > 0) ? (xB <= box_second.x) : (xB >= box_second.x); xB += xD)
|
|
|
|
|
{
|
|
|
|
|
for (int32_t yB = box_first.y; (yD > 0) ? (yB <= box_second.y) : (yB >= box_second.y); yB += yD)
|
|
|
|
|
{
|
|
|
|
|
if (hollow_selection && !(xB == box_first.x || xB == box_second.x || yB == box_first.y || yB == box_second.y))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
df::coord pos(xB, yB, box_second.z);
|
|
|
|
|
if (is_valid_building_site(pos))
|
|
|
|
|
building_sites.push_back(pos);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void apply_box_selection(bool new_start)
|
|
|
|
|
{
|
|
|
|
|
static bool saved_revert_setting = false;
|
|
|
|
|
static bool auto_select_applied = false;
|
|
|
|
|
|
|
|
|
|
box_select_mode = SELECT_MATERIALS;
|
|
|
|
|
if (new_start)
|
|
|
|
|
{
|
|
|
|
|
find_valid_building_sites();
|
|
|
|
|
saved_revert_setting = revert_to_last_used_type;
|
|
|
|
|
revert_to_last_used_type = true;
|
|
|
|
|
auto_select_applied = false;
|
|
|
|
|
box_select_materials.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (building_sites.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
df::coord pos = building_sites.back();
|
|
|
|
|
building_sites.pop_back();
|
|
|
|
|
if (box_select_materials.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
df::construction_type type = (df::construction_type) ui_build_selector->building_subtype;
|
|
|
|
|
df::item *item = NULL;
|
|
|
|
|
while (box_select_materials.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
item = box_select_materials.front();
|
|
|
|
|
if (!item->flags.bits.in_job)
|
|
|
|
|
break;
|
|
|
|
|
box_select_materials.pop_front();
|
|
|
|
|
item = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (designate_new_construction(pos, type, item))
|
|
|
|
|
{
|
|
|
|
|
box_select_materials.pop_front();
|
|
|
|
|
box_select_mode = AUTOSELECT_MATERIALS;
|
|
|
|
|
send_key(interface_key::LEAVESCREEN); //Must do this to register items in use
|
|
|
|
|
send_key(hotkeys[type]);
|
|
|
|
|
box_select_mode = SELECT_MATERIALS;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gui::setCursorCoords(pos.x, pos.y, box_second.z);
|
|
|
|
|
send_key(interface_key::CURSOR_DOWN_Z);
|
|
|
|
|
send_key(interface_key::CURSOR_UP_Z);
|
|
|
|
|
send_key(df::interface_key::SELECT);
|
|
|
|
|
|
|
|
|
|
if (in_material_choice_stage())
|
|
|
|
|
{
|
|
|
|
|
if (!auto_select_applied)
|
|
|
|
|
{
|
|
|
|
|
auto_select_applied = true;
|
|
|
|
|
if (populate_box_materials(preferred_materials[ui_build_selector->building_subtype]))
|
|
|
|
|
{
|
|
|
|
|
building_sites.push_back(pos); //Retry current tile with auto select
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
last_used_moved = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gui::setCursorCoords(box_second.x, box_second.y, box_second.z);
|
|
|
|
|
send_key(interface_key::CURSOR_DOWN_Z);
|
|
|
|
|
send_key(interface_key::CURSOR_UP_Z);
|
|
|
|
|
|
|
|
|
|
revert_to_last_used_type = saved_revert_setting;
|
|
|
|
|
if (!revert_to_last_used_type)
|
|
|
|
|
{
|
|
|
|
|
send_key(df::interface_key::LEAVESCREEN);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cancel_box_selection();
|
|
|
|
|
hollow_selection = false;
|
|
|
|
|
ignore_selection = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void reset_existing_selection()
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
|
|
|
{
|
|
|
|
|
send_key(df::interface_key::BUILDING_DIM_Y_DOWN);
|
|
|
|
|
send_key(df::interface_key::BUILDING_DIM_X_DOWN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handle_input(set<df::interface_key> *input)
|
|
|
|
|
{
|
|
|
|
|
if (in_material_choice_stage())
|
|
|
|
|
{
|
|
|
|
|
if (input->count(interface_key::LEAVESCREEN))
|
|
|
|
|
{
|
|
|
|
|
box_select_mode = SELECT_FIRST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MaterialDescriptor material = get_material_in_list(ui_build_selector->sel_index);
|
|
|
|
|
if (material.valid)
|
|
|
|
|
{
|
|
|
|
|
if (input->count(interface_key::SELECT) || input->count(interface_key::SEC_SELECT))
|
|
|
|
|
{
|
|
|
|
|
if (get_last_moved_material().matches(material))
|
|
|
|
|
last_used_moved = false;
|
|
|
|
|
last_used_moved = false; //Keep selected material on top
|
|
|
|
|
|
|
|
|
|
set_last_used_material(material);
|
|
|
|
|
|
|
|
|
|
if (box_select_enabled && input->count(interface_key::SEC_SELECT) && ui_build_selector->is_grouped)
|
|
|
|
|
{
|
|
|
|
|
auto curr_index = ui_build_selector->sel_index;
|
|
|
|
|
vector<MaterialDescriptor> gen_material;
|
|
|
|
|
gen_material.push_back(get_material_in_list(curr_index));
|
|
|
|
|
box_select_materials.clear();
|
|
|
|
|
populate_box_materials(gen_material);
|
|
|
|
|
ui_build_selector->sel_index = curr_index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (input->count(interface_key::CUSTOM_A))
|
|
|
|
|
{
|
|
|
|
@ -296,39 +610,141 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest
|
|
|
|
|
{
|
|
|
|
|
revert_to_last_used_type = !revert_to_last_used_type;
|
|
|
|
|
}
|
|
|
|
|
else if (input->count(interface_key::CUSTOM_B))
|
|
|
|
|
{
|
|
|
|
|
box_select_enabled = !box_select_enabled;
|
|
|
|
|
if (!box_select_enabled)
|
|
|
|
|
cancel_box_selection();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (input->count(interface_key::LEAVESCREEN))
|
|
|
|
|
{
|
|
|
|
|
switch (box_select_mode)
|
|
|
|
|
{
|
|
|
|
|
case SELECT_FIRST:
|
|
|
|
|
case SELECT_SECOND:
|
|
|
|
|
cancel_box_selection();
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (box_select_enabled &&
|
|
|
|
|
(ui_build_selector->building_subtype == construction_type::Wall ||
|
|
|
|
|
ui_build_selector->building_subtype == construction_type::Fortification ||
|
|
|
|
|
ui_build_selector->building_subtype == construction_type::Floor))
|
|
|
|
|
{
|
|
|
|
|
if (input->count(interface_key::SELECT))
|
|
|
|
|
{
|
|
|
|
|
switch (box_select_mode)
|
|
|
|
|
{
|
|
|
|
|
case SELECT_FIRST:
|
|
|
|
|
if (!Gui::getCursorCoords(box_first.x, box_first.y, box_first.z))
|
|
|
|
|
{
|
|
|
|
|
cancel_box_selection();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
box_select_mode = SELECT_SECOND;
|
|
|
|
|
if (!show_box_selection)
|
|
|
|
|
Gui::setDesignationCoords(box_first.x, box_first.y, box_first.z);
|
|
|
|
|
input->clear();
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case SELECT_SECOND:
|
|
|
|
|
if (!Gui::getCursorCoords(box_second.x, box_second.y, box_second.z))
|
|
|
|
|
{
|
|
|
|
|
cancel_box_selection();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
cancel_box_selection();
|
|
|
|
|
input->clear();
|
|
|
|
|
apply_box_selection(true);
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (input->count(interface_key::CUSTOM_X))
|
|
|
|
|
{
|
|
|
|
|
show_box_selection = !show_box_selection;
|
|
|
|
|
if (box_select_mode == SELECT_SECOND)
|
|
|
|
|
{
|
|
|
|
|
if (show_box_selection)
|
|
|
|
|
{
|
|
|
|
|
Gui::setDesignationCoords(-1, -1, -1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Gui::setDesignationCoords(box_first.x, box_first.y, box_first.z);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (input->count(interface_key::CUSTOM_H))
|
|
|
|
|
{
|
|
|
|
|
hollow_selection = !hollow_selection;
|
|
|
|
|
}
|
|
|
|
|
else if (input->count(interface_key::BUILDING_DIM_Y_UP) ||
|
|
|
|
|
input->count(interface_key::BUILDING_DIM_Y_DOWN) ||
|
|
|
|
|
input->count(interface_key::BUILDING_DIM_X_UP) ||
|
|
|
|
|
input->count(interface_key::BUILDING_DIM_X_DOWN))
|
|
|
|
|
{
|
|
|
|
|
input->clear();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input))
|
|
|
|
|
{
|
|
|
|
|
if (ignore_selection < SELECTION_IGNORE_TICKS)
|
|
|
|
|
{
|
|
|
|
|
//FIXME: Sometimes there's an extra ENTER key left over after box selection
|
|
|
|
|
ignore_selection = SELECTION_IGNORE_TICKS;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (box_select_mode != AUTOSELECT_MATERIALS)
|
|
|
|
|
handle_input(input);
|
|
|
|
|
|
|
|
|
|
int16_t last_used_constr_subtype = (in_material_choice_stage()) ? ui_build_selector->building_subtype : -1;
|
|
|
|
|
INTERPOSE_NEXT(feed)(input);
|
|
|
|
|
|
|
|
|
|
if (revert_to_last_used_type &&
|
|
|
|
|
last_used_constr_subtype >= 0 &&
|
|
|
|
|
!in_material_choice_stage() &&
|
|
|
|
|
in_type_choice_stage() &&
|
|
|
|
|
hotkeys.find(last_used_constr_subtype) != hotkeys.end())
|
|
|
|
|
{
|
|
|
|
|
input->clear();
|
|
|
|
|
input->insert(hotkeys[last_used_constr_subtype]);
|
|
|
|
|
this->feed(input);
|
|
|
|
|
INTERPOSE_NEXT(feed)(input);
|
|
|
|
|
|
|
|
|
|
if (box_select_mode == SELECT_MATERIALS)
|
|
|
|
|
{
|
|
|
|
|
apply_box_selection(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, render, ())
|
|
|
|
|
{
|
|
|
|
|
if (ignore_selection < SELECTION_IGNORE_TICKS)
|
|
|
|
|
{
|
|
|
|
|
++ignore_selection;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (in_material_choice_stage())
|
|
|
|
|
{
|
|
|
|
|
if (!last_used_moved && ui_build_selector->is_grouped)
|
|
|
|
|
{
|
|
|
|
|
if (auto_choose_materials && get_curr_constr_prefs().size() > 0)
|
|
|
|
|
{
|
|
|
|
|
last_used_moved = true;
|
|
|
|
|
if (choose_materials())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
last_used_moved = true;
|
|
|
|
|
move_material_to_top(get_last_used_material());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -344,15 +760,23 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest
|
|
|
|
|
|
|
|
|
|
INTERPOSE_NEXT(render)();
|
|
|
|
|
|
|
|
|
|
draw_box_selection();
|
|
|
|
|
|
|
|
|
|
if (in_type_choice_stage())
|
|
|
|
|
{
|
|
|
|
|
cancel_box_selection();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto dims = Gui::getDwarfmodeViewDims();
|
|
|
|
|
int left_margin = dims.menu_x1 + 1;
|
|
|
|
|
int x = left_margin;
|
|
|
|
|
int y = 25;
|
|
|
|
|
if (in_material_choice_stage())
|
|
|
|
|
{
|
|
|
|
|
MaterialDescriptor material = get_material_in_list(ui_build_selector->sel_index);
|
|
|
|
|
if (material.valid)
|
|
|
|
|
{
|
|
|
|
|
int left_margin = gps->dimx - 30;
|
|
|
|
|
int x = left_margin;
|
|
|
|
|
int y = 25;
|
|
|
|
|
|
|
|
|
|
string toggle_string = "Enable";
|
|
|
|
|
string title = "Disabled";
|
|
|
|
|
if (check_autoselect(material, false))
|
|
|
|
@ -363,20 +787,59 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest
|
|
|
|
|
|
|
|
|
|
OutputString(COLOR_BROWN, x, y, "DFHack Autoselect: " + title, true, left_margin);
|
|
|
|
|
OutputHotkeyString(x, y, toggle_string.c_str(), "a", true, left_margin);
|
|
|
|
|
|
|
|
|
|
if (box_select_mode == SELECT_MATERIALS)
|
|
|
|
|
{
|
|
|
|
|
++y;
|
|
|
|
|
OutputString(COLOR_BROWN, x, y, "Construction:", true, left_margin);
|
|
|
|
|
OutputString(COLOR_WHITE, x, y, int_to_string(building_sites.size() + 1) + " tiles to fill", true, left_margin);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (in_placement_stage() && ui_build_selector->building_subtype != 7)
|
|
|
|
|
else if (in_placement_stage() && ui_build_selector->building_subtype < 7)
|
|
|
|
|
{
|
|
|
|
|
int left_margin = gps->dimx - 30;
|
|
|
|
|
int x = left_margin;
|
|
|
|
|
int y = 25;
|
|
|
|
|
|
|
|
|
|
string autoselect_toggle_string = (auto_choose_materials) ? "Disable Auto Mat-select" : "Enable Auto Mat-select";
|
|
|
|
|
string revert_toggle_string = (revert_to_last_used_type) ? "Disable Auto Type-select" : "Enable Auto Type-select";
|
|
|
|
|
|
|
|
|
|
OutputString(COLOR_BROWN, x, y, "DFHack Options", true, left_margin);
|
|
|
|
|
OutputHotkeyString(x, y, autoselect_toggle_string.c_str(), "a", true, left_margin);
|
|
|
|
|
OutputHotkeyString(x, y, revert_toggle_string.c_str(), "t", true, left_margin);
|
|
|
|
|
|
|
|
|
|
if (ui_build_selector->building_subtype == construction_type::Wall ||
|
|
|
|
|
ui_build_selector->building_subtype == construction_type::Fortification ||
|
|
|
|
|
ui_build_selector->building_subtype == construction_type::Floor)
|
|
|
|
|
{
|
|
|
|
|
++y;
|
|
|
|
|
OutputHotkeyString(x, y, (box_select_enabled) ? "Disable Box Select" : "Enable Box Select", "b", true, left_margin);
|
|
|
|
|
if (box_select_enabled)
|
|
|
|
|
{
|
|
|
|
|
OutputHotkeyString(x, y, (show_box_selection) ? "Disable Box Marking" : "Enable Box Marking", "x", true, left_margin);
|
|
|
|
|
OutputHotkeyString(x, y, (hollow_selection) ? "Make Solid" : "Make Hollow", "h", true, left_margin);
|
|
|
|
|
}
|
|
|
|
|
++y;
|
|
|
|
|
if (box_select_enabled)
|
|
|
|
|
{
|
|
|
|
|
Screen::Pen pen(' ',COLOR_BLACK);
|
|
|
|
|
y = dims.y1 + 2;
|
|
|
|
|
Screen::fillRect(pen, x, y, dims.menu_x2, y + 17);
|
|
|
|
|
|
|
|
|
|
y += 2;
|
|
|
|
|
switch (box_select_mode)
|
|
|
|
|
{
|
|
|
|
|
case SELECT_FIRST:
|
|
|
|
|
OutputString(COLOR_BROWN, x, y, "Choose first corner", true, left_margin);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SELECT_SECOND:
|
|
|
|
|
OutputString(COLOR_GREEN, x, y, "Choose second corner", true, left_margin);
|
|
|
|
|
int cx = box_first.x;
|
|
|
|
|
int cy = box_first.y;
|
|
|
|
|
OutputString(COLOR_BROWN, cx, cy, "X");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OutputString(COLOR_BROWN, x, ++y, "Ignore Building Restrictions", true, left_margin);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|