Skip to content

Commit

Permalink
Add wesnoth.interface.add_floating_label as a replacement for wesnoth…
Browse files Browse the repository at this point in the history
….print

This returns a label handle which allows you to remove, reposition, or replace the label later.

In addition to all the features of wesnoth.print, you can now specify where the label appears onscreen.
  • Loading branch information
CelticMinstrel committed Mar 26, 2021
1 parent de4a59d commit ee03289
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 38 deletions.
Expand Up @@ -1270,12 +1270,12 @@
[/filter_condition]

# Print a reminder of the time limit
[print]
[floating_label]
text= _ "$(16 - $turn_number) turns remain to free $number_merfolk_caged| merfolk"
size=24
duration=5000
color=200,200,255
[/print]
[/floating_label]
[/event]

[event]
Expand Down
10 changes: 5 additions & 5 deletions data/campaigns/tutorial/utils/utils.cfg
@@ -1,18 +1,18 @@
#textdomain wesnoth-tutorial

#define PRINT STRING
[print]
[floating_label]
text={STRING}
size=18
duration=10000
red,green,blue=255,255,255
[/print]
color=255,255,255
[/floating_label]
#enddef

#define CLEAR_PRINT
[print]
[floating_label]
text="" # wmllint: ignore
[/print]
[/floating_label]
#enddef

#define GENDER MALE_WML FEMALE_WML
Expand Down
8 changes: 4 additions & 4 deletions data/core/macros/ai_controller.cfg
Expand Up @@ -485,11 +485,11 @@
{VARIABLE ai_controller_{AFFIX}.defend_location.original_controller_invokation_y $y1}
{VARIABLE ai_controller_finished yes}

[print]
[floating_label]
text= _ "Right-click to select a location to defend"
duration=100
{COLOR_WHITE}
[/print]
[/floating_label]

[set_menu_item]
id=ai_controller_defend_location_picker
Expand Down Expand Up @@ -523,7 +523,7 @@
[/goal]
)}

[print]
[floating_label]
text=" " # wmllint: ignore
duration=1
[/print]
Expand Down Expand Up @@ -551,7 +551,7 @@
[then]
{VARIABLE ai_controller_{AFFIX}.defend_location.picker_active no}

[print]
[floating_label]
text= _ "Location selection canceled"
duration=100
{COLOR_WHITE}
Expand Down
4 changes: 4 additions & 0 deletions data/lua/core/interface.lua
Expand Up @@ -53,6 +53,10 @@ if wesnoth.kernel_type() == "Game Lua Kernel" then
wesnoth.zoom = wesnoth.deprecate_api('wesnoth.zoom', 'wesnoth.interface.zoom', 1, nil, wesnoth.interface.zoom)
wesnoth.gamestate_inspector = wesnoth.deprecate_api('wesnoth.gamestate_inspector', 'gui.show_inspector', 1, nil, gui.show_inspector)
wesnoth.color_adjust = deprecate_api('wesnoth.color_adjust', 'wesnoth.interface.color_adjust', 1, nil, wesnoth.interface.color_adjust)
-- wesnoth.wml_actions.print doesn't exist yet at this point, so create a helper function instead.
wesnoth.print = wesnoth.deprecate_api('wesnoth.print', 'wesnoth.interface.add_floating_label', 1, nil, function(cfg)
wesnoth.wml_actions.print(cfg)
end)
-- No deprecation for these since since they're not actually public API yet
wesnoth.set_menu_item = wesnoth.interface.set_menu_item
wesnoth.clear_menu_item = wesnoth.interface.clear_menu_item
Expand Down
33 changes: 32 additions & 1 deletion data/lua/wml-tags.lua
Expand Up @@ -819,8 +819,39 @@ function wml_actions.redraw(cfg)
wesnoth.redraw(cfg, clear_shroud)
end

local wml_floating_label = nil
function wml_actions.print(cfg)
wesnoth.print(cfg)
wesnoth.deprecation_message('[print]', 1, nil, 'use [floating_label] instead')
if wml_floating_label then
wml_floating_label:remove()
end
local label_text = {cfg.text}
if cfg.size then
table.insert(label_text, cfg.size)
end
if cfg.color then
table.insert(label_text, stringx.split(cfg.color))
elseif cfg.red or cfg.green or cfg.blue then
table.insert(label_text, {cfg.red or 0, cfg.green or 0, cfg.blue or 0})
end

