-
Hey, I would like to draw a rectangle that resizes when the user move the mouse. Like when you click and drag on a desktop. I tried doing it with this code:
while(drag){
while(StartWindow.GetEvent(Event)){
sf::Vector2f coords = StartWindow.ConvertCoords(StartWindow.GetInput().GetMouseX(),StartWindow.GetInput().GetMouseY());
x2 = coords.x;
y2 = coords.y;
rectangle = sf::Shape::Rectangle(x,y,x2,y2,sf::Color::Blue,1,sf::Color::Red);
StartWindow.SetView(StartWindow.GetDefaultView());
rectangle.SetPosition(x,y);
StartWindow.Draw(rectangle);
}
This code is pretty incomplete, but its supposed to make a drag-able rectangle selection tool. This does draw the rectangle, but not where the the user clicks. Can anyone help me with this code, or suggest some new code? Thanks.
[/code]
-
I didn't really look too deeply at your code, because I didn't really get your logic at first glance. Why "while(drag)"?
Also, you already stated that it wasn't complete.
Anyway, I felt in the mood, and went and created a small program that does what you asked for:#include <SFML/Graphics.hpp>
int main()
{
// Initialization
sf::RenderWindow window( sf::VideoMode( 800, 600 ), "DragBox" );
const sf::Input &input = window.GetInput();
sf::Vector2i mouseDownPosition;
// Program loop
while( window.IsOpened() )
{
// Event handling
sf::Event event;
while( window.GetEvent( event ) )
{
if( event.Type == sf::Event::Closed )
window.Close();
else if( event.Type == sf::Event::MouseButtonPressed &&
event.MouseButton.Button == sf::Mouse::Left )
{
mouseDownPosition.x = event.MouseButton.X;
mouseDownPosition.y = event.MouseButton.Y;
}
}
// Drawing
window.Clear();
if( input.IsMouseButtonDown( sf::Mouse::Left ) )
{
sf::Shape box = sf::Shape::Rectangle( mouseDownPosition.x, mouseDownPosition.y,
input.GetMouseX(), input.GetMouseY(),
sf::Color( 0, 0, 0, 0 ), -1.f, sf::Color::Yellow );
window.Draw( box );
}
window.Display();
}
}
Another time, it is a good idea to post a minimal and complete example that demonstrates your problem. ;)
-
Thank you so much!! It turned out that I was defining the rectangle, then setting the position when I didn't need to set the position. Thanks!
-
Question, when you do that, creating a new sf::Shape, does it delete the previous from memory ? or does it leave a memory leak?
-
No, the variable dies when it goes out of scope, so there is no memory leak.
Had it been created withsf::Shape *box = new sf::Shape::Rectangle( ... );
it would stay in memory until deleted as:delete box;
-
Hi, I'm trying to do the same thing in SFML 2.1, but I'm having some trouble. I only get a square that disappears when I move the mouse.
This is my current code (based on model76's code):
#include <SFML/Graphics.hpp>
int main(int argc , char * argv[] )
{
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int BITS_PER_PIXEL = 32;
sf::VideoMode VMode( SCREEN_WIDTH , SCREEN_HEIGHT , BITS_PER_PIXEL );
sf::RenderWindow window( VMode , "SFML!" , sf::Style::Titlebar | sf::Style::Close );
sf::Vector2i mouse_position;
mouse_position = sf::Mouse::getPosition( window );
while( window.isOpen() )
{
sf::Event event;
while( window.pollEvent( event ) )
{
if( event.type == sf::Event::Closed || event.key.code == sf::Keyboard::Escape ) window.close();
if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left )
{
mouse_position.x = event.mouseButton.x;
mouse_position.y = event.mouseButton.y;
}
}
window.clear();
if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left )
{
sf::RectangleShape box;
box.setPosition( mouse_position.x , mouse_position.y );
box.setSize( sf::Vector2f( sf::Mouse::getPosition().x - mouse_position.x , sf::Mouse::getPosition().y - mouse_position.y ) );
box.setFillColor( sf::Color::White );
window.draw( box );
}
window.display();
}
return 0;
}
Thank you in advance. :-)
-
General idea:
When Mouse button left pressed, save position as start position, until Mouse button left released, calculate:
If start position X < mouse X, Draw rectangle from mouse X to start position x else draw from start position X to mouse X
Do same logic for Y axis and you got yourself the math complete now implement it using sfml. Good luck!
-
That's exactly what I'm trying to do though. :-\
Problem is, I can only set x, y and size, instead of x1, x2, y1 and y2.
The only thing I could think of is
box.setSize( sf::Vector2f( sf::Mouse::getPosition().x - mouse_position.x , sf::Mouse::getPosition().y - mouse_position.y ) );
...Where mouse_position is the x and y, but apparently I'm doing something wrong because it does not work at all as intended.
-
Never use events outside of the event loop!
Don't forget to give your window to sf::Mouse::getPosition()...
You could change the size of your box inside a MouseMoved event so that it's only modified when the mouse moves.
-
Here is a example of how i did it, but if you don't make your own damn copy and rewrite it all... I will me bad >:(
void SetRectangle(sf::Vector2f & startPos, sf::Vector2f & mousePos, sf::RectangleShape & rec)
{
if (mousePos.x < startPos.x && mousePos.y < startPos.y)//Mouse is left up of start, use mouse for x and y
{
rec.setPosition(mousePos.x, mousePos.y);
rec.setSize(sf::Vector2f(startPos.x - mousePos.x, startPos.y - mousePos.y));
}
else if (mousePos.x < startPos.x)//Rectagle is left down of start pos
{
rec.setPosition(mousePos.x, startPos.y);
rec.setSize(sf::Vector2f(startPos.x - mousePos.x, mousePos.y - startPos.y));
}
else if (mousePos.y < startPos.y)//Rectagle is right up of start pos
{
rec.setPosition(startPos.x, mousePos.y);
rec.setSize(sf::Vector2f(mousePos.x - startPos.x, startPos.y - mousePos.y));
}
else//Rectangle is right down, default state
{
rec.setPosition(startPos.x, startPos.y);
rec.setSize(sf::Vector2f(mousePos.x - startPos.x, mousePos.y - startPos.y));
}
}
int main()
{
sf::View view;
view.reset(sf::FloatRect(0, 0, float(800), float(600)));
view.setViewport(sf::FloatRect(0, 0, 1.f, 1.f));
sf::RenderWindow win;
sf::VideoMode vidMod(800, 600, 32);
win.create(vidMod, "test", sf::Style::Default);
win.setFramerateLimit(100);
win.setView(view);
sf::RectangleShape rec;
rec.setFillColor(sf::Color::White);
sf::Vector2f startPos;
sf::Vector2f mousePos;
bool isDrawRectangle = false;
bool done = false;
while (done == false)
{
win.clear();
sf::Event event;
while (win.pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
done = true;
break;
case sf::Event::MouseButtonPressed:
switch (event.mouseButton.button)
{
case sf::Mouse::Button::Left:
isDrawRectangle = true;
startPos = mousePos;
break;
default:
break;
}
break;
case sf::Event::MouseButtonReleased:
switch (event.mouseButton.button)
{
case sf::Mouse::Button::Left:
isDrawRectangle = false;
break;
default:
break;
}
break;
case sf::Event::MouseMoved:
mousePos.x = event.mouseMove.x;
mousePos.y = event.mouseMove.y;
break;
default:
break;
}
}
SetRectangle(startPos, mousePos, rec);
if (isDrawRectangle)
win.draw(rec);
win.display();
}
return 0;
}
-
Thanks for the help. sf::Event::MouseMoved is what I needed it seems. My code works perfectly now, and I think I can simplify it later, too. :)
#include <SFML/Graphics.hpp>
int main(int argc , char * argv[] )
{
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int BITS_PER_PIXEL = 32;
sf::VideoMode VMode( SCREEN_WIDTH , SCREEN_HEIGHT , BITS_PER_PIXEL );
sf::RenderWindow window( VMode , "SFML!" , sf::Style::Titlebar | sf::Style::Close );
sf::Vector2i starting_position;
starting_position = sf::Mouse::getPosition( window );
sf::Vector2f current_position;
sf::RectangleShape box;
while( window.isOpen() )
{
sf::Event event;
while( window.pollEvent( event ) )
{
if( event.type == sf::Event::Closed || event.key.code == sf::Keyboard::Escape ) window.close();
if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left )
{
starting_position.x = event.mouseButton.x;
starting_position.y = event.mouseButton.y;
}
if( event.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed(sf::Mouse::Left) )
{
current_position.x = event.mouseMove.x - starting_position.x;
current_position.y = event.mouseMove.y - starting_position.y;
box.setSize( current_position );
box.setPosition( starting_position.x , starting_position.y );
box.setFillColor( sf::Color::White );
}
}
window.clear();
window.draw( box );
window.display();
}
return 0;
}
@BaneTrapper Haha, don't worry mate, I never just copy/paste code anyway. Thanks for the example. ;D