Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Déplacement de "Frame" trop lente par rapport à la souris.  (Lu 3983 fois)

0 Membres et 1 Invité sur ce sujet

gaulois94

  • Sr. Member
  • ****
  • Messages: 259
    • Voir le profil
Bonjours,

alors voila, dans ma GUI, j'ai créé la classe Frame qui permet de créer des "petites fenêtres". Comme tout fenêtre, je laisse la possibilité de la déplacer avec la souris !!!

Mais voila, lors du déplacement, la Frame va beaucoup moins vite que ma souris !!! . Pour vous montrez cela, voici une petite vidéo qui montre comment fonctionne le tout : http://www.youtube.com/watch?v=PHNHG8KLR40&feature=youtu.be

Maintenant que tout est dit, voici comment le tout fonctionne en interne ;) (je ne vous met que les fonctions appelé pour faire ce déplacement ;) ) :

[#include "Widget.h"
#include "Button.h"
#include "Window.h"
#include "Frame.h"
#include <iostream>

int main()
{
        guiml::Window window(sf::VideoMode(800, 600), "teste"); //création de la fenêtre
        guiml::Frame frame(&window, sf::IntRect(100, 100, 550, 400), sf::Color(0, 255, 255), guiml::Image(), guiml::Label(NULL, std::string("Teste")), sf::Color(255, 0, 0)); //définition de la Frame
        while(window.isOpen())
        {
                window.update();
        }
        return 0;
}/code]

EventManager.cpp
[code=cpp]void EventManager::update()
{
        //du code

        while(w->pollEvent(m_event)) //w est un pointeur vers la classe Window.
        {
                if(m_event.type == sf::Event::KeyReleased)
                        if(m_event.key.code < static_cast<int>(NBR_KEYS))
                        {
                                m_keys[m_event.key.code] = false;
                                m_isInputKey[m_event.key.code] = false;
                        }

                if(m_event.type == sf::Event::KeyPressed)
                        if(m_event.key.code < static_cast<int>(NBR_KEYS))
                        {
                                m_isInputKey[m_event.key.code] = true;
                                m_keys[m_event.key.code] = true;
                                m_hasPressedKeyKey = true;
                        }

                if(m_event.type == sf::Event::MouseButtonReleased)
                        if(m_event.mouseButton.button < static_cast<int>(NBR_CLICS))
                        {
                                m_mouseClicked[m_event.mouseButton.button] = m_isInputMouse[m_event.mouseButton.button] = false;
                        }

                if(m_event.type == sf::Event::MouseButtonPressed)
                        if(m_event.mouseButton.button < static_cast<int>(NBR_CLICS))
                        {
                                m_isInputMouse[m_event.mouseButton.button] = true;
                                m_mouseClicked[m_event.mouseButton.button] = true;
                                m_hasPressedKeyMouse = true;
                        }
                //encore du code
        }
 //du code
}

Et on arrive à la classe Frame.cpp
void Frame::update(std::list<sf::Drawable*> &drawable)
        {
                if(m_isDrawing)
                {
                        std::cout << m_isMoving << std::endl; //permet de savoir si la frame bouge ou non.
                        if(isMoving()) //la condition du problème.
                        {
                                sf::Vector2i oldMousePos = getEventManager()->getOldMousePosition();
                                sf::Vector2i mousePos = getEventManager()->getMousePosition();
                                move(mousePos.x - oldMousePos.x, mousePos.y - oldMousePos.y);
                        }
                        //du code qui ne doit pas servir à grand chose
                }
                 //du code
        }

Bon, j'imagine qu'il vous manque des .h pour vous y repérer (une sorte de doc), alors les voici :

Window.h
#ifndef DEF_WINDOW
#define DEF_WINDOW

#include "EventManager.h"
#include "Image.h"
#include "Render.h"

namespace guiml
{
        class Window : public Render, public sf::RenderWindow
        {
        public:
                Window(const sf::VideoMode &mode, const std::string &title, Widget *parent = NULL, unsigned int framerateLimit = 60, const sf::Color &backgroundColor = sf::Color::Black, const Image &backgroundImage = Image());
                virtual ~Window();

