Commit 34a8d8f1 authored by louiz’'s avatar louiz’

Add a way to get the entity under the mouse

parent f254e423
......@@ -109,16 +109,17 @@ void Camera::handle_middle_click(const sf::Event&)
void Camera::handle_right_click(const sf::Event& event)
{
const Position pos = this->camera_to_world_position(event.mouseButton.x,
const Position pos = this->screen_to_world_position(event.mouseButton.x,
event.mouseButton.y);
bool queue = sf::Keyboard::isKeyPressed(sf::Keyboard::LShift);
log_debug("queue: " << queue);
// A right click when there's an action associated with the left click
// just resets the default action of the right click.
// resets the default action of the right click.
if (this->screen->get_left_click().callback)
this->screen->reset_left_click();
else // otherwise it always does the move action.
// else // otherwise it always does the move action.
{
std::vector<EntityId> ids;
for (const auto& entity: this->game->get_selection().get_entities())
......@@ -140,7 +141,7 @@ void Camera::handle_left_click(const sf::Event& event)
}
else
{
const Position pos = this->camera_to_world_position(event.mouseButton.x,
const Position pos = this->screen_to_world_position(event.mouseButton.x,
event.mouseButton.y);
if (this->screen->get_left_click().callback(pos) == true)
this->screen->reset_left_click();
......@@ -174,6 +175,9 @@ void Camera::set_mouse_selection_to_selection()
entities_in_mouse_selection.push_back(entity.get());
}
if (entities_in_mouse_selection.empty())
return ;
auto end_own_entities = std::partition(entities_in_mouse_selection.begin(),
entities_in_mouse_selection.end(),
[this](const Entity* entity) -> bool
......@@ -252,6 +256,7 @@ void Camera::update(const utils::Duration& dt)
void Camera::draw()
{
const sf::Vector2i mouse_pos = this->get_mouse_position();
const Entity* entity_under_mouse = this->get_entity_under_mouse();
// Sort the sprites by their vertical position
this->sprites.sort([](const auto& a, const auto& b)
......@@ -310,8 +315,9 @@ void Camera::draw()
Team* team = entity->get<Team>();
if (entity->is_manipulable() &&
this->mouse_selection.contains(mouse_pos,
this->world_to_camera_position(sprite_world_position)))
this->mouse_selection.contains(this->get_mouse_position(),
this->world_to_camera_position(sprite_world_position))
)
{
this->draw_hover_indicator(
this->world_to_camera_position(sprite_world_position),
......@@ -337,6 +343,11 @@ void Camera::draw()
std::to_string(world_mouse_pos.x.to_double()) + ", " +
std::to_string(world_mouse_pos.y.to_double()));
if (entity_under_mouse)
this->game->get_debug_hud().add_debug_line("Entity under mouse: " + std::to_string(entity_under_mouse->get_id()));
else
this->game->get_debug_hud().add_debug_line("No entity under mouse");
this->draw(this->fog.get_sprite());
}
......@@ -450,6 +461,11 @@ sf::Vector2i Camera::get_mouse_position() const
}
Position Camera::camera_to_world_position(const int x, const int y) const
{
return this->screen_to_world_position(x - this->x, y - this->y);
}
Position Camera::screen_to_world_position(const int x, const int y) const
{
// The empty space at the top of the world, due to tile size. In pixels
static const unsigned int top_offset = TILE_TOP_OFFSET;
......@@ -611,6 +627,18 @@ bool Camera::is_mouse_selection_ongoing() const
return this->mouse_selection.ongoing;
}
const Entity* Camera::get_entity_under_mouse() const
{
auto mouse_pos = this->get_mouse_position();
for (auto it = this->sprites.crbegin(); it != this->sprites.crend(); ++it)
{
EntitySprite* sprite = it->get();
if (sprite->is_mouse_over(this) == true)
return sprite->get_entity();
}
return nullptr;
}
void Camera::draw(const sf::Drawable& drawable, const sf::RenderStates& states)
{
this->win().draw(drawable, states);
......
......@@ -92,6 +92,14 @@ public:
*/
void update(const utils::Duration& dt);
sf::Vector2i world_to_camera_position(const Position&) const;
/**
* Convert a mouse position, screen-related, into a world position
*/
Position screen_to_world_position(const int, const int) const;
/**
* Like screen_to_world_position, but with a camera-related position of
* the mouse
*/
Position camera_to_world_position(const int, const int) const;
/**
* Return the mouse position, taking into account the position of the
......@@ -129,6 +137,11 @@ public:
* ongoing or not.
*/
bool is_mouse_selection_ongoing() const;
/**
* Return a pointer to a selectable entity under the mouse, nullptr if there is none
*/
const Entity* get_entity_under_mouse() const;
void draw(const sf::Drawable&, const sf::RenderStates& states = sf::RenderStates::Default);
void on_new_entity(const Entity*);
void on_entity_deleted(const Entity*);
......
......@@ -43,6 +43,9 @@ AbilitiesPanel::AbilitiesPanel(GameClient* game)
return true;
const bool queue = (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift) ||
sf::Keyboard::isKeyPressed(sf::Keyboard::RShift));
const Entity* target = game->get_camera().get_entity_under_mouse();
log_debug("attacking with " << ids.size() << " entities");
return game->action_cast(ids, pos, AbilityType::Attack, queue);
},
......
......@@ -46,3 +46,21 @@ Position EntitySprite::get_world_pos() const
assert(location);
return location->position();
}
bool EntitySprite::is_mouse_over(const Camera* camera) const
{
Location* location = this->entity->get<Location>();
if (!location)
return false;
const auto pos = camera->get_mouse_position();
Position mouse_pos = camera->camera_to_world_position(pos.x,
pos.y);
Position ent_pos = location->position();
// TODO, use different values depending on the sprite's size
return (mouse_pos.x > ent_pos.x - 50 &&
mouse_pos.x < ent_pos.x + 50 &&
mouse_pos.y > ent_pos.y - 80 &&
mouse_pos.y < ent_pos.y + 20);
}
......@@ -15,6 +15,7 @@ public:
~EntitySprite() {}
const Entity* get_entity() const;
Position get_world_pos() const override final;
bool is_mouse_over(const Camera* camera) const;
protected:
const Entity* const entity;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment