Rewrite the conversation rendering and interaction engine
- The only functional change is that clickable words are now red
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user