                void update();
                void update(std::list<sf::Drawable*> &drawable); //update all widgets and the event
                void show(std::list<sf::Drawable*> &drawable); //draw the window

                void setPosition(int x, int y);
                void setSize(int x, int y);
                virtual void setTitle(const std::string &title);
                void setView(const sf::View &view);
                void resetView();

                virtual EventManager* getEventManager() const;
                unsigned int getFramerate();
                virtual void resizeWidget(const sf::Vector2i& defaultWindowSize, const sf::Vector2i& newWindowSize);
        protected:
                EventManager *m_event;
                float m_framerate;
        };
}

#endif

Widget.h
#ifndef DEF_WIDGET
#define DEF_WIDGET

#include <SFML/Graphics.hpp>
#include <list>
#include <iostream>
#include <stdexcept>
#include "EventManager.h"

namespace guiml
{
        class Widget
        {
        public:
                Widget(Widget *parent, const sf::IntRect &rect = sf::IntRect(0, 0, 0, 0));
                Widget(const Widget &copy);

                virtual ~Widget();

                virtual void addChild(Widget *child, int pos = -1); //add a child of the widget
                void setParent(Widget *parent, int pos = -1); //set parent of the widget
                void removeChild(Widget *child); //remove one child of the widget
                virtual void drawWidget(bool drawing); //You can, if you want, draw or don't draw the widget
                void drawAllChild(bool drawing); //it simular that DrawWidget but is for all Children.

                virtual void update(std::list<sf::Drawable*> &drawables); //Update all Children of the Widget

                virtual void setPosition(const sf::Vector2i &newPos);
                virtual void setPosition(int x, int y);
                virtual void setSize(const sf::Vector2i &newSize);
                virtual void setSize(int x, int y);
                void move(int x, int y);
                void move(const sf::Vector2i &moving);
                void addSize(const sf::Vector2i &addingSize);
                void addSize(int x, int y);
                virtual void scale(float x, float y);
                virtual void scale(const sf::Vector2f &scaling);
                virtual void scale(float x);
                void moveAllChild(bool movingAllChild);

                bool getMovingAllChild() const;

                bool isDrawing() const; //boolean for know if this Widgets drawing or no.
                bool isChild(const Widget *child);
                bool hasParent() const;
                virtual EventManager* getEventManager() const; //get de EventManager who will be use for all of children.

                const sf::Vector2i& getPosition() const;
                const sf::Vector2i& getVirtualPosition() const;
                const sf::Vector2i& getSize() const;
                const sf::Vector2i& getVirtualSize() const;

                virtual sf::IntRect getRect() const;
                virtual sf::IntRect getVirtualRect() const;

                virtual void setRect(const sf::IntRect &rect);
                virtual Widget& operator=(const Widget &copy);
                virtual void resizeWidget(const sf::Vector2i& defaultWindowSize, const sf::Vector2i& newWindowSize);
                virtual Widget* copy() const;
        protected:
                std::list <Widget*> m_child;
                Widget *m_parent;
                bool m_isDrawing;
                sf::Vector2i m_pos;
                sf::Vector2i m_size;
                sf::Vector2i m_virtualPos;
                sf::Vector2i m_virtualSize;
                bool m_movingAllChild;
        };
}

#endif

EventManager.h
#ifndef DEF_EVENTMANAGER
#define DEF_EVENTMANAGER

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

const unsigned int NBR_KEYS = 321;
const unsigned int NBR_CLICS = 3;

class EventManager
{
public:
        EventManager(sf::Window *win);
        ~EventManager();
        void update(); //Update events
        void setDefaultWindowSize(const sf::Vector2i& defaultWindowSize);

