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

Author Topic: Crash when calling getView in a function. (called by another function)  (Read 2452 times)

0 Members and 1 Guest are viewing this topic.

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Hi!
I've a function which move the view, a class which contains the window (the base application class), and a a pointer to function wich call the function to move the view like this :

MyAppli(sf::RenderWindow &window) : Application (window) {
        running = false;
        actualKey = sf::Keyboard::Unknown;
        previousKey = sf::Keyboard::Unknown;
    }
    void close () {
        getWindow().close();

    }
    void keyHeldDown (sf::Keyboard::Key key, sf::Time elapsedTime) {
        sf::View view = getWindow().getView();
       ...
    }
     
 

In the event loop I do something like this :

sf::Event event;
        if (getWindow().pollEvent(event))
        {
            listener.pushEvent(event);
            if (event.type == sf::Event::Closed) {

                running =false;
            }
            if (event.type == sf::Event::KeyPressed) {
                previousKey = actualKey;
                actualKey = event.key.code;
                listener.setActionParams("MoveAction", this, event.key.code,realTime.restart());

            }
            if (event.type == sf::Event::KeyReleased) {
                caracter->setMoving(false);
                previousKey = event.key.code;
                actualKey = sf::Keyboard::Key::Unknown;
            }
            if (event.type == sf::Event::MouseMoved) {
                Vector2f mousePos = Vector2f(event.mouseMove.x, event.mouseMove.y);
                listener.setParams("MouseInside", this, this, mousePos, 0);

            }
        }
    }
 
When I want to retrive the view the debugger indicate me that the view is null, but for all other variables than the view it works. (When I comment this line : sf::View = getWindow().getView())
Code: [Select]


Here it's what the debugger says :
#0 0044775A MyAppli::keyHeldDown(this=<optimized out>, key=<optimized out>, elapsedTime=...) (D:/Projets/Projets-c++/TestSFGL/myApplication.h:51)
#1 004476CE operator() (args#1=..., args#0=sf::Keyboard::A, object=0x0, this=0x980fdc0) (C:/ODFAEG/include/ODFAEG/Core/function.h:73)
#2 ?? odfaeg::callback<void, MyAppli<sf::Keyboard::Key, sf::Time> > (func=..., object=0x0) (C:/ODFAEG/include/ODFAEG/Core/signal.h:9)
#3 00441E04 callFunc<0, 1, 2>(params=<error reading variable: access outside bounds of object referenced via synthetic pointer>, this=0x490b048) (C:/ODFAEG/include/ODFAEG/Core/function.h:49)
#4 ?? operator()<> (params=..., this=0x490b048) (C:/ODFAEG/include/ODFAEG/Core/function.h:44)
#5 ?? odfaeg::FastDelegate2<MyAppli<sf::Keyboard::Key, sf::Time> >::operator() (this=<optimized out>) (C:/ODFAEG/include/ODFAEG/Core/signal.h:93)
#6 0044699C operator() (this=<optimized out>) (C:/ODFAEG/include/ODFAEG/Core/signal.h:247)
#7 ?? operator() (this=<optimized out>) (C:/ODFAEG/include/ODFAEG/Core/actionMap.h:107)
#8 ?? odfaeg::Listener::run (this=<optimized out>) (C:/ODFAEG/include/ODFAEG/Core/system.h:157)
#9 0041E7F0 execute_native_thread_routine () (??:??)
#10 ?? ?? () (??:??)

Maybe I know where the problem come from, the prototype from the method getView is : const View & getView();

Why returning a const reference ?

A simple reference should be better I thing for modifying the view without having to call the setview() function.
« Last Edit: February 19, 2014, 10:54:12 pm by Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Crash when calling getView in a function. (called by another function)
« Reply #1 on: February 19, 2014, 11:37:15 pm »
I don't see how your second piece of code relates to the first one, and what your call stack is supposed to show. Where is the view in all this stuff?

Quote
A simple reference should be better I thing for modifying the view without having to call the setview() function.
I don't want that. I want the user to call setView to modify the view, so that I can track any modification to the current view. There's no reference to an internal view, views are handled by copy (they are lightweight objects).

