The Battle for Wesnoth  1.19.7+dev
lua_color.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020 - 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "color_range.hpp"
16 #include "scripting/lua_color.hpp"
17 #include "scripting/lua_common.hpp"
18 #include "scripting/push_check.hpp"
19 #include "log.hpp"
20 #include "game_config.hpp"
21 
22 static lg::log_domain log_scripting_lua("scripting/lua");
23 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
24 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
25 
26 static const char colorKey[] = "color range";
27 
28 static bool luaW_iscolor(lua_State* L, int index)
29 {
30  return luaL_testudata(L, index, colorKey) != nullptr;
31 }
32 
33 static color_range& LuaW_checkcolor(lua_State *L, int index)
34 {
35  if(!luaW_iscolor(L, index)) {
36  luaW_type_error(L, index, "color");
37  throw "luaW_type_error returned";
38  }
39  return *static_cast<color_range*>(lua_touserdata(L, index));
40 }
41 
42 
43 static color_range* luaW_pushcolor(lua_State *L, const color_range& color)
44 {
45  color_range* res = new(L) color_range(color);
46  luaL_setmetatable(L, colorKey);
47  return res;
48 }
49 
50 static int luaW_pushsinglecolor(lua_State *L, const color_t& color)
51 {
52  lua_createtable(L, 0, 4);
53  luaW_table_set(L, -1, "r", color.r);
54  luaW_table_set(L, -1, "g", color.g);
55  luaW_table_set(L, -1, "b", color.b);
56  luaW_table_set(L, -1, "a", color.a);
57  return 1;
58 }
59 
60 static int impl_color_collect(lua_State *L)
61 {
62  color_range *c = static_cast<color_range *>(lua_touserdata(L, 1));
63  c->color_range::~color_range();
64  return 0;
65 }
66 
67 /**
68  * Checks two color units for equality. (__eq metamethod)
69  */
70 static int impl_color_equality(lua_State* L)
71 {
72  color_range& left = LuaW_checkcolor(L, 1);
73  color_range& right = LuaW_checkcolor(L, 2);
74  const bool equal = left == right;
75  lua_pushboolean(L, equal);
76  return 1;
77 }
78 
79 /**
80  * Turns a lua color to string. (__tostring metamethod)
81  */
82 static int impl_color_tostring(lua_State* L)
83 {
84  color_range& c = LuaW_checkcolor(L, 1);
85  //TODO: is this the best way to call tostring?
86  lua_push(L, c.debug());
87  return 1;
88 }
89 
90 
91 /**
92  * - Arg 1: userdata (ignored).
93  * - Arg 2: string containing the name of the color.
94  * - Ret 1: color_range containing the color.
95  */
96 static int impl_get_color(lua_State *L)
97 {
98  std::string color_id = luaL_checkstring(L, 2);
100  return 1;
101 }
102 
103 static int impl_color_get(lua_State *L)
104 {
105  color_range& c = LuaW_checkcolor(L, 1);
106  char const *m = luaL_checkstring(L, 2);
107 
108  if(strcmp(m, "min") == 0) {
109  return luaW_pushsinglecolor(L, c.min());
110  }
111  if(strcmp(m, "max") == 0) {
112  return luaW_pushsinglecolor(L, c.max());
113  }
114  if(strcmp(m, "mid") == 0) {
115  return luaW_pushsinglecolor(L, c.mid());
116  }
117  if(strcmp(m, "minimap") == 0) {
118  return luaW_pushsinglecolor(L, c.rep());
119  }
120  // returns a string which can be used in Pango's foreground= attribute
121  if(strcmp(m, "pango_color") == 0) {
122  lua_push(L, c.mid().to_hex_string());
123  return 1;
124  }
125  return 0;
126 }
127 
128 static int impl_color_dir(lua_State* L)
129 {
130  static const std::vector<std::string> keys{"min", "max", "mid", "minimap", "pango_color"};
131  lua_push(L, keys);
132  return 1;
133 }
134 
135 static int impl_color_set(lua_State *L)
136 {
137  return luaL_argerror(L, 2, "color objects canot be modified");
138 }
139 
140 static int impl_colors_table_dir(lua_State* L)
141 {
142  std::vector<std::string> all_colours;
143  for(const auto& [key, value] : game_config::team_rgb_range) {
144  if(std::all_of(key.begin(), key.end(), [](char c) {return isdigit(c);})) {
145  // These colors are deprecated, don't show them
146  continue;
147  }
148  all_colours.push_back(key);
149  }
150  lua_push(L, all_colours);
151  return 1;
152 }
153 
154 namespace lua_colors {
155  std::string register_metatables(lua_State* L)
156  {
157  std::ostringstream cmd_out;
158 
159  // Create the color metatable.
160  cmd_out << "Adding color metatable...\n";
161 
162  luaL_newmetatable(L, colorKey);
163  lua_pushcfunction(L, impl_color_collect);
164  lua_setfield(L, -2, "__gc");
165  lua_pushcfunction(L, impl_color_equality);
166  lua_setfield(L, -2, "__eq");
167  lua_pushcfunction(L, impl_color_tostring);
168  lua_setfield(L, -2, "__tostring");
169  lua_pushcfunction(L, impl_color_get);
170  lua_setfield(L, -2, "__index");
171  lua_pushcfunction(L, impl_color_set);
172  lua_setfield(L, -2, "__newindex");
173  lua_pushcfunction(L, impl_color_dir);
174  lua_setfield(L, -2, "__dir");
175  lua_pushstring(L, "color range");
176  lua_setfield(L, -2, "__metatable");
177 
178 
179  // Create the colors variable with its metatable.
180  cmd_out << "Adding wesnoth.colors table...\n";
181 
182  lua_getglobal(L, "wesnoth");
183  lua_newuserdatauv(L, 0, 0);
184  lua_createtable(L, 0, 2);
185  lua_pushcfunction(L, impl_get_color);
186  lua_setfield(L, -2, "__index");
187  lua_pushcfunction(L, impl_colors_table_dir);
188  lua_setfield(L, -2, "__dir");
189  lua_pushstring(L, "colors table");
190  lua_setfield(L, -2, "__metatable");
191  lua_pushboolean(L, true);
192  lua_setfield(L, -2, "__dir_tablelike");
193  lua_setmetatable(L, -2);
194  lua_setfield(L, -2, "colors");
195  lua_pop(L, 1);
196 
197  return cmd_out.str();
198  }
199 }
A color range definition is made of four reference RGB colors, used for calculating conversions from ...
Definition: color_range.hpp:49
Standard logging facilities (interface).
static int impl_color_set(lua_State *L)
Definition: lua_color.cpp:135
static int impl_color_tostring(lua_State *L)
Turns a lua color to string.
Definition: lua_color.cpp:82
static lg::log_domain log_scripting_lua("scripting/lua")
static int impl_color_equality(lua_State *L)
Checks two color units for equality.
Definition: lua_color.cpp:70
static bool luaW_iscolor(lua_State *L, int index)
Definition: lua_color.cpp:28
static int luaW_pushsinglecolor(lua_State *L, const color_t &color)
Definition: lua_color.cpp:50
static int impl_color_get(lua_State *L)
Definition: lua_color.cpp:103
static int impl_color_dir(lua_State *L)
Definition: lua_color.cpp:128
static color_range * luaW_pushcolor(lua_State *L, const color_range &color)
Definition: lua_color.cpp:43
static int impl_colors_table_dir(lua_State *L)
Definition: lua_color.cpp:140
static color_range & LuaW_checkcolor(lua_State *L, int index)
Definition: lua_color.cpp:33
static int impl_get_color(lua_State *L)
Definition: lua_color.cpp:96
static const char colorKey[]
Definition: lua_color.cpp:26
static int impl_color_collect(lua_State *L)
Definition: lua_color.cpp:60
int luaW_type_error(lua_State *L, int narg, const char *tname)
std::map< std::string, color_range, std::less<> > team_rgb_range
Colors defined by WML [color_range] tags.
const color_range & color_info(std::string_view name)
std::string register_metatables(lua_State *L)
Definition: lua_color.cpp:155
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:425
void luaW_table_set(lua_State *L, int index, std::string_view k, const T &value)
Definition: push_check.hpp:457
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
mock_char c