        bool getPressedKey(unsigned int choice) const; //get the key who corresponds of the choice
        bool getOnePressedKey(unsigned int choice) const;
        const sf::Uint32& getText() const;
        bool isEnteredText() const;
        bool getMouseClicked(unsigned int choice) const; //get the key of the mouse who corresponds of the choice
        bool getOneMouseClicked(unsigned int choice) const;
        const sf::Vector2i &getMousePosition() const; //get the position of the mouse
        const sf::Vector2i &getOldMousePosition() const;
        template <typename T>
        bool isMouseInRect(const sf::Rect<T> &rect) const //See if the mouse is in the area of rect.
        {
                if(m_mousePos.x > rect.left
                && m_mousePos.x < rect.left + rect.width
                && m_mousePos.y > rect.top
                && m_mousePos.y < rect.top + rect.height)
                        return true;
                return false;
        }

        float getElapsedTime() const; //Return the time sell between two frames in microSeconds
        const sf::Event& getEvent() const;
        bool hasPressedKeyMouse() const;
        bool hasPressedKeyKey() const;
        bool windowIsResize() const;
        const sf::Vector2i& getNewWindowSize() const;
        const sf::Vector2i& getOldWindowSize() const;
        const sf::Vector2i& getDefaultWindowSize() const;
private:
        sf::Window *w;
        sf::Event m_event;
        bool m_keys[NBR_KEYS];
        sf::Uint32 m_text;
        bool m_enteredText;
        bool m_mouseClicked[NBR_CLICS];
        sf::Vector2i m_mousePos;
        sf::Vector2i m_oldMousePos;
        float m_elapsedTime;
        sf::Clock m_clock;
        bool m_isInputKey[NBR_KEYS];
        bool m_isInputMouse[NBR_CLICS];
        bool m_hasPressedKeyMouse;
        bool m_hasPressedKeyKey;
        bool m_isResize;
        sf::Vector2i m_newSize;
        sf::Vector2i m_oldSize;
        sf::Vector2i m_defaultSize;
};

#endif

Button.h
#ifndef DEF_BUTTON
#define DEF_BUTTON

#include "Widget.h"
#include "Image.h"
#include "Label.h"

namespace guiml
{
        class Button : public Widget
        {
        public:
                #include "SurchargeMethode.h"
                //-----------------------------------All constructors for various parameters-------------------------------------//
                Button(Widget *parent, const Label &text, const sf::IntRect &rect = sf::IntRect(0, 0, 0, 0));
                Button(Widget *parent, const Image &image, const sf::IntRect &rect = sf::IntRect(0, 0, 0, 0));
                Button(Widget *parent, const Label &text, const Image &image, const sf::IntRect &rect = sf::IntRect(0, 0, 0, 0));
                Button(Widget *parent);
                Button();
                Button(const Button &copy);
                //-------------------------------------------End of constructors--------------------------------------------//

                virtual void update(std::list<sf::Drawable*> &drawable);
                bool cursorInButton();
                void lightUpDrawable(bool lighten = true);

                //------------------------------------------Mutateurs---------------------------------------------------//
                virtual void drawWidget(bool drawing);
                void setPosition(int posx, int posy);
                void setSize(int sizex, int sizey);
                void setBackground(const Image &image);
                void setLabel(const Label &string);
                void selectIt(bool select);
                void activedIt(bool actived);

                void setKeyboardWhoActived(const sf::Keyboard::Key &key);
                void setClickMouseWhoActived(const sf::Mouse::Button &mouseButton);
                void setCharacterSize(unsigned int newsize);

                //-----------------------------------------End of Mutateurs--------------------------------------------//


                const Label* getLabel() const;
                const Image* getBackground() const;
                const unsigned int getKeyboardWhoActived() const;
                const unsigned int getClickMouseWhoActived() const;

                bool hasImage()const ;
                bool hasLabel() const ;
                bool isSelect() const ;
                bool isActived() const ;

                Button& operator=(const Button &copy);
                Widget* copy() const;

        protected:
                void centerLabel(); //Center the Label with regard to the background
                bool m_hasBackground;
                bool m_hasLabel;