As usual: complete and minimal code please. You should really make sure that the problem is not in your mess of FastDelegate before posting, nobody wants to deal with it.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Crash when calling getView in a function. (called by another function)
« Reply #2 on: February 20, 2014, 02:58:37 pm »
Ok here is a code whithout the fast delegate.

It doesn't crash but the view doesn't move :

#include "ODFAEG/Core/animationUpdater.h"
#include "caracter.h"
using namespace odfaeg;
using namespace sf;

class MyAppli : public Application {
    private :
    const int speed = 50;
    Map* theMap;
    Clock realTime;
    bool running;
     Wall *w;
    Caracter* caracter;
    sf::Keyboard::Key actualKey, previousKey;
    enum TEXTURES {
        GRASS, WALLS, HOUSE, FIRE1, FIRE2, FIRE3
    };

    public :
    MyAppli(sf::RenderWindow &window) : Application (window) {
        running = false;
        actualKey = sf::Keyboard::Unknown;
        previousKey = sf::Keyboard::Unknown;
    }
    void close () {
        getWindow().close();

    }
    void keyHeldDown (sf::Keyboard::Key key, sf::Time elapsedTime) {
        std::cout<<"key pressed : "<<key<<" elapsed time : "<<elapsedTime.asSeconds()<<std::endl;
        sf::View view = getWindow().getView();
        float t = speed * elapsedTime.asSeconds();
        if (actualKey != sf::Keyboard::Key::Unknown && key == sf::Keyboard::Key::Z) {
            view.move (0, -t);
            if (!caracter->isMoving()) {
                if (actualKey != previousKey) {
                    Vec2f dir(0, -1);
                    caracter->setDir(dir);
                }
                caracter->setMoving(true);
            }
            theMap->moveEntity(caracter, caracter->getDir().x * t, caracter->getDir().y * t);
        } else if (actualKey != sf::Keyboard::Key::Unknown && key == sf::Keyboard::Key::Q) {
            view.move (-t, 0);
            if (!caracter->isMoving()) {
                if (actualKey != previousKey) {
                    Vec2f dir(-1, 0);
                    caracter->setDir(dir);
                }
                caracter->setMoving(true);
            }
            theMap->moveEntity(caracter, caracter->getDir().x * t, caracter->getDir().y * t);
        } else if (actualKey != sf::Keyboard::Key::Unknown && key == sf::Keyboard::Key::S) {
            view.move (0, t);
            if (!caracter->isMoving()) {
                if (actualKey != previousKey) {
                    Vec2f dir(0, 1);
                    caracter->setDir(dir);
                }
                caracter->setMoving(true);
            }
            theMap->moveEntity(caracter, caracter->getDir().x * t, caracter->getDir().y * t);
        } else if (actualKey != sf::Keyboard::Key::Unknown && key == sf::Keyboard::Key::D) {
            view.move (t, 0);
            if (!caracter->isMoving()) {
                if (actualKey != previousKey) {
                    Vec2f dir(1, 0);
                    caracter->setDir(dir);
                }
                caracter->setMoving(true);
            }
            theMap->moveEntity(caracter, caracter->getDir().x * t, caracter->getDir().y * t);
        }

        getWindow().setView(view);
}
/*The next methods are render, init and load but they don't move the view so you don't need to see the source code here, they just draw the world and laod textures.*/
 void update () {
        // check all the window's events that were triggered since the last iteration of the execution's loop

        sf::Event event;
        while (getWindow().pollEvent(event))
        {
           
            if (event.type == sf::Event::Closed) {

                running =false;
            }
            if (event.type == sf::Event::KeyPressed) {
                previousKey = actualKey;
                actualKey = event.key.code;
                keyHeldDown(event.key.code, realTime.restart());              

            }
            if (event.type == sf::Event::KeyReleased) {
                caracter->setMoving(false);
                previousKey = event.key.code;
                actualKey = sf::Keyboard::Key::Unknown;
            }        
        }
    }
    void stop() {
        running = false;
    }
    int exec () {
        load();
        init();
        running = true;
        while (running) {
            render();
            update();
        }
        return EXIT_SUCCESS;
    }

