The Battle for Wesnoth  1.19.28+dev
lua_color.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020 - 2025
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 color_range& LuaW_checkcolor(lua_State *L, int index)
29 {
30  return *static_cast<color_range*>(luaL_checkudata(L, index, colorKey));
31 }
32 
33 
34 static color_range* luaW_pushcolor(lua_State *L, const color_range& color)
35 {
36  color_range* res = new(L) color_range(color);
37  luaL_setmetatable(L, colorKey);
38  return res;
39 }
40 
41 static int luaW_pushsinglecolor(lua_State *L, const color_t& color)
42 {
43  lua_createtable(L, 0, 4);
44  luaW_table_set(L, -1, "r", color.r);
45  luaW_table_set(L, -1, "g", color.g);
46  luaW_table_set(L, -1, "b", color.b);
47  luaW_table_set(L, -1, "a", color.a);
48  return 1;
49 }
50 
51 static int impl_color_collect(lua_State *L)
52 {
53  color_range *c = static_cast<color_range *>(luaL_checkudata(L, 1, colorKey));
54  c->color_range::~color_range();
55  return 0;
56 }
57 
58 /**
59  * Checks two color units for equality. (__eq metamethod)
60  */
61 static int impl_color_equality(lua_State* L)
62 {
63  color_range& left = LuaW_checkcolor(L, 1);
64  color_range& right = LuaW_checkcolor(L, 2);
65  const bool equal = left == right;
66  lua_pushboolean(L, equal);
67  return 1;
68 }
69 
70 /**
71  * Turns a lua color to string. (__tostring metamethod)
72  */
73 static int impl_color_tostring(lua_State* L)
74 {
75  color_range& c = LuaW_checkcolor(L, 1);
76  //TODO: is this the best way to call tostring?
77  lua_push(L, c.debug());
78  return 1;
79 }
80 
81 
82 /**
83  * - Arg 1: userdata (ignored).
84  * - Arg 2: string containing the name of the color.
85  * - Ret 1: color_range containing the color.
86  */
87 static int impl_get_color(lua_State *L)
88 {
89  std::string color_id = luaL_checkstring(L, 2);
91  return 1;
92 }
93 
94 static int impl_color_get(lua_State *L)
95 {
96  color_range& c = LuaW_checkcolor(L, 1);
97  char const *m = luaL_checkstring(L, 2);
98 
99  if(strcmp(m, "min") == 0) {
100  return luaW_pushsinglecolor(L, c.min());
101  }
102  if(strcmp(m, "max") == 0) {
103  return luaW_pushsinglecolor(L, c.max());
104  }
105  if(strcmp(m, "mid") == 0) {
106  return luaW_pushsinglecolor(L, c.mid());
107  }
108  if(strcmp(m, "minimap") == 0) {
109  return luaW_pushsinglecolor(L, c.rep());
110  }
111  if(strcmp(m, "font_color") == 0) {
112  return luaW_pushsinglecolor(L, c.font_color());
113  }
114  // returns a string which can be used in Pango's foreground= attribute
115  if(strcmp(m, "pango_color") == 0) {
116  lua_push(L, c.font_color().to_hex_string());
117  return 1;
118  }
119  return 0;
120 }
121 
122 static int impl_color_dir(lua_State* L)
123 {
124  static const std::vector<std::string> keys{"min", "max", "mid", "minimap", "font_color", "pango_color"};
125  lua_push(L, keys);
126  return 1;
127 }
128 
129 static int impl_color_set(lua_State *L)
130 {
131  return luaL_argerror(L, 2, "color objects canot be modified");
132 }
133 
134 static int impl_colors_table_dir(lua_State* L)
135 {
136  std::vector<std::string> all_colours;
137  for(const auto& [key, value] : game_config::team_rgb_range) {
138  if(std::all_of(key.begin(), key.end(), [](char c) {return isdigit(c);})) {
139  // These colors are deprecated, don't show them
140  continue;
141  }
142  all_colours.push_back(key);
143  }
144  lua_push(L, all_colours);
145  return 1;
146 }
147 
148 namespace lua_colors {
149  std::string register_metatables(lua_State* L)
150  {
151  std::ostringstream cmd_out;
152 
153  // Create the color metatable.
154  cmd_out << "Adding color metatable...\n";
155 
156  luaL_newmetatable(L, colorKey);
157  lua_pushcfunction(L, impl_color_collect);
158  lua_setfield(L, -2, "__gc");
159  lua_pushcfunction(L, impl_color_equality);
160  lua_setfield(L, -2, "__eq");
161  lua_pushcfunction(L, impl_color_tostring);
162  lua_setfield(L, -2, "__tostring");
163  lua_pushcfunction(L, impl_color_get);
164  lua_setfield(L, -2, "__index");
165  lua_pushcfunction(L, impl_color_set);
166  lua_setfield(L, -2, "__newindex");
167  lua_pushcfunction(L, impl_color_dir);
168  lua_setfield(L, -2, "__dir");
169  lua_pushstring(L, "color range");
170  lua_setfield(L, -2, "__metatable");
171 
172 
173  // Create the colors variable with its metatable.
174  cmd_out << "Adding wesnoth.colors table...\n";
175 
176  lua_getglobal(L, "wesnoth");
177  lua_newuserdatauv(L, 0, 0);
178  lua_createtable(L, 0, 2);
179  lua_pushcfunction(L, impl_get_color);
180  lua_setfield(L, -2, "__index");
181  lua_pushcfunction(L, impl_colors_table_dir);
182  lua_setfield(L, -2, "__dir");
183  lua_pushstring(L, "colors table");
184  lua_setfield(L, -2, "__metatable");
185  lua_pushboolean(L, true);
186  lua_setfield(L, -2, "__dir_tablelike");
187  lua_setmetatable(L, -2);
188  lua_setfield(L, -2, "colors");
189  lua_pop(L, 1);
190 
191  return cmd_out.str();
192  }
193 }
Representing the "team color" information, this C++ class contains a subset of WML's [color_range] ta...
Definition: color_range.hpp:53
Standard logging facilities (interface).
static int impl_color_set(lua_State *L)
Definition: lua_color.cpp:129
static int impl_color_tostring(lua_State *L)
Turns a lua color to string.
Definition: lua_color.cpp:73
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:61
static int luaW_pushsinglecolor(lua_State *L, const color_t &color)
Definition: lua_color.cpp:41
static int impl_color_get(lua_State *L)
Definition: lua_color.cpp:94
static int impl_color_dir(lua_State *L)
Definition: lua_color.cpp:122
static color_range * luaW_pushcolor(lua_State *L, const color_range &color)
Definition: lua_color.cpp:34
static int impl_colors_table_dir(lua_State *L)
Definition: lua_color.cpp:134
static color_range & LuaW_checkcolor(lua_State *L, int index)
Definition: lua_color.cpp:28
static int impl_get_color(lua_State *L)
Definition: lua_color.cpp:87
static const char colorKey[]
Definition: lua_color.cpp:26
static int impl_color_collect(lua_State *L)
Definition: lua_color.cpp:51
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:149
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
constexpr auto keys
Definition: ranges.hpp:43
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
std::unique_ptr< MIX_Audio, decltype(&MIX_DestroyAudio)> value
Definition: sound.cpp:139
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:51
mock_char c