Fix some rough edges when handling large pictures or full sheets

- Choose Picture dialog now scales these pictures down to fit in the available space, thus avoiding the ugly overlap issue.
- Choose Picture dialog now supports full sheets, scaling them down in a similar manner
- Due to the above, the Display Picture node now offers a Choose button
- The possibility of large (72x72) dialog pictures is now properly documented
This commit is contained in:
2015-06-28 20:13:33 -04:00
parent f6d9ac7633
commit 860cf9d5dd
6 changed files with 72 additions and 23 deletions

View File

@@ -134,6 +134,14 @@ consecutive custom sheet slots (pushed into the upper left corner).</p>
put 4 in the Picture Type field. Add 1000 to the slot the left
half is in, and put that number in the Pict spot.</p>
<p><b>Large Dialog Picture -</b> This works essentially the same as a small dialog picture
(above). A large dialog picture is a 72x72 graphic, meaning it can be split into four 36x36
parts. Thus, put each part in the sheet as if it were a small dialog graphic, in the order
top left, top right, bottom left, bottom right. This takes a total of 8 slots.</p>
<p>To use this graphic as the dialog picture in a dialog (created by a special node),
put 13 in the Picture Type field. Add 1000 to the slot the left
half is in, and put that number in the Pict spot.</p>
<p><b>Item - </b>An item graphic takes up one 28 x 36 slot. Add 1000 to the slot the
graphic is in, and put that number in the Item Picture field on the editing items window.</p>
<p>To use this graphic as the dialog picture in a dialog (created by a special node),

View File

