Skip to content

Commit

Permalink
Merge pull request CleverRaven#73538 from db48x/refactor-draw_colored…
Browse files Browse the repository at this point in the history
…_text

Refactor draw colored text
  • Loading branch information
Maleclypse authored May 20, 2024
2 parents b7e7dec + dec5cf3 commit d272059
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 33 deletions.
91 changes: 62 additions & 29 deletions src/cata_imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ struct pairs {
std::array<RGBTuple, color_loader<RGBTuple>::COLOR_NAMES_COUNT> rgbPalette;
std::array<pairs, 100> colorpairs; //storage for pair'ed colored

ImVec4 cataimgui::imvec4_from_color( nc_color &color )
{
int pair_id = color.get_index();
pairs &pair = colorpairs[pair_id];

int palette_index = pair.FG != 0 ? pair.FG : pair.BG;
if( color.is_bold() ) {
palette_index += color_loader<RGBTuple>::COLOR_NAMES_COUNT / 2;
}
RGBTuple &rgbCol = rgbPalette[palette_index];
return { static_cast<float>( rgbCol.Red / 255. ),
static_cast<float>( rgbCol.Green / 255. ),
static_cast<float>( rgbCol.Blue / 255. ),
static_cast<float>( 255. ) };
}

std::vector<std::pair<int, ImTui::mouse_event>> imtui_events;

static int GetFallbackStrWidth( const char *s_begin, const char *s_end,
Expand Down Expand Up @@ -189,6 +205,15 @@ RGBTuple color_loader<RGBTuple>::from_rgb( const int r, const int g, const int b
#include <imgui/imgui_impl_sdl2.h>
#include <imgui/imgui_impl_sdlrenderer2.h>

ImVec4 cataimgui::imvec4_from_color( nc_color &color )
{
SDL_Color c = curses_color_to_SDL( color );
return { static_cast<float>( c.r / 255. ),
static_cast<float>( c.g / 255. ),
static_cast<float>( c.b / 255. ),
static_cast<float>( c.a / 255. ) };
}

cataimgui::client::client( const SDL_Renderer_Ptr &sdl_renderer, const SDL_Window_Ptr &sdl_window,
const GeometryRenderer_Ptr &sdl_geometry ) :
sdl_renderer( sdl_renderer ),
Expand Down Expand Up @@ -368,20 +393,47 @@ void cataimgui::imvec2_to_point( ImVec2 *src, point *dest )
}
}

static void PushOrPopColor( const std::string_view seg, int minimumColorStackSize )
{
color_tag_parse_result tag = get_color_from_tag( seg, report_color_error::yes );
switch( tag.type ) {
case color_tag_parse_result::open_color_tag:
ImGui::PushStyleColor( ImGuiCol_Text, tag.color );
break;
case color_tag_parse_result::close_color_tag:
if( GImGui->ColorStack.Size > minimumColorStackSize ) {
ImGui::PopStyleColor();
}
break;
case color_tag_parse_result::non_color_tag:
// Do nothing
break;
}
}

void cataimgui::window::draw_colored_text( std::string const &text, const nc_color &color,
float wrap_width, bool *is_selected, bool *is_focused, bool *is_hovered )
{
nc_color color_cpy = color;
draw_colored_text( text, color_cpy, wrap_width, is_selected, is_focused, is_hovered );
ImGui::PushStyleColor( ImGuiCol_Text, color_cpy );
draw_colored_text( text, wrap_width, is_selected, is_focused, is_hovered );
ImGui::PopStyleColor();
}

void cataimgui::window::draw_colored_text( std::string const &text, nc_color &color,
float wrap_width, bool *is_selected, bool *is_focused, bool *is_hovered )
{
ImGui::PushStyleColor( ImGuiCol_Text, color );
draw_colored_text( text, wrap_width, is_selected, is_focused, is_hovered );
ImGui::PopStyleColor();
}

void cataimgui::window::draw_colored_text( std::string const &text,
float wrap_width, bool *is_selected, bool *is_focused, bool *is_hovered )
{
ImGui::PushID( text.c_str() );
int startColorStackCount = GImGui->ColorStack.Size;
ImGuiID itemId = GImGui->CurrentWindow->IDStack.back();
std::stack<nc_color> color_stack;
color_stack.push( color );
size_t chars_per_line = size_t( wrap_width );
if( chars_per_line == 0 ) {
chars_per_line = SIZE_MAX;
Expand All @@ -393,7 +445,6 @@ void cataimgui::window::draw_colored_text( std::string const &text, nc_color &co
std::vector<std::string> folded_msg = foldstring( text, chars_per_line );

for( const std::string &line : folded_msg ) {

const auto color_segments = split_by_color( line );
if( is_selected != nullptr ) {
ImGui::Selectable( "", is_selected );
Expand All @@ -406,35 +457,14 @@ void cataimgui::window::draw_colored_text( std::string const &text, nc_color &co
}

if( seg[0] == '<' ) {
const color_tag_parse_result::tag_type type =
update_color_stack( color_stack, seg, report_color_error::yes );
if( type != color_tag_parse_result::non_color_tag ) {
seg = rm_prefix( seg );
}
PushOrPopColor( seg, startColorStackCount );
seg = rm_prefix( seg );
}

color = color_stack.empty() ? color : color_stack.top();
if( i++ != 0 ) {
ImGui::SameLine( 0, 0 );
}
#if !(defined(TILES) || defined(WIN32))
int pair_id = color.get_index();
pairs &pair = colorpairs[pair_id];

int palette_index = pair.FG != 0 ? pair.FG : pair.BG;
if( color.is_bold() ) {
palette_index += color_loader<RGBTuple>::COLOR_NAMES_COUNT / 2;
}
RGBTuple &rgbCol = rgbPalette[palette_index];
ImGui::TextColored( { static_cast<float>( rgbCol.Red / 255. ), static_cast<float>( rgbCol.Green / 255. ),
static_cast<float>( rgbCol.Blue / 255. ), static_cast<float>( 255. ) },
"%s", seg.c_str() );
#else
SDL_Color c = curses_color_to_SDL( color );
ImGui::TextColored( { static_cast<float>( c.r / 255. ), static_cast<float>( c.g / 255. ),
static_cast<float>( c.b / 255. ), static_cast<float>( c.a / 255. ) },
"%s", seg.c_str() );
#endif
ImGui::TextUnformatted( seg.c_str() );
GImGui->LastItemData.ID = itemId;
if( is_focused && !*is_focused ) {
*is_focused = ImGui::IsItemFocused();
Expand All @@ -445,7 +475,10 @@ void cataimgui::window::draw_colored_text( std::string const &text, nc_color &co

}
}

for( int curColorStackCount = GImGui->ColorStack.Size; curColorStackCount > startColorStackCount;
curColorStackCount-- ) {
ImGui::PopStyleColor();
}
ImGui::PopID();
}

Expand Down
6 changes: 6 additions & 0 deletions src/cata_imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct input_event;

struct point;
struct ImVec2;
struct ImVec4;
class Font;
class input_context;

Expand Down Expand Up @@ -78,6 +79,8 @@ class client
void point_to_imvec2( point *src, ImVec2 *dest );
void imvec2_to_point( ImVec2 *src, point *dest );

ImVec4 imvec4_from_color( nc_color &color );

class window
{
std::unique_ptr<class window_impl> p_impl;
Expand All @@ -94,6 +97,9 @@ class window
void draw_colored_text( std::string const &text, nc_color &color,
float wrap_width = 0.0F, bool *is_selected = nullptr,
bool *is_focused = nullptr, bool *is_hovered = nullptr );
void draw_colored_text( std::string const &text,
float wrap_width = 0.0F, bool *is_selected = nullptr,
bool *is_focused = nullptr, bool *is_hovered = nullptr );
bool action_button( const std::string &action, const std::string &text );
bool has_button_action();
std::string get_button_action();
Expand Down
8 changes: 6 additions & 2 deletions src/color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "filesystem.h"
#include "flexbuffer_json-inl.h"
#include "flexbuffer_json.h"
#include "imgui/imgui.h"
#include "input_context.h"
#include "json.h"
#include "output.h"
Expand All @@ -26,9 +27,12 @@
#include "translations.h"
#include "ui.h"
#include "ui_manager.h"
#if !(defined(TILES) || defined(WIN32))
#include "cata_imgui.h"
#endif

nc_color::operator ImVec4()
{
return cataimgui::imvec4_from_color( *this );
}

void nc_color::serialize( JsonOut &jsout ) const
{
Expand Down
4 changes: 4 additions & 0 deletions src/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,8 @@ enum hl_enum {
NUM_HL
};

struct ImVec4;

class nc_color
{
private:
Expand All @@ -357,6 +359,8 @@ class nc_color
public:
nc_color() : attribute_value( 0 ), index( 0 ) { }

operator ImVec4(); // NOLINT(google-explicit-constructor): the conversion is not expensive

// Most of the functions here are implemented in ncurses_def.cpp
// (for ncurses builds) *and* in cursesport.cpp (for other builds).

Expand Down
3 changes: 1 addition & 2 deletions src/popup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ void query_popup_impl::draw_controls()
mouse_selected_option = -1;

for( const std::string &line : parent->folded_msg ) {
nc_color col = parent->default_text_color;
draw_colored_text( line, col );
draw_colored_text( line, parent->default_text_color );
}

if( !parent->buttons.empty() ) {
Expand Down

0 comments on commit d272059

Please sign in to comment.