                Image m_background;
                Label m_text;
                Image m_backgroundLighten;
                Label m_textLighten;
                Image *m_currentBackground;
                Label *m_currentLabel;
                bool m_isSelect;
                bool m_isSelectCopy;

                unsigned int m_howActivedKeyboard;
                unsigned int m_howActivedClickMouse;
                bool m_isActived;
        };
}

#endif

et enfin Frame.h
#ifndef DEF_FRAME
#define DEF_FRAME

#include "Label.h"
#include "Button.h"
#include "Render.h"

namespace guiml
{
        enum PosText
        {
                CENTER,
                RIGHT,
                LEFT
        };

        class Frame : public Render, public sf::RenderTexture
        {
        public:
                Frame(Widget *parent, const sf::IntRect &rect, const sf::Color &backgroundColor = sf::Color::Black, const Image &backgroundImage = Image(), const Label &title = Label(), const sf::Color &backgroundTitle = sf::Color(255, 255, 255, 255));

                void update(std::list<sf::Drawable*> &drawable);
                void show(std::list<sf::Drawable*> &drawable);

                void setTitle(const Label &title);
                void setTitle(const std::string &title);
                void setSize(int x, int y);
                void setPosition(int x, int y);
                void setBackgroundTitle(const sf::Color &colorTitle);
                void setRectMovingFrame(const sf::IntRect &rect);
                void setTitlePos(const PosText &posTitle);
                void setBackgroundImage(const Image &backgroundImage);
                void setView(const sf::View &view);
                void resetView();

                const Label& getLabelTitle() const;
                sf::IntRect getRectMoveFrame() const;
                sf::FloatRect getViewport() const;

                const PosText& positionTitle() const;
                bool isMoving();
        protected:
                void testIsMoving();
                sf::RectangleShape m_backgroundTitle;
                sf::Sprite m_spriteFrame;
                guiml::Label m_title;
                Button m_buttonMoveFrame;
                PosText m_posTitle;
                bool m_isMoving;
                bool m_hasAddChild;
        };
}

#endif

Voila, je pense avoir terminé :D . Merci d'avance ;)
« Modifié: Mai 25, 2012, 11:39:55 pm par gaulois94 »

Orwel

  • Full Member
  • ***
  • Messages: 208
    • Voir le profil
Re : Déplacement de "Frame" trop lente par rapport à la souris.
« Réponse #1 le: Mai 25, 2012, 11:37:50 pm »
Citer
je ne vous met que les fonctions appelé pour faire ce déplacement
Non, tu as mis les classes utiliser pour faire le déplacement. Malheureusement, cela représente énormément de code. Personne ne vas le lire, bien que ton code est bien mis en forme.

Met juste la fonction où tu captures les événement SFML et là où la fenêtre est déplacée.

gaulois94

  • Sr. Member
  • ****
  • Messages: 259
    • Voir le profil
Re : Déplacement de "Frame" trop lente par rapport à la souris.
« Réponse #2 le: Mai 25, 2012, 11:38:49 pm »
Très bien ;) (j'ai mis tout ce qui avait en rapport avec le problème, pour pas qu'il vous manque des infos... en revoyant le tout, je pense que j'ai mal fait x) ).

édit : c'est fait. Les deux premiers fichiers sont les .cpp, et le reste les .h qu'utilise le programme pour arriver à cette fonctionnalité.

édit : vous pouvez d'ailleurs voir dans la vidéo (en HD) qu'il y a un bout de pixel qui dépasse en haut à gauch, chose pas normale en sachant que j'utilise une sf::RenderTexture (et que donc elle doit être parfaitement rectangulaire).
« Modifié: Mai 26, 2012, 12:39:57 am par gaulois94 »

Orwel

  • Full Member
  • ***
  • Messages: 208
    • Voir le profil
Re : Déplacement de "Frame" trop lente par rapport à la souris.
« Réponse #3 le: Mai 26, 2012, 01:33:16 pm »
Je pense qu'il y a toujours trop de code inutile, et le code qui pourrait nous permmetre de t'aider est encore absent.

Citer
                                sf::Vector2i oldMousePos = getEventManager()->getOldMousePosition();
                                sf::Vector2i mousePos = getEventManager()->getMousePosition();
                                move(mousePos.x - oldMousePos.x, mousePos.y - oldMousePos.y);

Dans Frame::Update, tu appelles les méthodes getEventManager et move. Elle ne sont pas déclarer dans le header de la classe Frame. Et tu n'a pas mis le .cpp

Citer
Met juste la fonction où tu captures les événement SFML et là où la fenêtre est déplacée.

ps:: Je n'ai pas la possibilité de mettre des balises de code  :-\

gaulois94

  • Sr. Member
  • ****
  • Messages: 259
    • Voir le profil
Re : Déplacement de "Frame" trop lente par rapport à la souris.
« Réponse #4 le: Mai 26, 2012, 02:04:53 pm »
Elles ne sont pas déclarer dans les headers de Frame car sont dans l'header de Widget (or Frame hérite de Widget ;) ).

Voila ce que je fais pour move et pour capturer les events : (le problème est savoir quelle partie du code vous aidera x) ).

