Add dialog allowing you to alter the scenario's graphics sheets from within the scenario editor

- You can copy/paste images into the sheet, or import/export to/from png files

Also:
- Picture controls in the dialog engine have a new "scaled" flag; if set, the picture will be scaled into the provided bounds rather than overflowing. Currently, only full sheets honour the setting.
This commit is contained in:
2015-06-15 16:20:03 -04:00
parent 9d59b80a5c
commit e055b97c9f
18 changed files with 297 additions and 51 deletions

View File

@@ -4,6 +4,7 @@
#include <functional>
#include <numeric>
#include <algorithm>
#include <unordered_map>
#include <boost/lexical_cast.hpp>
#include "scen.global.hpp"
#include "scenario.hpp"
@@ -24,6 +25,7 @@
#include "stack.hpp"
#include "spell.hpp"
#include "mathutil.hpp"
#include "winutil.hpp"
extern short cen_x, cen_y,cur_town;
extern bool mouse_button_held;
@@ -3305,3 +3307,103 @@ void edit_custom_pics_types() {
}
pic_dlg.run();
}
void set_dlg_custom_sheet(cDialog& me, size_t sheet) {
me["num"].setTextToNum(sheet);
dynamic_cast<cPict&>(me["sheet"]).setPict(sheet, PIC_FULL);
}
void edit_custom_sheets() {
// TODO: What about "disconnected" sheets? eg, we have sheets 0-6, but also sheet 100.
// First, make sure we even have custom graphics! Also make sure they're not legacy format.
if(spec_scen_g.numSheets < 1) {
} else if(spec_scen_g.is_old) {
spec_scen_g.convert_sheets();
}
set_cursor(watch_curs);
// Get image data from the sheets in memory
size_t cur = 0;
std::unordered_map<size_t, sf::Image> sheets;
for(size_t i = 0; i < spec_scen_g.numSheets; i++) {
sheets[i] = spec_scen_g.sheets[i].copyToImage();
}
auto sheetsSave = sheets;
using namespace std::placeholders;
cDialog pic_dlg("graphic-sheets");
pic_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, _1, false));
pic_dlg["okay"].attachClickHandler(std::bind(&cDialog::toast, _1, true));
pic_dlg["copy"].attachClickHandler([&sheets,&cur](cDialog&, std::string, eKeyMod) -> bool {
set_clipboard_img(sheets[cur]);
return true;
});
pic_dlg["paste"].attachClickHandler([&sheets,&cur](cDialog&, std::string, eKeyMod) -> bool {
auto img = get_clipboard_img();
if(img == nullptr) {
beep();
return true;
}
sheets[cur] = *img;
spec_scen_g.replace_sheet(cur, *img);
return true;
});
pic_dlg["open"].attachClickHandler([&sheets,&cur](cDialog&, std::string, eKeyMod) -> bool {
fs::path fpath = nav_get_rsrc({"png", "bmp", "jpg", "jpeg", "gif", "psd"});
if(fpath.empty()) return true;
sf::Image img;
if(!img.loadFromFile(fpath.string().c_str())) {
beep();
return true;
}
sheets[cur] = img;
spec_scen_g.replace_sheet(cur, img);
return true;
});
pic_dlg["save"].attachClickHandler([&sheets,&cur](cDialog&, std::string, eKeyMod) -> bool {
fs::path fpath = nav_put_rsrc({"png", "bmp", "jpg", "jpeg"});
if(fpath.empty()) return true;
sheets[cur].saveToFile(fpath.string().c_str());
return true;
});
// TODO: These buttons not implemented yet
pic_dlg["new"].hide();
pic_dlg["del"].hide();
if(spec_scen_g.numSheets == 1) {
pic_dlg["left"].hide();
pic_dlg["right"].hide();
} else pic_dlg.attachClickHandlers([&sheets,&cur](cDialog& me, std::string dir, eKeyMod) -> bool {
if(dir == "left") {
if(cur == 0)
cur = spec_scen_g.numSheets - 1;
else cur--;
} else if(dir == "right") {
cur++;
if(cur >= spec_scen_g.numSheets)
cur = 0;
} else return true;
set_dlg_custom_sheet(me, cur);
return true;
}, {"left", "right"});
set_dlg_custom_sheet(pic_dlg, cur);
shut_down_menus(5); // So that cmd+O, cmd+N, cmd+S can work
pic_dlg.run();
// Now, we need to restore the sheets if they pressed cancel
if(!pic_dlg.accepted()) {
for(auto p : sheetsSave) {
spec_scen_g.replace_sheet(p.first, p.second);
}
}
// Restore menus
shut_down_menus(4);
if(overall_mode <= MODE_MAIN_SCREEN)
shut_down_menus(editing_town ? 2 : 1);
else shut_down_menus(3);
}

View File

@@ -1,6 +1,7 @@
class cDialog;
void edit_custom_sheets();
void edit_custom_pics_types();
bool edit_ter_type(ter_num_t which_ter);
bool edit_monst_type(short which_monst);

View File

