Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Drag and Drop from a Vector of Shapes  (Read 2340 times)

0 Members and 1 Guest are viewing this topic.

WellBob

  • Newbie
  • *
  • Posts: 2
    • View Profile
Drag and Drop from a Vector of Shapes
« on: August 23, 2020, 05:35:11 pm »
Hi. Looking to be able to drag and drop shapes from a vector, but I'm finding that when dragging one of the shapes I instead drag all of the shapes from the vector to the mouse position instead of just the single shape. Was wondering how I can drag the one shape without affecting the others?

#include <iostream>
#include "SFML/Graphics.hpp"
#include "Shape.h"
#include <vector>

int main()
{
    sf::RenderWindow window(sf::VideoMode(1280, 800), "SFML Game");

    sf::Event event;

    bool mouseClicked = false;
    bool mouseInsideRect = false;
    bool dragging = false;

    sf::Vector2f mouseRectOffset;

    int mouseX = 0;
    int mouseY = 0;

    std::vector<Shape> shapeVec;

    while (window.isOpen())
    {
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space)
            {
                Shape shape(window.getSize());
                shapeVec.push_back(shape);
            }

            if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left)
            {
                mouseClicked = true;

                for (int i = 0; i < shapeVec.size(); i++)
                {
                    dragging = true;
                    mouseRectOffset.x = event.mouseButton.x - shapeVec[i].GetShape().getGlobalBounds().left - shapeVec[i].GetShape().getOrigin().x;
                    mouseRectOffset.y = event.mouseButton.x - shapeVec[i].GetShape().getGlobalBounds().top - shapeVec[i].GetShape().getOrigin().y;
                }
            }

            if (event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left)
            {
                mouseClicked = false;
                dragging = false;
            }

            if (event.type == sf::Event::MouseMoved)
            {
                mouseX = event.mouseMove.x;
                mouseY = event.mouseMove.y;
            }
        }

        if (dragging == true)
        {
            for (int i = 0; i < shapeVec.size(); i++)
            {
                shapeVec[i].SetPos(mouseX - mouseRectOffset.x, mouseY - mouseRectOffset.y);
            }
        }

        window.clear();

        for (int i = 0; i < shapeVec.size(); i++)
        {
            shapeVec[i].Draw(window);
        }

        window.display();
    }

    return 0;
}
 

Hapax

  • Hero Member
  • *****
  • Posts: 3217
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Drag and Drop from a Vector of Shapes
« Reply #1 on: August 24, 2020, 11:50:11 pm »
Instead of looping through all the shapes in the vector and moving them all, just move the one you wish to move.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

WellBob

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Drag and Drop from a Vector of Shapes
« Reply #2 on: August 25, 2020, 06:28:32 pm »
How do I make sure that I'm selecting the element which the mouse has clicked on?

Paul

  • Jr. Member
  • **
  • Posts: 79
    • View Profile
Re: Drag and Drop from a Vector of Shapes
« Reply #3 on: August 26, 2020, 01:56:06 pm »
You can make new variable selectedShape which will be index in shapeVec, -1 if nothing is selected, >0 if something is selected. Or it can be pointer. The index should be assigned in shape vs cursor collision loop, which you don't have.

SFMLNewGuy

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Re: Drag and Drop from a Vector of Shapes
« Reply #4 on: September 04, 2020, 08:40:42 am »
How do I make sure that I'm selecting the element which the mouse has clicked on?

Hopefully, this helps, this was done quickly, but I think you can figure it out from here I believe.

#include <iostream>
#include "SFML/Graphics.hpp"

#include <vector>

struct Shape
{
    Shape(sf::Vector2f size) {
        shape.setSize(size);
        shape.setFillColor(sf::Color::Transparent);
        shape.setOutlineThickness(1.f);
        shape.setOutlineColor(sf::Color::Green);
    }
    sf::RectangleShape shape;
    bool selected = false;
};

int main() {
    sf::RenderWindow window(sf::VideoMode(1280, 800), "SFML Game");
    srand((unsigned)time(nullptr));

    sf::Event event;

    bool mouseClicked = false;
    bool mouseInsideRect = false;
    bool dragging = false;

    sf::Vector2f mouseRectOffset;

    int mouseX = 0;
    int mouseY = 0;

    std::vector<Shape> shapeVec;
    Shape* currentShape = nullptr;          // keep track of current shape being moved

    for (int i = 0; i < 10; ++i) {
        auto shape = new Shape({ 64.f,64.f });
        shape->shape.setPosition(rand() % 1100 + 100, rand() % 650 + 100);
        shapeVec.push_back(*shape);

    }
    while (window.isOpen()) {
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed || event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
                window.close();
            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space) {
                auto shape = new Shape({ 64.f,64.f });
                shape->shape.setPosition(rand() % 1100 + 100, rand() % 650 + 100);
                shapeVec.push_back(*shape);
            }

       
        }

        // get the mouse position
        auto mpos = window.mapPixelToCoords(sf::Mouse::getPosition(window));

        // Moving the shapes
        if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
            if (mpos.x >= 0 && mpos.x < window.getSize().x && mpos.y >= 0 * mpos.y < window.getSize().y && !dragging) {
                dragging = true;
                for (auto& it : shapeVec) {
                    if (it.shape.getGlobalBounds().contains(mpos.x, mpos.y)) {
                        it.selected = true;
                        currentShape = &it;
                        break;
                    }
                }
            }
        }
        else {
           
            dragging = false;
            if (currentShape)
                currentShape->selected = false;
        }

        // removing the shapes
        if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {
            if (mpos.x >= 0 && mpos.x < window.getSize().x && mpos.y >= 0 * mpos.y < window.getSize().y) {
                auto shapeIt = shapeVec.begin();
                while (shapeIt != shapeVec.end()) {
                    auto it = *shapeIt;
                    if (it.shape.getGlobalBounds().contains(mpos.x, mpos.y)) {
                        shapeIt = shapeVec.erase(shapeIt);
                    }
                    else {
                        ++shapeIt;
                    }
                }
            }
        }

        if (dragging == true) {
            for (int i = 0; i < shapeVec.size(); i++) {
                if(shapeVec[i].selected)
                     shapeVec[i].shape.setPosition(mpos.x,mpos.y);

            }
        }

        window.clear();

        for (int i = 0; i < shapeVec.size(); i++) {
            window.draw(shapeVec[i].shape);
        }

        window.display();
    }

    return 0;
}
« Last Edit: September 04, 2020, 09:00:39 am by SFMLNewGuy »