diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 56c1f8894..e9d918df3 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,8 @@ REQUIRE_GLOBAL(ui); REQUIRE_GLOBAL(gps); REQUIRE_GLOBAL(enabler); +#define CONFIG_PATH "manipulator" + struct SkillLevel { const char *name; @@ -270,10 +273,12 @@ struct UnitInfo int active_index; string squad_effective_name; string squad_info; + bool selected; }; enum altsort_mode { ALTSORT_NAME, + ALTSORT_SELECTED, ALTSORT_PROFESSION_OR_SQUAD, ALTSORT_STRESS, ALTSORT_ARRIVAL, @@ -376,8 +381,14 @@ bool sortBySkill (const UnitInfo *d1, const UnitInfo *d2) return false; } +bool sortBySelected (const UnitInfo *d1, const UnitInfo *d2) +{ + return descending ? (d1->selected > d2->selected) : (d1->selected < d2->selected); +} + enum display_columns { DISP_COLUMN_STRESS, + DISP_COLUMN_SELECTED, DISP_COLUMN_NAME, DISP_COLUMN_PROFESSION_OR_SQUAD, DISP_COLUMN_LABORS, @@ -414,6 +425,7 @@ protected: bool do_refresh_names; int first_row, sel_row, num_rows; int first_column, sel_column; + int last_selection; int col_widths[DISP_COLUMN_MAX]; int col_offsets[DISP_COLUMN_MAX]; @@ -443,6 +455,7 @@ viewscreen_unitlaborsst::viewscreen_unitlaborsst(vector &src, int cur cur->unit = unit; cur->allowEdit = true; + cur->selected = false; cur->active_index = active_idx[unit]; if (!Units::isOwnRace(unit)) @@ -481,6 +494,8 @@ viewscreen_unitlaborsst::viewscreen_unitlaborsst(vector &src, int cur // don't scroll beyond the end if (first_row > units.size() - num_rows) first_row = units.size() - num_rows; + + last_selection = -1; } void viewscreen_unitlaborsst::refreshNames() @@ -521,6 +536,8 @@ void viewscreen_unitlaborsst::calcSize() int col_maxwidth[DISP_COLUMN_MAX]; col_minwidth[DISP_COLUMN_STRESS] = 6; col_maxwidth[DISP_COLUMN_STRESS] = 6; + col_minwidth[DISP_COLUMN_SELECTED] = 1; + col_maxwidth[DISP_COLUMN_SELECTED] = 1; col_minwidth[DISP_COLUMN_NAME] = 16; col_maxwidth[DISP_COLUMN_NAME] = 16; // adjusted in the loop below col_minwidth[DISP_COLUMN_PROFESSION_OR_SQUAD] = 10; @@ -799,6 +816,17 @@ void viewscreen_unitlaborsst::feed(set *events) } break; + case DISP_COLUMN_SELECTED: + if (enabler->mouse_lbut || enabler->mouse_rbut) + { + input_sort = ALTSORT_SELECTED; + if (enabler->mouse_lbut) + events->insert(interface_key::SECONDSCROLL_PAGEUP); + if (enabler->mouse_rbut) + events->insert(interface_key::SECONDSCROLL_PAGEDOWN); + } + break; + case DISP_COLUMN_NAME: if (enabler->mouse_lbut || enabler->mouse_rbut) { @@ -839,6 +867,20 @@ void viewscreen_unitlaborsst::feed(set *events) // do nothing break; + case DISP_COLUMN_SELECTED: + // left-click to select, right-click to extend selection + if (enabler->mouse_lbut) + { + input_row = click_unit; + events->insert(interface_key::CUSTOM_X); + } + if (enabler->mouse_rbut) + { + input_row = click_unit; + events->insert(interface_key::CUSTOM_SHIFT_X); + } + break; + case DISP_COLUMN_NAME: case DISP_COLUMN_PROFESSION_OR_SQUAD: // left-click to view, right-click to zoom @@ -938,6 +980,9 @@ void viewscreen_unitlaborsst::feed(set *events) case ALTSORT_NAME: std::stable_sort(units.begin(), units.end(), sortByName); break; + case ALTSORT_SELECTED: + std::stable_sort(units.begin(), units.end(), sortBySelected); + break; case ALTSORT_PROFESSION_OR_SQUAD: std::stable_sort(units.begin(), units.end(), show_squad ? sortBySquad : sortByProfession); break; @@ -954,6 +999,9 @@ void viewscreen_unitlaborsst::feed(set *events) switch (altsort) { case ALTSORT_NAME: + altsort = ALTSORT_SELECTED; + break; + case ALTSORT_SELECTED: altsort = ALTSORT_PROFESSION_OR_SQUAD; break; case ALTSORT_PROFESSION_OR_SQUAD: @@ -972,6 +1020,28 @@ void viewscreen_unitlaborsst::feed(set *events) show_squad = !show_squad; } + if (events->count(interface_key::CUSTOM_SHIFT_X)) + { + if (last_selection == -1 || last_selection == input_row) + events->insert(interface_key::CUSTOM_X); + else + { + for (int i = std::min(input_row, last_selection); + i <= std::max(input_row, last_selection); + i++) + { + if (i == last_selection) continue; + units[i]->selected = units[last_selection]->selected; + } + } + } + + if (events->count(interface_key::CUSTOM_X)) + { + cur->selected = !cur->selected; + last_selection = input_row; + } + if (VIRTUAL_CAST_VAR(unitlist, df::viewscreen_unitlistst, parent)) { if (events->count(interface_key::UNITJOB_VIEW) || events->count(interface_key::UNITJOB_ZOOM_CRE)) @@ -1011,6 +1081,7 @@ void viewscreen_unitlaborsst::render() Screen::drawBorder(" Dwarf Manipulator - Manage Labors "); Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_STRESS], 2, "Stress"); + Screen::paintTile(Screen::Pen('\373', 7, 0), col_offsets[DISP_COLUMN_SELECTED], 2); Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_NAME], 2, "Name"); Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_PROFESSION_OR_SQUAD], 2, show_squad ? "Squad" : "Profession"); @@ -1070,6 +1141,11 @@ void viewscreen_unitlaborsst::render() fg = 10; // 2:1 Screen::paintString(Screen::Pen(' ', fg, bg), col_offsets[DISP_COLUMN_STRESS], 4 + row, stress); + if (cur->selected) + Screen::paintTile(Screen::Pen('\373', 10, 0), col_offsets[DISP_COLUMN_SELECTED], 4 + row); + else + Screen::paintTile(Screen::Pen('-', 8, 0), col_offsets[DISP_COLUMN_SELECTED], 4 + row); + fg = 15; if (row_offset == sel_row) { @@ -1204,7 +1280,7 @@ void viewscreen_unitlaborsst::render() canToggle = (cur->allowEdit) && columns[sel_column].isValidLabor(ui->main.fortress_entity); } - int x = 2, y = dim.y - 3; + int x = 2, y = dim.y - 4; OutputString(10, x, y, Screen::getKeyDisplay(interface_key::SELECT)); OutputString(canToggle ? 15 : 8, x, y, ": Toggle labor, "); @@ -1217,7 +1293,7 @@ void viewscreen_unitlaborsst::render() OutputString(10, x, y, Screen::getKeyDisplay(interface_key::UNITJOB_ZOOM_CRE)); OutputString(15, x, y, ": Zoom-Cre"); - x = 2; y = dim.y - 2; + x = 2; y = dim.y - 3; OutputString(10, x, y, Screen::getKeyDisplay(interface_key::LEAVESCREEN)); OutputString(15, x, y, ": Done, "); @@ -1238,6 +1314,9 @@ void viewscreen_unitlaborsst::render() case ALTSORT_NAME: OutputString(15, x, y, "Name"); break; + case ALTSORT_SELECTED: + OutputString(15, x, y, "Selected"); + break; case ALTSORT_PROFESSION_OR_SQUAD: OutputString(15, x, y, show_squad ? "Squad" : "Profession"); break; @@ -1251,6 +1330,11 @@ void viewscreen_unitlaborsst::render() OutputString(15, x, y, "Unknown"); break; } + + x = 2; y = dim.y - 2; + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::CUSTOM_X)); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::CUSTOM_SHIFT_X)); + OutputString(15, x, y, ": Select"); } df::unit *viewscreen_unitlaborsst::getSelectedUnit() @@ -1314,6 +1398,11 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) DFhackCExport command_result plugin_init ( color_ostream &out, vector &commands) { + if (!Filesystem::isdir(CONFIG_PATH) && !Filesystem::mkdir(CONFIG_PATH)) + { + out.printerr("manipulator: Could not create configuration folder: \"%s\"\n", CONFIG_PATH); + return CR_FAILURE; + } return CR_OK; }