update les events dans Window.update()
m_event->update(); //m_event est un EventManager

Voici maintenant la partie intéressante pour la souris de event.update()
while(w->pollEvent(m_event)) //w est un pointeur vers la Window qui appelle cette fonction (ici window présent dans le main).
        {
                if(m_event.type == sf::Event::MouseMoved)
                {
                        m_oldMousePos = m_mousePos;
                        m_mousePos = sf::Vector2i(m_event.mouseMove.x, m_event.mouseMove.y);
                }
        }
 

Maintenant voici comment je fait pour le move et le setPosition() présent dans la classe Widget :
void Widget::move(int x, int y)
        {
                setPosition(m_virtualPos.x + x, m_virtualPos.y + y);
        }

void Widget::setPosition(int x, int y)
        {
                if(m_movingAllChild) //permet de déplacer les enfants du Widgets en même temps (ici, la Frame déplace le cadre rouge, le titre).
                        for(std::list<Widget*>::iterator it = m_child.begin(); it != m_child.end(); ++it)
                                (*it)->move(x - m_virtualPos.x, y - m_virtualPos.y);

                EventManager *event = getEventManager();
                if(event)
                {
                        sf::Vector2i defaultWindowSize = event->getDefaultWindowSize();
                        if(defaultWindowSize.x != 0 && defaultWindowSize.y != 0) //évitez des divisions par zéro.
                        {
                                sf::Vector2i newWindowSize = event->getNewWindowSize();
                                m_pos = sf::Vector2i(x * newWindowSize.x/defaultWindowSize.x, y * newWindowSize.y / defaultWindowSize.y);
                        }
                        else
                                m_pos = sf::Vector2i(x, y);
                }
                else

                m_pos = sf::Vector2i(x, y); //m_pos est la position tenant compte si la fenêtre est redimensionné ou non
                m_virtualPos = sf::Vector2i(x, y); //m_virtualPos ne tient pas compte des redimensionnements de la fenêtre
        }
 

Frame.setPosition() mais elle ne sert pas à grand chose ici x) . Il permet juste de changer les variables m_pos. Pour regarder comment elle est utiliser, il faut regarder Frame.update(const sf::Drawable* drawable)
void Frame::setPosition(int x, int y)
        {
                moveView(x - m_virtualPos.x, y - m_virtualPos.y); //déplace la vu de la Frame
                Widget::setPosition(x, y);
        }

