The Battle for Wesnoth  1.19.27+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  // returns a string which can be used in Pango's foreground= attribute
112  if(strcmp(m, "pango_color") == 0) {
113  lua_push(L, c.mid().to_hex_string());
114  return 1;
115  }
116  return 0;
117 }
118 
119 static int impl_color_dir(lua_State* L)
120 {
121  static const std::vector<std::string> keys{"min", "max", "mid", "minimap", "pango_color"};
122  lua_push(L, keys);
123  return 1;
124 }
125 
126 static int impl_color_set(lua_State *L)
127 {
128  return luaL_argerror(L, 2, "color objects canot be modified");
129 }
130 
131 static int impl_colors_table_dir(lua_State* L)
132 {
133  std::vector<std::string> all_colours;
134  for(const auto& [key, value] : game_config::team_rgb_range) {
135  if(std::all_of(key.begin(), key.end(), [](char c) {return isdigit(c);})) {
136  // These colors are deprecated, don't show them
137  continue;
138  }
139  all_colours.push_back(key);
140  }
141  lua_push(L, all_colours);
142  return 1;
143 }
144 
145 namespace lua_colors {
146  std::string register_metatables(lua_State* L)
147  {
148  std::ostringstream cmd_out;
149 
150  // Create the color metatable.
151  cmd_out << "Adding color metatable...\n";
152 
153  luaL_newmetatable(L, colorKey);
154  lua_pushcfunction(L, impl_color_collect);
155  lua_setfield(L, -2, "__gc");
156  lua_pushcfunction(L, impl_color_equality);
157  lua_setfield(L, -2, "__eq");
158  lua_pushcfunction(L, impl_color_tostring);
159  lua_setfield(L, -2, "__tostring");
160  lua_pushcfunction(L, impl_color_get);
161  lua_setfield(L, -2, "__index");
162  lua_pushcfunction(L, impl_color_set);
163  lua_setfield(L, -2, "__newindex");
164  lua_pushcfunction(L, impl_color_dir);
165  lua_setfield(L, -2, "__dir");
166  lua_pushstring(L, "color range");
167  lua_setfield(L, -2, "__metatable");
168 
169 
170  // Create the colors variable with its metatable.
171  cmd_out << "Adding wesnoth.colors table...\n";
172 
173  lua_getglobal(L, "wesnoth");
174  lua_newuserdatauv(L, 0, 0);
175  lua_createtable(L, 0, 2);
176  lua_pushcfunction(L, impl_get_color);
177  lua_setfield(L, -2, "__index");
178  lua_pushcfunction(L, impl_colors_table_dir);
179  lua_setfield(L, -2, "__dir");
180  lua_pushstring(L, "colors table");
181  lua_setfield(L, -2, "__metatable");
182  lua_pushboolean(L, true);
183  lua_setfield(L, -2, "__dir_tablelike");
184  lua_setmetatable(L, -2);
185  lua_setfield(L, -2, "colors");
186  lua_pop(L, 1);
187 
188  return cmd_out.str();
189  }
190 }
A color range definition is made of four reference RGB colors, used for calculating conversions from ...
Definition: color_range.hpp:43
Standard logging facilities (interface).
static int impl_color_set(lua_State *L)
Definition: lua_color.cpp:126
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:119
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:131
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:146
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