Refactor color_range to use color_t
Temporarily breaks TC/RC coloring, will fix.
This commit is contained in:
parent
49155fadd6
commit
f2ab245e8d
20 changed files with 282 additions and 284 deletions
|
@ -1235,7 +1235,7 @@ private:
|
|||
display* gui = display::get_singleton();
|
||||
std::string team_name;
|
||||
|
||||
color_t color = color_t::from_argb_bytes(team::get_side_rgb(ai_.get_side()));
|
||||
color_t color = team::get_side_rgb(ai_.get_side());
|
||||
|
||||
const terrain_label *res;
|
||||
res = gui->labels().set_label(location, text, ai_.get_side() - 1, team_name, color);
|
||||
|
|
|
@ -26,146 +26,102 @@
|
|||
#include "util.hpp"
|
||||
|
||||
#include <iomanip>
|
||||
#include <unordered_set>
|
||||
|
||||
std::map<uint32_t, uint32_t> recolor_range(const color_range& new_range, const std::vector<uint32_t>& old_rgb){
|
||||
std::map<uint32_t, uint32_t> map_rgb;
|
||||
color_range_map recolor_range(const color_range& new_range, const std::vector<color_t>& old_rgb)
|
||||
{
|
||||
color_range_map map_rgb;
|
||||
|
||||
uint16_t new_red = (new_range.mid() & 0x00FF0000)>>16;
|
||||
uint16_t new_green= (new_range.mid() & 0x0000FF00)>>8;
|
||||
uint16_t new_blue = (new_range.mid() & 0x000000FF);
|
||||
uint16_t max_red = (new_range.max() & 0x00FF0000)>>16;
|
||||
uint16_t max_green= (new_range.max() & 0x0000FF00)>>8 ;
|
||||
uint16_t max_blue = (new_range.max() & 0x000000FF) ;
|
||||
uint16_t min_red = (new_range.min() & 0x00FF0000)>>16;
|
||||
uint16_t min_green= (new_range.min() & 0x0000FF00)>>8 ;
|
||||
uint16_t min_blue = (new_range.min() & 0x000000FF) ;
|
||||
const uint16_t new_red = new_range.mid().r;
|
||||
const uint16_t new_green = new_range.mid().g;
|
||||
const uint16_t new_blue = new_range.mid().b;
|
||||
|
||||
const uint16_t max_red = new_range.max().r;
|
||||
const uint16_t max_green = new_range.max().g;
|
||||
const uint16_t max_blue = new_range.max().b;
|
||||
|
||||
const uint16_t min_red = new_range.min().r;
|
||||
const uint16_t min_green = new_range.min().g;
|
||||
const uint16_t min_blue = new_range.min().b;
|
||||
|
||||
// Map first color in vector to exact new color
|
||||
uint32_t temp_rgb= old_rgb.empty() ? 0 : old_rgb[0];
|
||||
uint16_t old_r=(temp_rgb & 0X00FF0000)>>16;
|
||||
uint16_t old_g=(temp_rgb & 0X0000FF00)>>8;
|
||||
uint16_t old_b=(temp_rgb & 0X000000FF);
|
||||
uint16_t reference_avg = (( old_r + old_g + old_b) / 3);
|
||||
const color_t temp_rgb = old_rgb.empty() ? color_t() : old_rgb[0];
|
||||
|
||||
for(std::vector< uint32_t >::const_iterator temp_rgb2 = old_rgb.begin();
|
||||
temp_rgb2 != old_rgb.end(); ++temp_rgb2)
|
||||
{
|
||||
old_r=((*temp_rgb2) & 0X00FF0000)>>16;
|
||||
old_g=((*temp_rgb2) & 0X0000FF00)>>8;
|
||||
old_b=((*temp_rgb2) & 0X000000FF);
|
||||
const uint16_t reference_avg = (temp_rgb.r + temp_rgb.g + temp_rgb.b) / 3;
|
||||
|
||||
const uint16_t old_avg = (( old_r + old_g + old_b) / 3);
|
||||
// Calculate new color
|
||||
uint32_t new_r, new_g, new_b;
|
||||
for(const auto& old_c : old_rgb) {
|
||||
const uint16_t old_avg = (old_c.r + old_c.g + old_c.b) / 3;
|
||||
|
||||
if(reference_avg && old_avg <= reference_avg){
|
||||
float old_rat = static_cast<float>(old_avg)/reference_avg;
|
||||
new_r=uint32_t( old_rat * new_red + (1 - old_rat) * min_red);
|
||||
new_g=uint32_t( old_rat * new_green + (1 - old_rat) * min_green);
|
||||
new_b=uint32_t( old_rat * new_blue + (1 - old_rat) * min_blue);
|
||||
}else if(255 - reference_avg){
|
||||
float old_rat = (255.0f - static_cast<float>(old_avg)) /
|
||||
(255.0f - reference_avg);
|
||||
// Calculate new color
|
||||
uint32_t new_r = 0, new_g = 0, new_b = 0;
|
||||
|
||||
new_r=static_cast<uint32_t>( old_rat * new_red + (1 - old_rat) * max_red);
|
||||
new_g=static_cast<uint32_t>( old_rat * new_green + (1 - old_rat) * max_green);
|
||||
new_b=static_cast<uint32_t>( old_rat * new_blue + (1 - old_rat) * max_blue);
|
||||
}else{
|
||||
new_r=0; new_g=0; new_b=0; // Suppress warning
|
||||
assert(false);
|
||||
if(reference_avg && old_avg <= reference_avg) {
|
||||
float old_ratio = static_cast<float>(old_avg) / reference_avg;
|
||||
|
||||
new_r = static_cast<uint32_t>(old_ratio * new_red + (1 - old_ratio) * min_red);
|
||||
new_g = static_cast<uint32_t>(old_ratio * new_green + (1 - old_ratio) * min_green);
|
||||
new_b = static_cast<uint32_t>(old_ratio * new_blue + (1 - old_ratio) * min_blue);
|
||||
} else if(reference_avg != 255) {
|
||||
float old_ratio = (255.0f - static_cast<float>(old_avg)) / (255.0f - reference_avg);
|
||||
|
||||
new_r = static_cast<uint32_t>(old_ratio * new_red + (1 - old_ratio) * max_red);
|
||||
new_g = static_cast<uint32_t>(old_ratio * new_green + (1 - old_ratio) * max_green);
|
||||
new_b = static_cast<uint32_t>(old_ratio * new_blue + (1 - old_ratio) * max_blue);
|
||||
} else {
|
||||
// Should never get here.
|
||||
// Would imply old_avg > reference_avg = 255
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if(new_r>255) new_r=255;
|
||||
if(new_g>255) new_g=255;
|
||||
if(new_b>255) new_b=255;
|
||||
new_r = std::min<uint32_t>(new_r, 255);
|
||||
new_g = std::min<uint32_t>(new_g, 255);
|
||||
new_b = std::min<uint32_t>(new_b, 255);
|
||||
|
||||
uint32_t newrgb = (new_r << 16) + (new_g << 8) + (new_b );
|
||||
map_rgb[*temp_rgb2]=newrgb;
|
||||
map_rgb[old_c] = {static_cast<uint8_t>(new_r), static_cast<uint8_t>(new_g), static_cast<uint8_t>(new_b)};
|
||||
}
|
||||
|
||||
return map_rgb;
|
||||
}
|
||||
|
||||
bool string2rgb(const std::string& s, std::vector<uint32_t>& result) {
|
||||
result = std::vector<uint32_t>();
|
||||
std::vector<uint32_t> out;
|
||||
std::vector<std::string> rgb_vec = utils::split(s);
|
||||
std::vector<std::string>::iterator c=rgb_vec.begin();
|
||||
while(c!=rgb_vec.end())
|
||||
{
|
||||
uint32_t rgb_hex;
|
||||
if(c->length() != 6)
|
||||
{
|
||||
try {
|
||||
// integer triplets, e.g. white="255,255,255"
|
||||
rgb_hex = (0x00FF0000 & (std::stoi(*c++))<<16); //red
|
||||
if(c!=rgb_vec.end())
|
||||
{
|
||||
rgb_hex += (0x0000FF00 & (std::stoi(*c++)<<8)); //green
|
||||
if(c!=rgb_vec.end())
|
||||
{
|
||||
rgb_hex += (0x000000FF & (std::stoi(*c++)<<0)); //blue
|
||||
}
|
||||
}
|
||||
} catch (std::invalid_argument&) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// hexadecimal format, e.g. white="FFFFFF"
|
||||
char* endptr;
|
||||
rgb_hex = (0x00FFFFFF & strtol(c->c_str(), &endptr, 16));
|
||||
if (*endptr != '\0') {
|
||||
return false;
|
||||
}
|
||||
++c;
|
||||
}
|
||||
out.push_back(rgb_hex);
|
||||
}
|
||||
result = out;
|
||||
return true;
|
||||
}
|
||||
std::vector<color_t> palette(const color_range& cr)
|
||||
{
|
||||
std::vector<color_t> temp, res;
|
||||
std::unordered_set<color_t> clist;
|
||||
|
||||
std::vector<uint32_t> palette(color_range cr){
|
||||
// generate a color palette from a color range
|
||||
std::vector<uint32_t> temp,res;
|
||||
std::set<uint32_t> clist;
|
||||
// use blue to make master set of possible colors
|
||||
for(int i=255;i!=0;i--){
|
||||
int j=255-i;
|
||||
uint32_t rgb = i;
|
||||
temp.push_back(rgb);
|
||||
rgb = (j << 16) + (j << 8) + 255;
|
||||
temp.push_back(rgb);
|
||||
// Use blue to make master set of possible colors
|
||||
for(int i = 255; i != 0; i--) {
|
||||
const int j = 255 - i;
|
||||
|
||||
temp.emplace_back(0,0,i);
|
||||
temp.emplace_back(j,j,255);
|
||||
}
|
||||
|
||||
// Use recolor function to generate list of possible colors.
|
||||
// Could use a special function, would be more efficient,
|
||||
// but harder to maintain.
|
||||
std::map<uint32_t,uint32_t> cmap = recolor_range(cr,temp);
|
||||
for(std::map<uint32_t,uint32_t>::const_iterator k=cmap.begin(); k!=cmap.end();++k){
|
||||
clist.insert(k->second);
|
||||
// Could use a special function, would be more efficient, but harder to maintain.
|
||||
color_range_map cmap = recolor_range(cr, temp);
|
||||
for(const auto& cm : cmap) {
|
||||
clist.insert(cm.second);
|
||||
}
|
||||
res.push_back(cmap[255]);
|
||||
for(std::set<uint32_t>::const_iterator c=clist.begin();c!=clist.end();++c){
|
||||
if(*c != res[0] && *c!=0 && *c != 0x00FFFFFF){
|
||||
res.push_back(*c);}
|
||||
|
||||
res.push_back(cmap[{0,0,255}]);
|
||||
|
||||
for(const auto& cs : clist) {
|
||||
if(cs != res[0] && !cs.null() && cs != color_t(255, 255, 255)) {
|
||||
res.push_back(cs);
|
||||
}
|
||||
}
|
||||
return(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string color_range::debug() const
|
||||
{
|
||||
std::ostringstream o;
|
||||
|
||||
static const uint32_t mask = 0x00FFFFFF;
|
||||
|
||||
o << std::hex << std::setfill('0')
|
||||
<< '{' << std::setw(6) << (mid_ & mask)
|
||||
<< ',' << std::setw(6) << (max_ & mask)
|
||||
<< ',' << std::setw(6) << (min_ & mask)
|
||||
<< ',' << std::setw(6) << (rep_ & mask)
|
||||
o << '{' << mid_.to_hex_string()
|
||||
<< ',' << max_.to_hex_string()
|
||||
<< ',' << min_.to_hex_string()
|
||||
<< ',' << rep_.to_hex_string()
|
||||
<< '}';
|
||||
|
||||
return o.str();
|
||||
|
|
|
@ -17,22 +17,21 @@
|
|||
#ifndef COLOR_RANGE_H_INCLUDED
|
||||
#define COLOR_RANGE_H_INCLUDED
|
||||
|
||||
#include "global.hpp"
|
||||
#include "sdl/color.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
//These macros interfere with MS VC++
|
||||
#ifdef _MSC_VER
|
||||
#undef max
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#include "global.hpp"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
/* Convert comma separated string into rgb values.
|
||||
* Return false and empty result on error.
|
||||
*/
|
||||
bool string2rgb(const std::string& s, std::vector<uint32_t>& result);
|
||||
using color_range_map = std::unordered_map<color_t, color_t>;
|
||||
|
||||
/**
|
||||
* A color range definition is made of four reference RGB colors, used
|
||||
|
@ -53,73 +52,88 @@ bool string2rgb(const std::string& s, std::vector<uint32_t>& result);
|
|||
class color_range
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor, which expects four reference RGB colors.
|
||||
* @param mid Average color shade.
|
||||
* @param max Maximum (highlight) color shade
|
||||
* @param min Minimum color shade
|
||||
* @param rep High-contrast reference color
|
||||
*/
|
||||
color_range(uint32_t mid , uint32_t max = 0x00FFFFFF , uint32_t min = 0x00000000 , uint32_t rep = 0x00808080):mid_(mid),max_(max),min_(min),rep_(rep){}
|
||||
/**
|
||||
* Constructor, which expects four reference RGB colors.
|
||||
* @param mid Average color shade.
|
||||
* @param max Maximum (highlight) color shade
|
||||
* @param min Minimum color shade
|
||||
* @param rep High-contrast reference color
|
||||
*/
|
||||
color_range(color_t mid, color_t max = {255, 255, 255}, color_t min = {0, 0, 0}, color_t rep = {128, 128, 128})
|
||||
: mid_(mid)
|
||||
, max_(max)
|
||||
, min_(min)
|
||||
, rep_(rep)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor, which expects four reference RGB colors.
|
||||
* @param v STL vector with the four reference colors in order.
|
||||
*/
|
||||
color_range(const std::vector<uint32_t>& v)
|
||||
: mid_(v.size() ? v[0] : 0x00808080),
|
||||
max_(v.size() > 1 ? v[1] : 0x00FFFFFF),
|
||||
min_(v.size() > 2 ? v[2] : 0x00000000),
|
||||
rep_(v.size() > 3 ? v[3] : mid_)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Constructor, which expects four reference RGB colors.
|
||||
* @param v STL vector with the four reference colors in order.
|
||||
*/
|
||||
color_range(const std::vector<color_t>& v)
|
||||
: mid_(v.size() ? v[0] : color_t(128, 128, 128))
|
||||
, max_(v.size() > 1 ? v[1] : color_t(255, 255, 255))
|
||||
, min_(v.size() > 2 ? v[2] : color_t(0 , 0 , 0 ))
|
||||
, rep_(v.size() > 3 ? v[3] : mid_)
|
||||
{}
|
||||
|
||||
/** Default constructor. */
|
||||
color_range() : mid_(0x00808080), max_(0x00FFFFFF), min_(0x00000000), rep_(0x00808080) {}
|
||||
/** Default constructor. */
|
||||
color_range()
|
||||
: mid_(128, 128, 128)
|
||||
, max_(255, 255, 255)
|
||||
, min_()
|
||||
, rep_(128, 128, 128)
|
||||
{}
|
||||
|
||||
/** Average color shade. */
|
||||
uint32_t mid() const{return(mid_);}
|
||||
/** Maximum color shade. */
|
||||
uint32_t max() const{return(max_);}
|
||||
/** Minimum color shade. */
|
||||
uint32_t min() const{return(min_);}
|
||||
/** High-contrast shade, intended for the minimap markers. */
|
||||
uint32_t rep() const{return(rep_);}
|
||||
/** Average color shade. */
|
||||
color_t mid() const { return mid_; }
|
||||
|
||||
bool operator<(const color_range& b) const
|
||||
{
|
||||
if(mid_ != b.mid()) return(mid_ < b.mid());
|
||||
if(max_ != b.max()) return(max_ < b.max());
|
||||
if(min_ != b.min()) return(min_ < b.min());
|
||||
return(rep_ < b.rep());
|
||||
}
|
||||
/** Maximum color shade. */
|
||||
color_t max() const { return max_; }
|
||||
|
||||
bool operator==(const color_range& b) const
|
||||
{
|
||||
return(mid_ == b.mid() && max_ == b.max() && min_ == b.min() && rep_ == b.rep());
|
||||
}
|
||||
/** Minimum color shade. */
|
||||
color_t min() const { return min_; }
|
||||
|
||||
/** Return a string describing the color range for debug output. */
|
||||
std::string debug() const;
|
||||
/** High-contrast shade, intended for the minimap markers. */
|
||||
color_t rep() const { return rep_; }
|
||||
|
||||
bool operator==(const color_range& b) const
|
||||
{
|
||||
return mid_ == b.mid() && max_ == b.max() && min_ == b.min() && rep_ == b.rep();
|
||||
}
|
||||
|
||||
bool operator<(const color_range& b) const
|
||||
{
|
||||
if(mid_ != b.mid()) { return mid_.to_rgba_bytes() < b.mid().to_rgba_bytes(); }
|
||||
if(max_ != b.max()) { return max_.to_rgba_bytes() < b.max().to_rgba_bytes(); }
|
||||
if(min_ != b.min()) { return min_.to_rgba_bytes() < b.min().to_rgba_bytes(); }
|
||||
|
||||
return rep_.to_rgba_bytes() < b.rep().to_rgba_bytes();
|
||||
}
|
||||
|
||||
/** Return a string describing the color range for debug output. */
|
||||
std::string debug() const;
|
||||
|
||||
private:
|
||||
uint32_t mid_ , max_ , min_ , rep_;
|
||||
color_t mid_ , max_ , min_ , rep_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a reference color palette from a color range.
|
||||
*/
|
||||
std::vector<uint32_t> palette(color_range cr);
|
||||
std::vector<color_t> palette(const color_range& cr);
|
||||
|
||||
/**
|
||||
* Converts a source palette using the specified color_range object.
|
||||
* This holds the main interface for range-based team coloring. The output is
|
||||
* used with the recolor_image() method to do the actual recoloring.
|
||||
* @param new_rgb Specifies parameters for the conversion.
|
||||
* @param old_rgb Source palette.
|
||||
* @return A STL map of colors, with the keys being source palette elements, and the values
|
||||
* are the result of applying the color range conversion on it.
|
||||
* This holds the main interface for range-based team coloring. The output is used with the recolor_image()
|
||||
* method to do the actual recoloring.
|
||||
*
|
||||
* @param new_rgb Specifies parameters for the conversion.
|
||||
* @param old_rgb Source palette.
|
||||
*
|
||||
* @return A STL map of colors, with the keys being source palette elements, and the values
|
||||
* are the result of applying the color range conversion on it.
|
||||
*/
|
||||
std::map<uint32_t, uint32_t> recolor_range(const color_range& new_rgb, const std::vector<uint32_t>& old_rgb);
|
||||
color_range_map recolor_range(const color_range& new_rgb, const std::vector<color_t>& old_rgb);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1896,20 +1896,20 @@ void display::draw_minimap_units()
|
|||
if (!preferences::minimap_movement_coding()) {
|
||||
|
||||
if (dc_->teams()[currentTeam_].is_enemy(side)) {
|
||||
col = color_t::from_argb_bytes(game_config::color_info(preferences::enemy_color()).rep());
|
||||
col = game_config::color_info(preferences::enemy_color()).rep();
|
||||
} else {
|
||||
|
||||
if (currentTeam_ +1 == static_cast<unsigned>(side)) {
|
||||
|
||||
if (u->movement_left() == u->total_movement())
|
||||
col = color_t::from_argb_bytes(game_config::color_info(preferences::unmoved_color()).rep());
|
||||
col = game_config::color_info(preferences::unmoved_color()).rep();
|
||||
else if (u->movement_left() == 0)
|
||||
col = color_t::from_argb_bytes(game_config::color_info(preferences::moved_color()).rep());
|
||||
col = game_config::color_info(preferences::moved_color()).rep();
|
||||
else
|
||||
col = color_t::from_argb_bytes(game_config::color_info(preferences::partial_color()).rep());
|
||||
col = game_config::color_info(preferences::partial_color()).rep();
|
||||
|
||||
} else
|
||||
col = color_t::from_argb_bytes(game_config::color_info(preferences::allied_color()).rep());
|
||||
col = game_config::color_info(preferences::allied_color()).rep();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ void display_chat_manager::add_chat_message(const time_t& time, const std::strin
|
|||
}
|
||||
color_t speaker_color = {255,255,255,SDL_ALPHA_OPAQUE};
|
||||
if(side >= 1) {
|
||||
speaker_color = color_t::from_argb_bytes(team::get_side_color_range(side).mid());
|
||||
speaker_color = team::get_side_color_range(side).mid();
|
||||
}
|
||||
|
||||
color_t message_color = chat_message_color;
|
||||
|
|
|
@ -31,7 +31,7 @@ std::string get_pango_color_from_id(const std::string& id)
|
|||
{
|
||||
const auto color = game_config::team_rgb_colors.find(id);
|
||||
if(color != game_config::team_rgb_colors.end()) {
|
||||
return color_t::from_argb_bytes(color->second[0]).to_hex_string();
|
||||
return (color->second[0]).to_hex_string();
|
||||
}
|
||||
|
||||
return "";
|
||||
|
|
|
@ -155,7 +155,7 @@ static std::vector<color_t> blue_white_scale_text;
|
|||
std::map<std::string, color_range> team_rgb_range;
|
||||
std::map<std::string, t_string> team_rgb_name;
|
||||
|
||||
std::map<std::string, std::vector<uint32_t>> team_rgb_colors;
|
||||
std::map<std::string, std::vector<color_t>> team_rgb_colors;
|
||||
|
||||
std::vector<std::string> default_colors;
|
||||
|
||||
|
@ -349,10 +349,9 @@ void load_config(const config &v)
|
|||
const std::string& key,
|
||||
const color_t fallback)->std::vector<color_t>
|
||||
{
|
||||
std::vector<std::string> temp = utils::split(v[key].str());
|
||||
std::vector<color_t> color_vec;
|
||||
|
||||
for(const auto& s : temp) {
|
||||
for(const auto& s : utils::split(v[key].str())) {
|
||||
try {
|
||||
color_vec.push_back(color_t::from_hex_string(s));
|
||||
} catch(std::invalid_argument& e) {
|
||||
|
@ -410,41 +409,53 @@ void load_config(const config &v)
|
|||
}
|
||||
}
|
||||
|
||||
void add_color_info(const config &v)
|
||||
void add_color_info(const config& v)
|
||||
{
|
||||
for(const config& teamC : v.child_range("color_range")) {
|
||||
const config::attribute_value *a1 = teamC.get("id"),
|
||||
*a2 = teamC.get("rgb");
|
||||
if (!a1 || !a2) {
|
||||
const config::attribute_value* a1 = teamC.get("id"), *a2 = teamC.get("rgb");
|
||||
if(!a1 || !a2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string id = *a1;
|
||||
std::vector<uint32_t> temp;
|
||||
if(!string2rgb(*a2, temp)) {
|
||||
std::stringstream ss;
|
||||
ss << "can't parse color string:\n" << teamC.debug() << "\n";
|
||||
throw config::error(ss.str());
|
||||
std::vector<color_t> temp;
|
||||
|
||||
for(const auto& s : utils::split(*a2)) {
|
||||
try {
|
||||
temp.push_back(color_t::from_hex_string(s));
|
||||
} catch(std::invalid_argument& e) {
|
||||
std::stringstream ss;
|
||||
ss << "can't parse color string:\n" << teamC.debug() << "\n";
|
||||
throw config::error(ss.str());
|
||||
}
|
||||
}
|
||||
team_rgb_range.insert(std::make_pair(id,color_range(temp)));
|
||||
|
||||
team_rgb_range.insert({id, color_range(temp)});
|
||||
team_rgb_name[id] = teamC["name"];
|
||||
|
||||
LOG_NG << "registered color range '" << id << "': " << team_rgb_range[id].debug() << '\n';
|
||||
|
||||
// Ggenerate palette of same name;
|
||||
std::vector<uint32_t> tp = palette(team_rgb_range[id]);
|
||||
std::vector<color_t> tp = palette(team_rgb_range[id]);
|
||||
if(tp.empty()) {
|
||||
continue;
|
||||
}
|
||||
team_rgb_colors.insert(std::make_pair(id,tp));
|
||||
|
||||
team_rgb_colors.insert({id, tp});
|
||||
}
|
||||
|
||||
for(const config &cp : v.child_range("color_palette")) {
|
||||
for(const config::attribute& rgb : cp.attribute_range()) {
|
||||
std::vector<uint32_t> temp;
|
||||
if(!string2rgb(rgb.second, temp)) {
|
||||
ERR_NG << "Invalid color palette: " << rgb.second << std::endl;
|
||||
std::vector<color_t> temp;
|
||||
for(const auto& s : utils::split(rgb.second)) {
|
||||
try {
|
||||
temp.push_back(color_t::from_hex_string(s));
|
||||
} catch(std::invalid_argument& e) {
|
||||
ERR_NG << "Invalid color in palette: " << s << std::endl;
|
||||
}
|
||||
}
|
||||
team_rgb_colors.insert(std::make_pair(rgb.first, temp));
|
||||
|
||||
team_rgb_colors.insert({rgb.first, temp});
|
||||
LOG_NG << "registered color palette: " << rgb.first << '\n';
|
||||
}
|
||||
}
|
||||
|
@ -465,30 +476,34 @@ const color_range& color_info(const std::string& name)
|
|||
return i->second;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> temp;
|
||||
if(!string2rgb(name, temp)) {
|
||||
std::vector<color_t> temp;
|
||||
try {
|
||||
temp.push_back(color_t::from_hex_string(name));
|
||||
} catch(std::invalid_argument& e) {
|
||||
throw config::error(_("Invalid color range: ") + name);
|
||||
}
|
||||
|
||||
team_rgb_range.insert(std::make_pair(name,color_range(temp)));
|
||||
team_rgb_range.insert({name, color_range(temp)});
|
||||
return color_info(name);
|
||||
}
|
||||
|
||||
const std::vector<uint32_t>& tc_info(const std::string& name)
|
||||
const std::vector<color_t>& tc_info(const std::string& name)
|
||||
{
|
||||
auto i = team_rgb_colors.find(name);
|
||||
if(i != team_rgb_colors.end()) {
|
||||
return i->second;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> temp;
|
||||
if(!string2rgb(name, temp)) {
|
||||
static std::vector<uint32_t> stv;
|
||||
std::vector<color_t> temp;
|
||||
try {
|
||||
temp.push_back(color_t::from_hex_string(name));
|
||||
} catch(std::invalid_argument& e) {
|
||||
static std::vector<color_t> stv;
|
||||
ERR_NG << "Invalid color palette: " << name << std::endl;
|
||||
return stv;
|
||||
}
|
||||
|
||||
team_rgb_colors.insert(std::make_pair(name,temp));
|
||||
team_rgb_colors.insert({name, temp});
|
||||
return tc_info(name);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace game_config
|
|||
|
||||
extern std::map<std::string, color_range> team_rgb_range;
|
||||
extern std::map<std::string, t_string> team_rgb_name;
|
||||
extern std::map<std::string, std::vector<uint32_t> > team_rgb_colors;
|
||||
extern std::map<std::string, std::vector<color_t>> team_rgb_colors;
|
||||
|
||||
extern std::vector<std::string> default_colors;
|
||||
|
||||
|
@ -166,7 +166,7 @@ namespace game_config
|
|||
void load_config(const config &cfg);
|
||||
|
||||
void add_color_info(const config& v);
|
||||
const std::vector<uint32_t>& tc_info(const std::string& name);
|
||||
const std::vector<color_t>& tc_info(const std::string& name);
|
||||
const color_range& color_info(const std::string& name);
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "gui/widgets/window.hpp"
|
||||
|
||||
#include "desktop/clipboard.hpp"
|
||||
#include "font/text_formatting.hpp"
|
||||
#include "game_events/manager.hpp"
|
||||
#include "serialization/parser.hpp" // for write()
|
||||
|
||||
|
@ -603,15 +604,15 @@ void event_mode_controller::show_event(tree_view_node& node, bool is_wmi)
|
|||
static stuff_list_adder add_unit_entry(stuff_list_adder& progress, const unit& u, const display_context& dc)
|
||||
{
|
||||
|
||||
Uint32 team_color = game_config::tc_info(dc.get_team(u.side()).color())[0];
|
||||
color_t team_color = game_config::tc_info(dc.get_team(u.side()).color())[0];
|
||||
std::stringstream s;
|
||||
|
||||
s << '(' << u.get_location() << ')';
|
||||
progress.widget("loc", s.str());
|
||||
|
||||
s.str("");
|
||||
s << "<span color='#" << std::hex << team_color << std::dec;
|
||||
s << "'>side=" << u.side() << "</span>";
|
||||
s << font::span_color(team_color);
|
||||
s << "side=" << u.side() << "</span>";
|
||||
progress.widget("side", s.str(), true);
|
||||
|
||||
if(u.can_recruit()) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "utils/functional.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "game_display.hpp"
|
||||
#include "font/text_formatting.hpp"
|
||||
#include "map/label.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "gui/auxiliary/find_widget.hpp"
|
||||
|
@ -91,9 +92,9 @@ void label_settings::pre_show(window& window) {
|
|||
continue;
|
||||
}
|
||||
int team = std::stoi(category.substr(5)) - 1;
|
||||
Uint32 which_color = game_config::tc_info(viewer.teams()[team].color())[0];
|
||||
color_t which_color = game_config::tc_info(viewer.teams()[team].color())[0];
|
||||
std::ostringstream sout;
|
||||
sout << "<span color='#" << std::hex << which_color << "'>" << name << "</span>";
|
||||
sout << font::span_color(which_color) << name << "</span>";
|
||||
name = sout.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "color_range.hpp"
|
||||
#include "config.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "game_config.hpp"
|
||||
|
|
|
@ -646,12 +646,10 @@ REGISTER_MOD_PARSER(TC, args)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::map<Uint32, Uint32> rc_map;
|
||||
color_range_map rc_map;
|
||||
try {
|
||||
color_range const& new_color =
|
||||
game_config::color_info(team_color);
|
||||
std::vector<Uint32> const& old_color =
|
||||
game_config::tc_info(params[1]);
|
||||
const color_range& new_color = game_config::color_info(team_color);
|
||||
const std::vector<color_t>& old_color = game_config::tc_info(params[1]);
|
||||
|
||||
rc_map = recolor_range(new_color,old_color);
|
||||
}
|
||||
|
@ -676,12 +674,10 @@ REGISTER_MOD_PARSER(RC, args)
|
|||
//
|
||||
// recolor source palette to color range
|
||||
//
|
||||
std::map<Uint32, Uint32> rc_map;
|
||||
color_range_map rc_map;
|
||||
try {
|
||||
color_range const& new_color =
|
||||
game_config::color_info(recolor_params[1]);
|
||||
std::vector<Uint32> const& old_color =
|
||||
game_config::tc_info(recolor_params[0]);
|
||||
const color_range& new_color = game_config::color_info(recolor_params[1]);
|
||||
const std::vector<color_t>& old_color = game_config::tc_info(recolor_params[0]);
|
||||
|
||||
rc_map = recolor_range(new_color,old_color);
|
||||
}
|
||||
|
@ -715,11 +711,9 @@ REGISTER_MOD_PARSER(PAL, args)
|
|||
|
||||
|
||||
try {
|
||||
std::map<Uint32, Uint32> rc_map;
|
||||
std::vector<Uint32> const& old_palette =
|
||||
game_config::tc_info(remap_params[0]);
|
||||
std::vector<Uint32> const& new_palette =
|
||||
game_config::tc_info(remap_params[1]);
|
||||
color_range_map rc_map;
|
||||
const std::vector<color_t>& old_palette = game_config::tc_info(remap_params[0]);
|
||||
const std::vector<color_t>& new_palette =game_config::tc_info(remap_params[1]);
|
||||
|
||||
for(size_t i = 0; i < old_palette.size() && i < new_palette.size(); ++i) {
|
||||
rc_map[old_palette[i]] = new_palette[i];
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#ifndef IMAGE_MODIFICATIONS_HPP_INCLUDED
|
||||
#define IMAGE_MODIFICATIONS_HPP_INCLUDED
|
||||
|
||||
#include "color_range.hpp"
|
||||
#include "lua_jailbreak_exception.hpp"
|
||||
#include "sdl/utils.hpp"
|
||||
#include <queue>
|
||||
|
@ -125,7 +126,7 @@ public:
|
|||
* RC-map based constructor.
|
||||
* @param recolor_map The palette switch map.
|
||||
*/
|
||||
rc_modification(const std::map<Uint32, Uint32>& recolor_map)
|
||||
rc_modification(const color_range_map& recolor_map)
|
||||
: rc_map_(recolor_map)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
|
@ -135,11 +136,11 @@ public:
|
|||
|
||||
bool no_op() const { return rc_map_.empty(); }
|
||||
|
||||
const std::map<Uint32, Uint32>& map() const { return rc_map_;}
|
||||
std::map<Uint32, Uint32>& map() { return rc_map_;}
|
||||
const color_range_map& map() const { return rc_map_;}
|
||||
color_range_map& map() { return rc_map_;}
|
||||
|
||||
private:
|
||||
std::map<Uint32, Uint32> rc_map_;
|
||||
color_range_map rc_map_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -733,7 +733,7 @@ void menu_handler::label_terrain(mouse_handler& mousehandler, bool team_only)
|
|||
if (team_only) {
|
||||
team_name = gui_->labels().team_name();
|
||||
} else {
|
||||
color = color_t::from_argb_bytes(team::get_side_rgb(gui_->viewing_side()));
|
||||
color = team::get_side_rgb(gui_->viewing_side());
|
||||
}
|
||||
const terrain_label* res = gui_->labels().set_label(loc, label, gui_->viewing_team(), team_name, color);
|
||||
if (res)
|
||||
|
|
|
@ -189,7 +189,7 @@ surface getMinimap(int w, int h, const gamemap &map, const team *vw, const std::
|
|||
if (it == game_config::team_rgb_range.end()) {
|
||||
col = color_t(0,0,0,0);
|
||||
} else
|
||||
col = color_t::from_argb_bytes(it->second.rep());
|
||||
col = it->second.rep();
|
||||
|
||||
bool first = true;
|
||||
const t_translation::ter_list& underlying_terrains = tdata.underlying_union_terrain(terrain);
|
||||
|
@ -200,7 +200,7 @@ surface getMinimap(int w, int h, const gamemap &map, const team *vw, const std::
|
|||
if (it == game_config::team_rgb_range.end())
|
||||
continue;
|
||||
|
||||
color_t tmp = color_t::from_argb_bytes(it->second.rep());
|
||||
color_t tmp = it->second.rep();
|
||||
|
||||
if (fogged) {
|
||||
if (tmp.b < 50) tmp.b = 0;
|
||||
|
@ -239,7 +239,7 @@ surface getMinimap(int w, int h, const gamemap &map, const team *vw, const std::
|
|||
|
||||
int side = (resources::gameboard ? resources::gameboard->village_owner(loc) : -1); //check needed for mp create dialog
|
||||
|
||||
color_t col = color_t::from_argb_bytes(game_config::team_rgb_range.find("white")->second.min());
|
||||
color_t col = game_config::team_rgb_range.find("white")->second.min();
|
||||
|
||||
if (!fogged) {
|
||||
if (side > -1) {
|
||||
|
@ -249,11 +249,11 @@ surface getMinimap(int w, int h, const gamemap &map, const team *vw, const std::
|
|||
} else {
|
||||
|
||||
if (vw->owns_village(loc))
|
||||
col = color_t::from_argb_bytes(game_config::color_info(preferences::unmoved_color()).rep());
|
||||
col = game_config::color_info(preferences::unmoved_color()).rep();
|
||||
else if (vw->is_enemy(side + 1))
|
||||
col = color_t::from_argb_bytes(game_config::color_info(preferences::enemy_color()).rep());
|
||||
col = game_config::color_info(preferences::enemy_color()).rep();
|
||||
else
|
||||
col = color_t::from_argb_bytes(game_config::color_info(preferences::allied_color()).rep());
|
||||
col = game_config::color_info(preferences::allied_color()).rep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,11 @@
|
|||
#ifndef COLOR_T_HPP_INCLUDED
|
||||
#define COLOR_T_HPP_INCLUDED
|
||||
|
||||
#include <algorithm> // for max
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <algorithm> // for max
|
||||
#include <utility>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
|
@ -234,4 +235,16 @@ inline std::ostream& operator<<(std::ostream& s, const color_t& c)
|
|||
return s;
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<color_t>
|
||||
{
|
||||
size_t operator()(const color_t& c) const
|
||||
{
|
||||
return c.to_rgba_bytes();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
#include "global.hpp"
|
||||
#include "color_range.hpp"
|
||||
|
||||
#include "sdl/utils.hpp"
|
||||
#include "sdl/rect.hpp"
|
||||
|
@ -1052,42 +1051,47 @@ surface swap_channels_image(const surface& surf, channel r, channel g, channel b
|
|||
return nsurf;
|
||||
}
|
||||
|
||||
surface recolor_image(surface surf, const std::map<Uint32, Uint32>& map_rgb, bool optimize){
|
||||
surface recolor_image(surface surf, const color_range_map& map_rgb, bool optimize)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if(!map_rgb.empty()){
|
||||
surface nsurf(make_neutral_surface(surf));
|
||||
if(nsurf == nullptr) {
|
||||
std::cerr << "failed to make neutral surface\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface_lock lock(nsurf);
|
||||
Uint32* beg = lock.pixels();
|
||||
Uint32* end = beg + nsurf->w*surf->h;
|
||||
|
||||
while(beg != end) {
|
||||
Uint8 alpha = (*beg) >> 24;
|
||||
|
||||
if(alpha){ // don't recolor invisible pixels.
|
||||
// palette use only RGB channels, so remove alpha
|
||||
Uint32 oldrgb = (*beg) & 0x00FFFFFF;
|
||||
std::map<Uint32, Uint32>::const_iterator i = map_rgb.find(oldrgb);
|
||||
if(i != map_rgb.end()){
|
||||
*beg = (alpha << 24) + i->second;
|
||||
}
|
||||
}
|
||||
++beg;
|
||||
}
|
||||
|
||||
if(optimize) {
|
||||
adjust_surface_alpha(nsurf, SDL_ALPHA_OPAQUE);
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
if(map_rgb.empty()) {
|
||||
return surf;
|
||||
}
|
||||
return surf;
|
||||
|
||||
surface nsurf(make_neutral_surface(surf));
|
||||
if(nsurf == nullptr) {
|
||||
std::cerr << "failed to make neutral surface" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface_lock lock(nsurf);
|
||||
Uint32* beg = lock.pixels();
|
||||
Uint32* end = beg + nsurf->w*surf->h;
|
||||
|
||||
while(beg != end) {
|
||||
Uint8 alpha = (*beg) >> 24;
|
||||
|
||||
// Don't recolor invisible pixels.
|
||||
if(alpha) {
|
||||
// Palette use only RGB channels, so remove alpha
|
||||
Uint32 oldrgb = (*beg) & 0x00FFFFFF;
|
||||
|
||||
auto i = map_rgb.find(color_t::from_argb_bytes(oldrgb));
|
||||
if(i != map_rgb.end()) {
|
||||
*beg = (alpha << 24) | i->second.to_argb_bytes();
|
||||
}
|
||||
}
|
||||
|
||||
++beg;
|
||||
}
|
||||
|
||||
if(optimize) {
|
||||
adjust_surface_alpha(nsurf, SDL_ALPHA_OPAQUE);
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface brighten_image(const surface &surf, fixed_t amount, bool optimize)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#ifndef SDL_UTILS_INCLUDED
|
||||
#define SDL_UTILS_INCLUDED
|
||||
|
||||
#include "color_range.hpp"
|
||||
#include "sdl/color.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
@ -252,8 +253,7 @@ surface swap_channels_image(const surface& surf, channel r, channel g, channel b
|
|||
* @return A recolored surface, or a null surface if there are
|
||||
* problems with the source.
|
||||
*/
|
||||
surface recolor_image(surface surf, const std::map<Uint32, Uint32>& map_rgb,
|
||||
bool optimize=true);
|
||||
surface recolor_image(surface surf, const color_range_map& map_rgb, bool optimize=true);
|
||||
|
||||
surface brighten_image(const surface &surf, fixed_t amount, bool optimize=true);
|
||||
|
||||
|
|
|
@ -820,19 +820,19 @@ const color_range team::get_side_color_range(int side)
|
|||
return(gp->second);
|
||||
}
|
||||
|
||||
return(color_range(0x00FF0000,0x00FFFFFF,0x00000000,0x00FF0000));
|
||||
return color_range({255, 0, 0}, {255, 255, 255}, {0, 0, 0}, {255, 0, 0});
|
||||
}
|
||||
|
||||
color_t team::get_side_color(int side)
|
||||
{
|
||||
return color_t::from_argb_bytes(get_side_color_range(side).mid());
|
||||
return get_side_color_range(side).mid();
|
||||
}
|
||||
|
||||
color_t team::get_minimap_color(int side)
|
||||
{
|
||||
// Note: use mid() instead of rep() unless
|
||||
// high contrast is needed over a map or minimap!
|
||||
return color_t::from_argb_bytes(get_side_color_range(side).rep());
|
||||
return get_side_color_range(side).rep();
|
||||
}
|
||||
|
||||
std::string team::get_side_color_index(int side)
|
||||
|
@ -850,7 +850,7 @@ std::string team::get_side_color_index(int side)
|
|||
|
||||
std::string team::get_side_highlight_pango(int side)
|
||||
{
|
||||
return color_t::from_argb_bytes(get_side_color_range(side + 1).mid()).to_hex_string();
|
||||
return get_side_color_range(side + 1).mid().to_hex_string();
|
||||
}
|
||||
|
||||
void team::log_recruitable() const {
|
||||
|
|
|
@ -361,9 +361,9 @@ public:
|
|||
|
||||
//function which, when given a 1-based side will return the color used by that side.
|
||||
static const color_range get_side_color_range(int side);
|
||||
static uint32_t get_side_rgb(int side) { return(get_side_color_range(side).mid()); }
|
||||
static uint32_t get_side_rgb_max(int side) { return(get_side_color_range(side).max()); }
|
||||
static uint32_t get_side_rgb_min(int side) { return(get_side_color_range(side).min()); }
|
||||
static color_t get_side_rgb(int side) { return(get_side_color_range(side).mid()); }
|
||||
static color_t get_side_rgb_max(int side) { return(get_side_color_range(side).max()); }
|
||||
static color_t get_side_rgb_min(int side) { return(get_side_color_range(side).min()); }
|
||||
static color_t get_side_color(int side);
|
||||
static color_t get_minimap_color(int side);
|
||||
static std::string get_side_color_index(int side);
|
||||
|
|
Loading…
Add table
Reference in a new issue