void Frame::update(std::list<sf::Drawable*> &drawable)
        {
                if(m_isDrawing) //si on souhaite afficher la Frame
                {
                        if(isMoving())
                        {
                                sf::Vector2i oldMousePos = getEventManager()->getOldMousePosition();
                                sf::Vector2i mousePos = getEventManager()->getMousePosition();
                                move(mousePos.x - oldMousePos.x, mousePos.y - oldMousePos.y);
                        }

                        for(std::list<Widget*>::iterator it = m_child.begin(); it != m_child.end(); ++it)
                                (*it)->move(m_virtualPos.x, m_virtualPos.y); //déplace tout les Widgets enfants. En effet, un Widget position à (0, 0) se situe visuellement à m_virtualPos (aide pour la souris)

                        clear(m_backgroundColor);
                        std::list<sf::Drawable*> drawableForFrame; //regroupe les sf::Drawable que souhaite afficher les Widgets.
                        Widget::update(drawableForFrame); //update tout les Widgets.
                        show(drawableForFrame); //appele la méthode show pour déssiner les Widgets sur le render
                        drawable.push_back(&m_spriteFrame); //demande à la classe Window de déssiner le sprite de la Frame (voir émthode show())

                        for(std::list<Widget*>::iterator it = m_child.begin(); it != m_child.end(); ++it) //replace les Widgets comme a demander l'utilisateur (annule le déplacement précédent).
                                (*it)->move(-m_virtualPos.x, -m_virtualPos.y);
                }

                else
                        clear(sf::Color(0, 0, 0, 255));
        }

void Frame::show(std::list<sf::Drawable*> &drawable)
        {
                for(std::list<sf::Drawable*>::iterator it = drawable.begin(); it != drawable.end(); ++it)
                        draw(*(*it));
                display();
                m_spriteFrame.setTexture(getTexture());
                m_spriteFrame.setPosition(sf::Vector2f(m_virtualPos.x, m_virtualPos.y));
        }

Voila je pense avoir mis tout le nécessaire :) . Merci d'avance :)

édit : si jamais vous avez besoins du code source COMPLET de la lib, regarder le sur le server git suivant (vous aidera peut être à comprendre certains points) : https://github.com/Gaulois94/GUIML . Ps : le code n'est pas expliqué. Demander moi des renseignement sibesoin (j'ajouterai des commentaires bien plus tard ;) ).
« Modifié: Mai 26, 2012, 02:06:34 pm par gaulois94 »

lezebulon

  • Full Member
  • ***
  • Messages: 235
    • Voir le profil
Re : Déplacement de "Frame" trop lente par rapport à la souris.
« Réponse #5 le: Mai 26, 2012, 04:06:25 pm »
Au lieu de faire Move() et de déplacer ta fenêtre relativement par rapport au déplacement relatif de la souris, tu peux pas appeller genre SetPosition() sur ta fenêtre, en donnat la position de la souris?

gaulois94

  • Sr. Member
  • ****
  • Messages: 259
    • Voir le profil
Re : Déplacement de "Frame" trop lente par rapport à la souris.
« Réponse #6 le: Mai 26, 2012, 04:24:30 pm »
Ah en effet, ce n'est pas idiot, je pense que je vais faire cette méthode x) (comme quoi, les réponses les plus simples sont souvent les meilleurs x) ). M'enfin ceci est à faire correctement, car l'utilisateur ne va pas cliquer forcément sur le coin en haut à droite de la Frame ;) .

En effet sa fonctionne, voici le code correspondant :

Frame::update(const sf::Drawable* drawables)
{
               if(isMoving() && getEventManager())
                        {
                                sf::Vector2i newMousePosition = getEventManager()->getMousePosition();
                                setPosition(newMousePosition.x - m_mousePos.x, newMousePosition.y - m_mousePos.y);
                        }
}
 
et voici comment est calculer m_mousePos (seulement au tout premier click du déplacement)


m_isMoving = m_buttonMoveFrame.isActived();
m_mousePos = getEventManager()->getMousePosition();
m_mousePos.x -= m_pos.x;
m_mousePos.y -= m_pos.y;


Sa fonctionne, c'est beau c'est vrai mais j’aperçois des "téléportation", comme si le nombre de FPS était bas (mais reste constant, pour le moment ;) ).

édit : sa c'est le code sans compter les resize. Avec les resizes, c'est un peu près le même mais un tout petit peu plus complexes ;) .
« Modifié: Mai 26, 2012, 06:16:13 pm par gaulois94 »