    ~MyAppli () {

    }
 
       
And here is the main :

#include "myApplication.h"
using namespace sf;
int main(void)
{
    sf::RenderWindow window (sf::VideoMode(800, 600), "ODFAEG Demo");
        MyAppli app(window);
        return app.exec();
}
 
   
« Last Edit: February 20, 2014, 03:03:26 pm by Lolilolight »

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Crash when calling getView in a function. (called by another function)
« Reply #3 on: February 20, 2014, 04:47:17 pm »
Ok, I've found why, the value for the speed wasn't big anough, but it recrash in the delegate :

But I've a question can I set a pointer member function to null and doing something like this ???


template <typename R, typename O, typename ...A> class MemberFunction <R(O*, A...)> {
    public :

    MemberFunction (R(O::*f)(A...)) : function(f) {
        constFunction = nullptr;
    }
    MemberFunction (R(O::*f)(A...) const) : constFunction(f) {
        function = nullptr;
    }
    R operator() (O* object, A... args) {
        if (function != nullptr)
            return (object->*function)(args...);
        else
            return (object->*constFunction)(args...);
    }

    bool operator== (const MemberFunction<R(O*,  A...)>& other) {
        return function == other.function || constFunction == other.constFunction;
    }
    private :
    R(O::*function)(A...);
    R(O::*constFunction)(A...) const;
};

 


It tells me that the object onwich I call the member function pointer is null.

Or I've past it as a parameter...

listener.setActionParams("MoveAction", this, event.key.code,realTime.restart());
 

(Otherwise this code'll not compile anyway)

But I pass the parameters in different locations (the class listener pass it to the class action map, the class actionmap pass it to the generic delegate class, the generic delegate class try to do a cast from it's generic delegate object to a specific delegate object, if the cast is succesfull it means that it's on that function pointer which we want to change the params so it pass the params to the specific delegate object, then the specific delegate object store the params into a tuple.

When we call the action map's delegate, the delegate call the function of it's delegate using the polymorpism. (The function of the specific delegates is so called and pass the function's argument to the funtor which calls the right callback function. (The callback function take a pointer to a function member and it's argument and call the pointer to the function)

There are one callback function for each kind of function type. (member function, normal/static function, lambda function, etc...)

It worked well until I wanted to store two members function pointers into the same class because I've already a lot of classes and I didn't want to use one more class for const member functions.
« Last Edit: February 20, 2014, 04:50:23 pm by Lolilolight »

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
I've found why it crashes sorry.

I had to call pushEvent after that I change the params, because otherwise, if the event is triggered, it call the function with an empty list of parameters.

sf::Event event;
        if (getWindow().pollEvent(event))
        {

            if (event.type == sf::Event::Closed) {

                running =false;
            }
            if (event.type == sf::Event::KeyPressed) {
                previousKey = actualKey;
                actualKey = event.key.code;
                listener.setActionParams("MoveAction", this, event.key.code,realTime.restart());

            }
            if (event.type == sf::Event::KeyReleased) {
                caracter->setMoving(false);
                previousKey = event.key.code;
                actualKey = sf::Keyboard::Key::Unknown;
            }
            if (event.type == sf::Event::MouseMoved) {
                Vector2f mousePos = Vector2f(event.mouseMove.x, event.mouseMove.y);
                //listener.setParams("MouseInside", this, this, mousePos, 0);

            }
            listener.pushEvent(event);
        }
 

RESOLVED.

Ok now I have just to create a class button and an inteface ActionListener. :D

But before that I've to do some changement in my action map class (a second constructor whiwh takes an action, a signal and a slot!)

So when the one or more sf::event if the action is triggered and when the  the signal function returns true (so when the left mouse button is clicked and the mouse is in the button rect), it'll call the actionPerformed function of the slot.

It'll simply rocks.  :D

The framework'll provide to way to manage events (the first way by a interface from which the parent class of the component can inherits from, and the second way by connecting signals and slots.
« Last Edit: February 20, 2014, 05:33:11 pm by Lolilolight »