add wesnoth.colors

see #3706

the main usecase to be able to show messages and
dialog labels in the color of a specific team.
This commit is contained in:
gfgtdf 2020-03-10 21:13:28 +01:00
parent f166e2edee
commit f9790bcb5d
7 changed files with 218 additions and 0 deletions

View file

@ -2624,6 +2624,9 @@
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Debug|Win32'">$(IntDir)Scripting\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|Win32'">$(IntDir)Scripting\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\scripting\lua_color.cpp">
<ObjectFileName>$(IntDir)Scripting\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\scripting\lua_common.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)Scripting\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='ReleaseDEBUG|Win32'">$(IntDir)Scripting\</ObjectFileName>

View file

@ -2634,6 +2634,9 @@
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Debug|x64'">$(IntDir)Scripting\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|x64'">$(IntDir)Scripting\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\scripting\lua_color.cpp">
<ObjectFileName>$(IntDir)Scripting\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\scripting\lua_common.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)Scripting\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='ReleaseDEBUG|x64'">$(IntDir)Scripting\</ObjectFileName>
@ -3981,6 +3984,7 @@
<ClInclude Include="..\..\src\scripting\debug_lua.hpp" />
<ClInclude Include="..\..\src\scripting\game_lua_kernel.hpp" />
<ClInclude Include="..\..\src\scripting\lua_audio.hpp" />
<ClInclude Include="..\..\src\scripting\lua_color.hpp" />
<ClInclude Include="..\..\src\scripting\lua_common.hpp" />
<ClInclude Include="..\..\src\scripting\lua_cpp_function.hpp" />
<ClInclude Include="..\..\src\scripting\lua_fileops.hpp" />

View file

@ -310,6 +310,7 @@ scripting/application_lua_kernel.cpp
scripting/debug_lua.cpp
scripting/game_lua_kernel.cpp
scripting/lua_audio.cpp
scripting/lua_color.cpp
scripting/lua_common.cpp
scripting/lua_cpp_function.cpp
scripting/lua_fileops.cpp

174
src/scripting/lua_color.cpp Normal file
View file

@ -0,0 +1,174 @@
/*
Copyright (C) 2020-2020 by the Battle for Wesnoth Project https://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "color_range.hpp"
#include "scripting/lua_color.hpp"
#include "scripting/lua_common.hpp"
#include "scripting/push_check.hpp"
#include "lua/lauxlib.h"
#include "lua/lua.h" // for lua_State, lua_settop, etc
#include "log.hpp"
#include "game_config.hpp"
static lg::log_domain log_scripting_lua("scripting/lua");
#define LOG_LUA LOG_STREAM(info, log_scripting_lua)
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)
static const char colorKey[] = "color range";
bool luaW_iscolor(lua_State* L, int index)
{
return luaL_testudata(L, index, colorKey) != nullptr;
}
static color_range& LuaW_checkcolor(lua_State *L, int index)
{
if(!luaW_iscolor(L, index)) {
luaW_type_error(L, index, "color");
throw "luaW_type_error returned";
}
return *static_cast<color_range*>(lua_touserdata(L, index));
}
color_range* luaW_pushcolor(lua_State *L, const color_range& color)
{
color_range* res = new(L) color_range(color);
luaL_setmetatable(L, colorKey);
return res;
}
int luaW_pushsinglecolor(lua_State *L, const color_t& color)
{
lua_createtable(L, 0, 4);
luaW_table_set(L, -1, "r", color.r);
luaW_table_set(L, -1, "g", color.g);
luaW_table_set(L, -1, "b", color.b);
luaW_table_set(L, -1, "a", color.a);
return 1;
}
static int impl_color_collect(lua_State *L)
{
color_range *c = static_cast<color_range *>(lua_touserdata(L, 1));
c->color_range::~color_range();
return 0;
}
/**
* Checks two color units for equality. (__eq metamethod)
*/
static int impl_color_equality(lua_State* L)
{
color_range& left = LuaW_checkcolor(L, 1);
color_range& right = LuaW_checkcolor(L, 2);
const bool equal = left == right;
lua_pushboolean(L, equal);
return 1;
}
/**
* Turns a lua color to string. (__tostring metamethod)
*/
static int impl_color_tostring(lua_State* L)
{
color_range& c = LuaW_checkcolor(L, 1);
//TODO: is this the best way to call tostring?
lua_push(L, c.debug());
return 1;
}
/**
* - Arg 1: userdata (ignored).
* - Arg 2: string containing the name of the color.
* - Ret 1: color_range containing the color.
*/
static int impl_get_color(lua_State *L)
{
std::string color_id = luaL_checkstring(L, 2);
luaW_pushcolor(L, game_config::color_info(color_id));
return 1;
}
static int impl_color_get(lua_State *L)
{
color_range& c = LuaW_checkcolor(L, 1);
char const *m = luaL_checkstring(L, 2);
if(strcmp(m, "min") == 0) {
return luaW_pushsinglecolor(L, c.min());
}
if(strcmp(m, "max") == 0) {
return luaW_pushsinglecolor(L, c.max());
}
if(strcmp(m, "mid") == 0) {
return luaW_pushsinglecolor(L, c.mid());
}
if(strcmp(m, "minimap") == 0) {
return luaW_pushsinglecolor(L, c.rep());
}
// TODO: i think this shortcut would be useful, but im not sure yet on the best attribute name.
//if(strcmp(m, "pango_hex") == 0) {
// lua_push(L, c.mid().to_hex_string());
// return 1;
//}
return 0;
}
static int impl_color_set(lua_State *L)
{
return luaL_argerror(L, 2, "color objects canot be modified");
}
namespace lua_colors {
std::string register_metatables(lua_State* L)
{
std::ostringstream cmd_out;
// Create the getunit metatable.
cmd_out << "Adding color metatable...\n";
luaL_newmetatable(L, colorKey);
lua_pushcfunction(L, impl_color_collect);
lua_setfield(L, -2, "__gc");
lua_pushcfunction(L, impl_color_equality);
lua_setfield(L, -2, "__eq");
lua_pushcfunction(L, impl_color_tostring);
lua_setfield(L, -2, "__tostring");
lua_pushcfunction(L, impl_color_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, impl_color_set);
lua_setfield(L, -2, "__newindex");
lua_pushstring(L, "color range");
lua_setfield(L, -2, "__metatable");
// Create the current variable with its metatable.
cmd_out << "Adding wesnoth.colors table...\n";
lua_getglobal(L, "wesnoth");
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, impl_get_color);
lua_setfield(L, -2, "__index");
lua_pushstring(L, "colors table");
lua_setfield(L, -2, "__metatable");
lua_setmetatable(L, -2);
lua_setfield(L, -2, "colors");
lua_pop(L, 1);
return cmd_out.str();
}
}

View file

@ -0,0 +1,19 @@
/*
Copyright (C) 2020-2020 by the Battle for Wesnoth Project https://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include <string>
struct lua_State;
namespace lua_colors {
std::string register_metatables(lua_State* L);
}

View file

@ -28,6 +28,7 @@
#include "scripting/debug_lua.hpp"
#endif
#include "scripting/lua_color.hpp"
#include "scripting/lua_common.hpp"
#include "scripting/lua_cpp_function.hpp"
#include "scripting/lua_fileops.hpp"
@ -570,6 +571,8 @@ lua_kernel_base::lua_kernel_base()
// Create formula bridge metatables
cmd_log_ << lua_formula_bridge::register_metatables(L);
cmd_log_ << lua_colors::register_metatables(L);
// Create the Lua interpreter table
cmd_log_ << "Sandboxing Lua interpreter...\nTo make variables visible outside the interpreter, assign to _G.variable.\n";
cmd_log_ << "The special variable _ holds the result of the last expression (if any).\n";

View file

@ -397,3 +397,17 @@ lua_check_impl::remove_constref<T> luaW_table_get_def(lua_State *L, int index, u
lua_pop(L, 1);
return res;
}
template<typename T>
void luaW_table_set(lua_State *L, int index, utils::string_view k, const T& value)
{
if(!lua_istable(L, index)) {
luaL_argerror(L, index, "table expected");
}
index = lua_absindex(L, index);
lua_pushlstring(L, k.data(), k.size());
lua_push(L, value);
lua_settable(L, index);
}