@@ -296,6 +296,10 @@ void handle_menu_choice(eMenu item_hit) {
set_starting_loc();
change_made = true;
break;
case eMenu::SCEN_SHEETS:
edit_custom_sheets();
change_made = true;
break;
case eMenu::SCEN_PICS:
edit_custom_pics_types();
change_made = true;

View File

@@ -23,7 +23,7 @@ enum class eMenu {
SCEN_SAVE_ITEM_RECTS, SCEN_HORSES, SCEN_BOATS,
TOWN_VARYING, SCEN_TIMERS, SCEN_ITEM_SHORTCUTS, TOWN_DELETE,
SCEN_DATA_DUMP, SCEN_TEXT_DUMP,
SCEN_PICS,
SCEN_PICS, SCEN_SHEETS,
// Town menu
TOWN_DETAILS, TOWN_WANDERING, TOWN_BOUNDARIES, TOWN_AREAS,
TOWN_ITEMS_RANDOM, TOWN_ITEMS_NOT_PROPERTY, TOWN_ITEMS_CLEAR,

View File

@@ -52,7 +52,7 @@ void init_menubar() {
eMenu::EDIT_CUT, eMenu::EDIT_COPY, eMenu::EDIT_PASTE, eMenu::EDIT_DELETE, eMenu::EDIT_SELECT_ALL,
};
static const eMenu scen_choices[] = {
eMenu::TOWN_CREATE, eMenu::NONE, eMenu::SCEN_DETAILS, eMenu::SCEN_INTRO, eMenu::TOWN_START, eMenu::SCEN_PICS, eMenu::NONE, eMenu::NONE,
eMenu::TOWN_CREATE, eMenu::NONE, eMenu::SCEN_DETAILS, eMenu::SCEN_INTRO, eMenu::TOWN_START, eMenu::SCEN_SHEETS, eMenu::SCEN_PICS, eMenu::NONE, eMenu::NONE,
eMenu::SCEN_SPECIALS, eMenu::SCEN_TEXT, eMenu::SCEN_JOURNALS, eMenu::TOWN_IMPORT, eMenu::SCEN_SAVE_ITEM_RECTS,
eMenu::SCEN_HORSES, eMenu::SCEN_BOATS, eMenu::TOWN_VARYING, eMenu::SCEN_TIMERS, eMenu::SCEN_ITEM_SHORTCUTS,
eMenu::TOWN_DELETE, eMenu::SCEN_DATA_DUMP, eMenu::SCEN_TEXT_DUMP,
@@ -96,6 +96,7 @@ void init_menubar() {
}
// mode 0 - initial shut down, 1 - no town, 2 - no out, 3 - no town or out 4 - all menus on
// 5 - disable file/edit menus
// TODO: Use an enum here
void shut_down_menus(short mode) {
if(mode == 0) {
@@ -105,6 +106,8 @@ void shut_down_menus(short mode) {
[[menu_bar_handle itemWithTitle: @"Outdoors"] setEnabled: NO];
}
if(mode == 4) {
[[menu_bar_handle itemWithTitle: @"File"] setEnabled: YES];
[[menu_bar_handle itemWithTitle: @"Edit"] setEnabled: YES];
[[file_menu itemWithTitle: @"Save"] setEnabled: YES];
[[menu_bar_handle itemWithTitle: @"Scenario"] setEnabled: YES];
[[menu_bar_handle itemWithTitle: @"Town"] setEnabled: YES];
@@ -130,6 +133,10 @@ void shut_down_menus(short mode) {
if([[item title] length] > 0 && [[item title] characterAtIndex: 0] != ' ')
[item setEnabled: NO];
}
if(mode == 5) {
[[menu_bar_handle itemWithTitle: @"File"] setEnabled: NO];
[[menu_bar_handle itemWithTitle: @"Edit"] setEnabled: NO];
}
}
@implementation MenuHandler

View File

@@ -80,7 +80,7 @@ void init_menubar() {
eMenu::EDIT_CUT, eMenu::EDIT_COPY, eMenu::EDIT_PASTE, eMenu::EDIT_DELETE, eMenu::EDIT_SELECT_ALL,
};
static const eMenu scen_choices[] = {
eMenu::TOWN_CREATE, eMenu::NONE, eMenu::SCEN_DETAILS, eMenu::SCEN_INTRO, eMenu::TOWN_START, eMenu::SCEN_PICS, eMenu::NONE, eMenu::NONE,
eMenu::TOWN_CREATE, eMenu::NONE, eMenu::SCEN_DETAILS, eMenu::SCEN_INTRO, eMenu::TOWN_START, eMenu::SCEN_SHEETS, eMenu::SCEN_PICS, eMenu::NONE, eMenu::NONE,
eMenu::SCEN_SPECIALS, eMenu::SCEN_TEXT, eMenu::SCEN_JOURNALS, eMenu::TOWN_IMPORT, eMenu::SCEN_SAVE_ITEM_RECTS,
eMenu::SCEN_HORSES, eMenu::SCEN_BOATS, eMenu::TOWN_VARYING, eMenu::SCEN_TIMERS, eMenu::SCEN_ITEM_SHORTCUTS,
eMenu::TOWN_DELETE, eMenu::SCEN_DATA_DUMP, eMenu::SCEN_TEXT_DUMP,