Rewrite the conversation rendering and interaction engine

- The only functional change is that clickable words are now red
This commit is contained in:
2014-11-30 20:38:21 -05:00
parent 048de39583
commit 6c0fc58bf1
6 changed files with 303 additions and 366 deletions

View File

@@ -197,14 +197,20 @@ struct text_params_t {
TextStyle style;
eTextMode mode;
location offset = {0,0};
// Hilite ranges are, like the STL, of the form [first, last).
std::vector<hilite_t> hilite_ranges;
sf::Color hilite_fg, hilite_bg = sf::Color::Transparent;
enum {RECTS} returnType;
std::vector<RECT> returnRects;
};
struct snippet_t {
std::string text;
location at;
bool hilited;
};
void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string str,text_params_t options);
void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string str,text_params_t& options);
void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string str,eTextMode mode,TextStyle style, location offset) {
text_params_t params;
@@ -214,12 +220,57 @@ void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string st
win_draw_string(dest_window, dest_rect, str, params);
}
void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string str,text_params_t options) {
std::vector<RECT> draw_string_hilite(sf::RenderTarget& dest_window,RECT dest_rect,std::string str,TextStyle style,std::vector<hilite_t> hilites,sf::Color hiliteClr) {
text_params_t params;
params.mode = eTextMode::WRAP;
params.hilite_ranges = hilites;
params.style = style;
params.hilite_fg = hiliteClr;
params.returnType = text_params_t::RECTS;
win_draw_string(dest_window, dest_rect, str, params);
return params.returnRects;
}
void push_snippets(size_t start, size_t end, text_params_t& options, std::vector<snippet_t>& snippets, size_t& iHilite, const std::string& str, location loc) {
std::vector<hilite_t>& hilites = options.hilite_ranges;
// Check if we have any hilites on this line.
// We assume the list of hilites is sorted, so we just need to
// check the current entry.
size_t upper_bound = end;
do {
bool hilited = false;
if(iHilite < hilites.size()) {
// Possibilities: (vertical bars indicate line boundaries, parentheses for hilite boundaries, dots are data)
// 1. |...|...(...) --> no hilite on this line
// 2a. |...(...|...) --> hilite starts on this line and continues past it
// 2b. |...(...)...| --> hilite starts and ends on this line
// 3a. (...|...)...| --> hilite starts (or continues) at the start of the line and ends on this line
// 3b. (...|......)| --> entire line hilited
// Case 1 needs no special handling; check case 3, then case 2.
if(hilites[iHilite].first <= start) {
hilited = true;
if(hilites[iHilite].second < end) // 3a
end = hilites[iHilite].second;
} else if(hilites[iHilite].first < end)
end = hilites[iHilite].first;
// 2b will reduce to 3a after shifting start over
}
size_t amount = end - start;
snippets.push_back({str.substr(start,amount), loc, hilited});
loc.x += string_length(snippets[snippets.size()-1].text, options.style);
start = end;
end = upper_bound;
if(iHilite < hilites.size() && start >= hilites[iHilite].second)
iHilite++;
} while(start < upper_bound);
}
void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string str,text_params_t& options) {
short line_height = options.style.lineHeight;
sf::Text str_to_draw;
options.style.applyTo(str_to_draw);
short str_len,i;
short last_line_break = 0,last_word_break = 0;
unsigned short last_line_break = 0,last_word_break = 0;
short total_width = 0;
short adjust_x = 0,adjust_y = 0;
@@ -245,9 +296,12 @@ void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string st
return str_to_draw.findCharacterPos(i).x;
};
// Special stuff
size_t iHilite = 0;
location moveTo;
std::vector<snippet_t> snippets;
line_height -= 2;
line_height -= 2; // TODO: ...why are we arbitrarily reducing the line height from the requested value?
if(mode == eTextMode::WRAP) {
moveTo = location(dest_rect.left + 1 + adjust_x, dest_rect.top + 1 + adjust_y + 9);
@@ -258,8 +312,7 @@ void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string st
str[i] = ' ';
last_word_break = i + 1;
}
size_t amount = last_word_break - last_line_break - 1;
snippets.push_back({str.substr(last_line_break,amount), moveTo});
push_snippets(last_line_break, last_word_break, options, snippets, iHilite, str, moveTo);
moveTo.y += line_height;
last_line_break = last_word_break;
}
@@ -270,7 +323,7 @@ void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string st
if(i - last_line_break > 1) {
std::string snippet = str.substr(last_line_break);
if(snippet.size() > 2)
snippets.push_back({snippet, moveTo});
push_snippets(last_line_break, str.length() + 1, options, snippets, iHilite, str, moveTo);
}
} else {
switch(mode) {
@@ -287,12 +340,23 @@ void win_draw_string(sf::RenderTarget& dest_window,RECT dest_rect,std::string st
case eTextMode::WRAP:
break; // Never happens, but put this here to silence warning
}
snippets.push_back({str, moveTo});
push_snippets(0, str.length() + 1, options, snippets, iHilite, str, moveTo);
}
for(auto& snippet : snippets) {
str_to_draw.setString(snippet.text);
str_to_draw.setPosition(snippet.at);
if(snippet.hilited) {
RECT bounds = str_to_draw.getGlobalBounds();
// Adjust so that drawing the same text to
// the same rect is positioned exactly right
bounds.left = snippet.at.x - 1;
bounds.top = snippet.at.y + 5;
if(options.returnType == text_params_t::RECTS)
options.returnRects.push_back(bounds);
str_to_draw.setColor(options.hilite_fg);
fill_rect(dest_window, bounds, options.hilite_bg);
} else str_to_draw.setColor(options.style.colour);
dest_window.draw(str_to_draw);
}
}