Fix #1987: halo remained after killing an unit with the context menu
The cause for this bug was the whiteboard. A unit destroys its halo when the unit itself is destroyed. Makes sense, right? Unfortunately, units are managed by shared pointers, and therefore are not destroyed until all references to them are gone. And the whiteboard retains a reference to the most recently selected unit. The obvious fix would be to use a weak (non-owning) pointer in the whiteboard, but it's sadly not possible because unit_ptr is an intrusive_ptr. It stores the reference count right in the unit itself, and therefore the refcount is lost when the unit is destroyed: hence weak pointers are impossible. Thus, what I ended up doing was explicitly notifying the whiteboard when an unit is killed, and releasing the reference when it happens. If anyone has suggestions about a better implementation, I'd love to hear them.
This commit is contained in:
parent
905f1eb391
commit
79554179e9
5 changed files with 15 additions and 0 deletions
|
@ -69,6 +69,7 @@
|
|||
#include "recall_list_manager.hpp" // for recall_list_manager
|
||||
#include "replay.hpp" // for get_user_choice, etc
|
||||
#include "reports.hpp" // for register_generator, etc
|
||||
#include "resources.hpp" // for whiteboard
|
||||
#include "scripting/lua_audio.hpp"
|
||||
#include "scripting/lua_unit.hpp"
|
||||
#include "scripting/lua_unit_attacks.hpp"
|
||||
|
@ -104,6 +105,7 @@
|
|||
#include "units/types.hpp" // for unit_type_data, unit_types, etc
|
||||
#include "variable.hpp" // for vconfig, etc
|
||||
#include "variable_info.hpp"
|
||||
#include "whiteboard/manager.hpp" // for whiteboard
|
||||
#include "wml_exception.hpp"
|
||||
|
||||
#include "utils/functional.hpp" // for bind_t, bind
|
||||
|
@ -2128,6 +2130,7 @@ int game_lua_kernel::intf_erase_unit(lua_State *L)
|
|||
}
|
||||
|
||||
units().erase(loc);
|
||||
resources::whiteboard->on_kill_unit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "formula/string_utils.hpp"
|
||||
#include "units/types.hpp"
|
||||
#include "units/udisplay.hpp"
|
||||
#include "whiteboard/manager.hpp"
|
||||
#include "font/standard_colors.hpp"
|
||||
|
||||
static lg::log_domain log_replay("replay");
|
||||
|
@ -533,6 +534,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_kill, child, use_undo, /*show*/, /*error_h
|
|||
if (i.valid()) {
|
||||
resources::gameboard->units().erase(i);
|
||||
}
|
||||
resources::whiteboard->on_kill_unit();
|
||||
actions::recalculate_fog(dying_side);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -58,6 +58,8 @@ public:
|
|||
/// @return the collection of actions that are highlighted but don't have the focus
|
||||
secondary_highlights_t get_secondary_highlights() { return secondary_highlights_; }
|
||||
|
||||
void set_selection_candidate(unit_ptr candidate) { selection_candidate_ = candidate; }
|
||||
|
||||
private:
|
||||
unit_map& get_unit_map();
|
||||
/** Unhighlight a given action (main or secondary). */
|
||||
|
|
|
@ -410,6 +410,13 @@ void manager::on_change_controller(int side, const team& t)
|
|||
}
|
||||
}
|
||||
|
||||
void manager::on_kill_unit()
|
||||
{
|
||||
if(highlighter_ != nullptr) {
|
||||
highlighter_->set_selection_candidate(unit_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
bool manager::current_side_has_actions()
|
||||
{
|
||||
if(current_side_actions()->empty()) {
|
||||
|
|
|
@ -92,6 +92,7 @@ public:
|
|||
void on_gamestate_change();
|
||||
void on_viewer_change(size_t team_index);
|
||||
void on_change_controller(int side, const team& t);
|
||||
void on_kill_unit();
|
||||
/** Handles various cleanup right before removing an action from the queue */
|
||||
void pre_delete_action(action_ptr action);
|
||||
/** Handles various cleanup right after removing an action from the queue */
|
||||
|
|
Loading…
Add table
Reference in a new issue