I'd register mouse position on MouseButtonPressed and set a bool "dragging" to true, check mouse position in MouseButtonReleased and set the "dragging" bool to false then if the 2 mouse positions are the same I activate the square.
On MouseMoved if dragging is true then I move the view. (I don't remember if the delta is inside the event data or if you have to compute it yourself)
That's pretty much how it works in your link. (if you manage to start and end you drag on the same position it activates the square)
I thought about a similar thing, and updated my code as well:
#include <iostream>
#include <SFML/Graphics.hpp>
#include <unordered_set>
#include <cmath>
#include "game_logic.h"
#include "patterns.h"
inline float distance(sf::Vector2i vec1, sf::Vector2i vec2){
return sqrt(pow(vec2.x - vec1.x, 2) + pow(vec2.y - vec1.y, 2));
}
int main(){
// We implement the grid using a sparse matrix - which is just a set that stores only the *live cells*.
std::unordered_set<sf::Vector2i, pair_hash, pair_equal> grid;
sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Game of life", sf::Style::Default);
bool focus = true; // True iff focus is on window.
bool getting_input = false, dragging = false;
sf::View view(sf::FloatRect(WINDOW_WIDTH * (MULTIPLE / 2), WINDOW_HEIGHT * (MULTIPLE / 2), WINDOW_WIDTH, WINDOW_HEIGHT));
// Since our initial view is different from the default view, we have to set it before we continue.
window.setView(view);
getting_input = true;
sf::Clock timestep_clock;
sf::Vector2i old_view_pos = sf::Mouse::getPosition(window), new_view_pos, drag_start;
while (window.isOpen()){
sf::Event evnt;
while (window.pollEvent(evnt)){
switch(evnt.type){
// The program exits when user closes the window by pressing 'X'.
case sf::Event::Closed:
window.close();
return 0;
break;
if (evnt.key.code == sf::Keyboard::Enter){
if (getting_input){ // Submitting input (finished getting input)
getting_input = false;
}
}
break;
// Because 'isKeyPressed' is "connected" to the actual device, it's getting input even when window is out of focus.
// We want to accept keyboard input only when the window has focus, so we have to keep track of it using a boolean.
case sf::Event::GainedFocus:
focus = true;
break;
case sf::Event::LostFocus:
focus = false;
break;
// Getting input from mouse.
case sf::Event::MouseButtonReleased:{
sf::Vector2i pixel_pos = sf::Mouse::getPosition(window);
sf::Vector2i view_pos = static_cast<sf::Vector2i>((window.mapPixelToCoords(pixel_pos)));
if (getting_input && evnt.mouseButton.button == sf::Mouse::Left && distance(drag_start, pixel_pos) <= 2 * CELL_SIZE){
handleLeftClick(window, grid, sf::Vector2i(view_pos.x, view_pos.y));
}
dragging = false;
break;
}
}
}
new_view_pos = sf::Mouse::getPosition(window);
if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left)){
if (!dragging){
dragging = true;
drag_start = new_view_pos;
}
sf::Vector2i deltaPos = old_view_pos - new_view_pos;
view.move(deltaPos.x, deltaPos.y);
window.setView(view);
}
old_view_pos = sf::Mouse::getPosition(window);
if (TIMESTEP <= timestep_clock.getElapsedTime() && !getting_input){
timestep_clock.restart();
updateGrid(grid)
}
window.clear();
drawGrid(window, grid);
window.display();
}
return 0;
}
But it's still not fluid. Mainly, if you click, release and move the mouse, it doesn't register the click sometimes.
I have a gif to show it:
https://gifyu.com/image/SR2k8Every time I move the mouse I also click it, and note how it sometimes doesn't register.
You mentioned using 'mouseMoved' event. I intentioanlly avoided it, and using events at all for this, because I know that dragging is a continous motion, and for that we prefer using functions that are "connected" to the device itself (like isKeyPressed). Basically, to mimic mouseMoved I simply save old_view_pos and new_view_pos.
Do you think I should switch to events?