wesnoth.interface.add_floating_label(label_text, cfg.duration or 50)
end

function wml_actions.floating_label(cfg)
local label_text = {cfg.text}
if cfg.size then
table.insert(label_text, cfg.size)
end
if cfg.color then
table.insert(label_text, stringx.split(cfg.color))
end
local offset = nil
if cfg.x_offset or cfg.y_offset then
offset = {cfg.x_offset or 0, cfg.y_offset or 0}
end

wesnoth.interface.add_floating_label(label_text, cfg.duration, offset)
end

function wml_actions.unsynced(cfg)
Expand Down
152 changes: 127 additions & 25 deletions src/scripting/game_lua_kernel.cpp
Expand Up @@ -1869,42 +1869,144 @@ int game_lua_kernel::intf_find_cost_map(lua_State *L)
return 1;
}

int game_lua_kernel::intf_print(lua_State *L) {
vconfig cfg(luaW_checkvconfig(L, 1));

// Remove any old message.
static int floating_label = 0;
if (floating_label)
font::remove_floating_label(floating_label);
const char* labelKey = "floating label";

// Display a message on-screen
std::string text = cfg["text"];
if(text.empty() || !game_display_)
return 0;
static int* luaW_check_floating_label(lua_State* L, int idx)
{
return reinterpret_cast<int*>(luaL_checkudata(L, idx, labelKey));
}

int size = cfg["size"].to_int(font::SIZE_SMALL);
int lifetime = cfg["duration"].to_int(50);
static int impl_floating_label_getmethod(lua_State* L)
{
const char* m = luaL_checkstring(L, 2);
return_bool_attrib("valid", *luaW_check_floating_label(L, 1) != 0);
return luaW_getmetafield(L, 1, m);
}

color_t color = font::LABEL_COLOR;
int game_lua_kernel::intf_remove_floating_label(lua_State* L)
{
int* handle = luaW_check_floating_label(L, 1);
if(*handle != 0) {
font::remove_floating_label(*handle);
}
*handle = 0;
return 0;
}

if(!cfg["color"].empty()) {
color = color_t::from_rgb_string(cfg["color"]);
} else if(cfg.has_attribute("red") || cfg.has_attribute("green") || cfg.has_attribute("blue")) {
color = color_t(cfg["red"], cfg["green"], cfg["blue"]);
int game_lua_kernel::intf_move_floating_label(lua_State* L)
{
int* handle = luaW_check_floating_label(L, 1);
if(*handle != 0) {
font::move_floating_label(*handle, luaL_checknumber(L, 2), luaL_checknumber(L, 3));
}
return 0;
}

int game_lua_kernel::intf_set_floating_label(lua_State* L, bool spawn)
{
int first_arg = spawn ? 1 : 2;
t_string text;
int size = font::SIZE_SMALL;
color_t color = font::LABEL_COLOR;
if(!luaW_totstring(L, first_arg, text)) {
if(lua_type(L, first_arg) != LUA_TTABLE) {
return luaW_type_error(L, 1, "string or table");
}
for(lua_Unsigned i = 1; i <= lua_rawlen(L, first_arg); i++) {
lua_geti(L, first_arg, i);
if(i == 1) {
text = luaW_checktstring(L, -1);
} else switch(lua_type(L, -1)) {
default:
return luaL_error(L, "unknown floating label text setting - should be either size (integer) or color (hex string or array of 3 integers)");
case LUA_TNUMBER:
size = lua_tointeger(L, -1);
break;
case LUA_TSTRING:
color = color_t::from_hex_string(lua_tostring(L, -1));
break;
case LUA_TTABLE:
auto vec = lua_check<std::vector<int>>(L, -1);
if(vec.size() != 3) {
return luaL_error(L, "floating label text color should be a hex string or an array of 3 integers");
}
color.r = vec[0];
color.g = vec[1];
color.b = vec[2];
break;
}
lua_pop(L, 1);
}
}

int lifetime = 2'000;
map_location loc{0, 0, wml_loc()};
bool found_location = false;
switch(lua_type(L, first_arg + 1)) {
case LUA_TNIL: case LUA_TNONE:
break;
case LUA_TTABLE:
luaW_tolocation(L, first_arg + 1, loc);
found_location = true;
break;
case LUA_TNUMBER:
lifetime = lua_tointeger(L, first_arg + 1);
break;
case LUA_TSTRING:
if(luaW_tostring(L, first_arg + 1) == "infinity") {
lifetime = -1;
break;
}
[[fallthrough]];
default:
return luaW_type_error(L, first_arg + 1, "integer or 'infinity'");
}

if(!found_location && !lua_isnoneornil(L, first_arg + 2)) {
loc = luaW_checklocation(L, first_arg + 2);
}

int* handle = nullptr;
if(spawn) {
// Creating a new label, allocate a new handle
handle = new(L)int();
} else {
// First argument is the label handle
handle = luaW_check_floating_label(L, 1);
}
int handle_idx = lua_gettop(L);

if(*handle != 0) {
font::remove_floating_label(*handle);
}

const SDL_Rect& rect = game_display_->map_outside_area();

int x = rect.x + rect.w / 2 + loc.wml_x(), y = rect.y + rect.h / 2 + loc.wml_y();

font::floating_label flabel(text);
flabel.set_font_size(size);
flabel.set_color(color);
flabel.set_position(rect.x + rect.w/2, rect.y + rect.h/2);
flabel.set_position(x, y);
flabel.set_lifetime(lifetime);
flabel.set_clip_rect(rect);

floating_label = font::add_floating_label(flabel);

return 0;

*handle = font::add_floating_label(flabel);
lua_settop(L, handle_idx);
if(luaL_newmetatable(L, labelKey)) {
// Initialize the metatable
static const luaL_Reg methods[] = {
{"remove", &dispatch<&game_lua_kernel::intf_remove_floating_label>},
{"move", &dispatch<&game_lua_kernel::intf_move_floating_label>},
{"replace", &dispatch2<&game_lua_kernel::intf_set_floating_label, false>},
{"__index", &impl_floating_label_getmethod},
{ nullptr, nullptr }
};
luaL_setfuncs(L, methods, 0);
luaW_table_set(L, -1, "__metatable", std::string(labelKey));
}
lua_setmetatable(L, handle_idx);
lua_settop(L, handle_idx);
return 1;
}

void game_lua_kernel::put_unit_helper(const map_location& loc)
Expand Down Expand Up @@ -3946,7 +4048,6 @@ game_lua_kernel::game_lua_kernel(game_state & gs, play_controller & pc, reports
{ "log_replay", &dispatch<&game_lua_kernel::intf_log_replay > },
{ "log", &dispatch<&game_lua_kernel::intf_log > },
{ "message", &dispatch<&game_lua_kernel::intf_message > },
{ "print", &dispatch<&game_lua_kernel::intf_print > },
{ "redraw", &dispatch<&game_lua_kernel::intf_redraw > },
{ "remove_event_handler", &dispatch<&game_lua_kernel::intf_remove_event > },
{ "replace_schedule", &dispatch<&game_lua_kernel::intf_replace_schedule > },
Expand Down Expand Up @@ -4177,6 +4278,7 @@ game_lua_kernel::game_lua_kernel(game_state & gs, play_controller & pc, reports
{"zoom", &dispatch<&game_lua_kernel::intf_zoom>},
{"clear_menu_item", &dispatch<&game_lua_kernel::intf_clear_menu_item>},
{"set_menu_item", &dispatch<&game_lua_kernel::intf_set_menu_item>},
{"add_floating_label", &dispatch2<&game_lua_kernel::intf_set_floating_label, true>},
{ nullptr, nullptr }
};
lua_getglobal(L, "wesnoth");
Expand Down
4 changes: 3 additions & 1 deletion src/scripting/game_lua_kernel.hpp
Expand Up @@ -115,7 +115,9 @@ class game_lua_kernel : public lua_kernel_base
int intf_message(lua_State *L);
int intf_open_help(lua_State *L);
int intf_play_sound(lua_State *L);
int intf_print(lua_State *L);
int intf_set_floating_label(lua_State* L, bool spawn);
int intf_remove_floating_label(lua_State* L);
int intf_move_floating_label(lua_State* L);
void put_unit_helper(const map_location& loc);
int intf_put_unit(lua_State *L);
int intf_erase_unit(lua_State *L);
Expand Down

0 comments on commit ee03289

Please sign in to comment.