@@ -385,6 +385,7 @@ void cSpecial::append(legacy::special_node_type& old){
// J - Choose button to select a quest status
// < - Choose button to select a cardinal direction
// ~ - Choose button to select a weapon enchantment
// _ - Choose button to select a full sheet
// 0..9 - Choose button to select a specific type of picture
// (terrain, monster, dialog, talk, item, pc, field, boom, missile, status)
static const char*const button_dict[7][11] = {
@@ -394,7 +395,7 @@ static const char*const button_dict[7][11] = {
" ", // msg3
" p 3 ", // pic
" ? ", // pictype
" & x T i M cit j ", // ex1a
" & x T i _ M cit j ", // ex1a
" % S ss cJ ", // ex1b
" ", // ex1c
" tt ", // ex2a

View File

@@ -22,8 +22,6 @@
// TODO: This should probably be a source file instead of a header
#include "dlogutil.buttons.hpp" // must be included here and only here
const size_t cPictChoice::per_page = 36;
cPictChoice::cPictChoice(const std::vector<pic_num_t>& pics,ePicType t,cDialog* parent) : cPictChoice(pics.begin(), pics.end(), t, parent) {}
cPictChoice::cPictChoice(const std::vector<std::pair<pic_num_t,ePicType>>& pics,cDialog* parent) : dlg("choose-pict",parent) {
@@ -100,7 +98,19 @@ void cPictChoice::fillPage(){
cPict& pic = dynamic_cast<cPict&>(dlg[sout.str()]);
if(page * per_page + i < picts.size()){
pic.show();
pic.setPict(picts[per_page * page + i].first, picts[per_page * page + i].second);
ePicType tp = picts[per_page * page + i].second;
pic.setPict(picts[per_page * page + i].first, tp);
rectangle b = pic.getBounds();
if(tp == PIC_DLOG_LG || tp == PIC_CUSTOM_DLOG_LG || tp == PIC_SCEN_LG) {
pic.setFormat(TXT_WRAP, false);
b.width() /= 2;
b.height() /= 2;
} else if(tp == PIC_FULL) {
pic.setFormat(TXT_WRAP, false);
b.width() = 40;
b.height() = 40;
} else pic.setFormat(TXT_WRAP, true);
pic.setBounds(b);
}else pic.hide();
}
}
@@ -153,8 +163,6 @@ size_t cPictChoice::getSelected() {
return cur;
}
const size_t cStringChoice::per_page = 40;
cStringChoice::cStringChoice(
std::vector<std::string>& strs,
std::string title,

View File

@@ -156,7 +156,7 @@ public:
/// A dialog that presents a list of strings with LEDs and allows you to choose one.
/// The list may span several pages.
class cStringChoice {
static const size_t per_page;
static const size_t per_page = 40;
cDialog dlg;
bool onLeft();
bool onRight();
@@ -197,7 +197,7 @@ public:
/// Like cStringChoice, but presents a list of icons rather than strings.
class cPictChoice {
static const size_t per_page;
static const size_t per_page = 36;
bool didAccept;
cDialog dlg;
void attachHandlers();

View File

@@ -734,8 +734,8 @@ void cPict::drawPresetDlog(short num, rectangle to_rect){
}
void cPict::drawPresetDlogLg(short num, rectangle to_rect){
to_rect.right = to_rect.left + 72;
to_rect.bottom = to_rect.top + 72;
to_rect.right = to_rect.left + (drawScaled ? getBounds().width() : 72);
to_rect.bottom = to_rect.top + (drawScaled ? getBounds().height() : 72);
std::shared_ptr<sf::Texture> from_gw = getSheet(SHEET_DLOG);
rectangle from_rect = {0,0,72,72};
from_rect.offset(36 * (num % 4),36 * (num / 4));
@@ -762,8 +762,8 @@ void cPict::drawPresetScen(short num, rectangle to_rect){
void cPict::drawPresetScenLg(short num, rectangle to_rect){
std::shared_ptr<sf::Texture> from_gw = getSheet(SHEET_SCEN_LG);
to_rect.right = to_rect.left + 64;
to_rect.bottom = to_rect.top + 64;
to_rect.right = to_rect.left + (drawScaled ? getBounds().width() : 64);
to_rect.bottom = to_rect.top + (drawScaled ? getBounds().height() : 64);
rectangle from_rect = {0,0,64,64};
from_rect.offset(num * 64, 0);
rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect);
@@ -967,31 +967,42 @@ void cPict::drawCustomMonstLg(short num, rectangle to_rect){
rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha);
}
// This is a super-hacky way to wedge in scaled form, but at least it should work.
static int dlog_to_w = 18, dlog_to_h = 36;
void cPict::drawCustomDlog(short num, rectangle to_rect){
rectangle from_rect;
sf::Texture* from_gw;
graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num);
to_rect.right = to_rect.left + 18;
to_rect.bottom = to_rect.top + 36;
to_rect.right = to_rect.left + dlog_to_w;
to_rect.bottom = to_rect.top + dlog_to_h;
from_rect.right = from_rect.left + 18;
from_rect.bottom = from_rect.top + 36;
rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect);
graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+1);
to_rect.offset(18,0);
to_rect.offset(dlog_to_w,0);
from_rect.right = from_rect.left + 18;
from_rect.bottom = from_rect.top + 36;
rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect);
}
void cPict::drawCustomDlogLg(short num, rectangle to_rect){
if(drawScaled) {
dlog_to_w = 9;
dlog_to_h = 18;
}
drawCustomDlog(num,to_rect);
to_rect.offset(36,0);
to_rect.offset(dlog_to_h,0);
drawCustomDlog(num + 2,to_rect);
to_rect.offset(-36,36);
to_rect.offset(-dlog_to_h,dlog_to_h);
drawCustomDlog(num + 4,to_rect);
to_rect.offset(36,0);
to_rect.offset(dlog_to_h,0);
drawCustomDlog(num + 6,to_rect);
if(drawScaled) {
dlog_to_w = 18;
dlog_to_h = 26;
}
}
void cPict::drawCustomTalk(short num, rectangle to_rect){

View File

@@ -26,7 +26,7 @@ extern cCustomGraphics spec_scen_g;
std::vector<pic_num_t> field_pics = {0,3,5,6,7,8,9,10,11,12,13,14,15,24,25,26,27,28,29,30,31};
std::vector<pic_num_t> boom_pics = {0,1,2,3,4};
std::vector<pic_num_t> lgdlog_pics = {0,72};
std::vector<pic_num_t> lgdlog_pics = {0,32};
size_t num_strs(eStrMode str_mode) {
switch(str_mode) {
@@ -154,6 +154,7 @@ short choose_background(short cur_choice, cDialog* parent) {
// TODO: I have two functions that do this. (The other one is pick_picture.)
pic_num_t choose_graphic(short cur_choice,ePicType g_type,cDialog* parent) {
extern fs::path tempDir;
int i = 0;
std::vector<pic_num_t> all_pics;
size_t total_pics = 0;
@@ -174,7 +175,25 @@ pic_num_t choose_graphic(short cur_choice,ePicType g_type,cDialog* parent) {
case PIC_STATUS: total_pics = 27; break;
case PIC_SCEN_LG: total_pics = 4; break;
case PIC_TER_MAP: total_pics = 980; break;
case PIC_FULL: return NO_PIC; // TODO: Is it even possible to do a pict selection dialog for this?
case PIC_FULL:
if(!fs::is_directory(tempDir/"scenario/graphics")) {
giveError("You have no custom graphics, so it's not possible to select this kind of picture!",parent);
return NO_PIC;
}
for(fs::directory_iterator iter(tempDir/"scenario/graphics"); iter != fs::directory_iterator(); iter++) {
std::string fname = iter->path().filename().string().c_str();
size_t dot = fname.find_last_of('.');
if(dot == std::string::npos) continue;
std::transform(fname.begin(), fname.end(), fname.begin(), tolower);
if(fname.substr(dot) != ".png") continue;
size_t digit = fname.find_first_of("0123456789");
if(digit == std::string::npos) continue;
if(fname.substr(0, digit) != "sheet") continue;
all_pics.push_back(boost::lexical_cast<pic_num_t>(fname.substr(digit, dot - digit)));
}
std::sort(all_pics.begin(), all_pics.end());
pic_dlg = new cPictChoice(all_pics, g_type, parent); // To suppress adding custom pics
break;
default:
std::cerr << "Picture type " << (g_type + PIC_PRESET) << " is missing case in choose_graphic." << std::endl;
return NO_PIC;
@@ -773,9 +792,10 @@ snd_num_t choose_sound(short cur, cDialog* parent, std::string title) {
}
static bool edit_spec_enc_value(cDialog& me, std::string item_hit, node_stack_t& edit_stack) {
static const ePicType pics[10] = {
static const ePicType pics[11] = {
PIC_TER, PIC_MONST, PIC_DLOG, PIC_TALK, PIC_ITEM,
PIC_PC, PIC_FIELD, PIC_BOOM, PIC_MISSILE, PIC_STATUS
PIC_PC, PIC_FIELD, PIC_BOOM, PIC_MISSILE, PIC_STATUS,
PIC_FULL
};
std::string field = item_hit.substr(0, item_hit.find_first_of('-'));
char btn;
@@ -884,8 +904,9 @@ static bool edit_spec_enc_value(cDialog& me, std::string item_hit, node_stack_t&
case '<': strt = STRT_DIR; title = "Select the direction:"; break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '_':
choose_string = false;
store = choose_graphic(val, pics[btn - '0'], &me);
store = choose_graphic(val, pics[btn == '_' ? 10 : btn - '0'], &me);
if(store < 0) store = val;
break;
default: