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

Author Topic: sf::Drawable  (Read 6142 times)

0 Members and 1 Guest are viewing this topic.

Andrei15193

  • Guest
sf::Drawable
« on: September 01, 2012, 09:25:22 pm »
Hello

Is it possible in future releases of SFML that sf::Drawable instances to hold x and y coordinates?

victorlevasseur

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: sf::Drawable
« Reply #1 on: September 01, 2012, 09:42:01 pm »
Hello,

Just inherit your object of sf::Drawable and sf::Tranformable :
http://www.sfml-dev.org/documentation/2.0/classsf_1_1Transformable.php

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10883
    • View Profile
    • development blog
    • Email
Re: sf::Drawable
« Reply #2 on: September 01, 2012, 09:50:42 pm »
Is it possible in future releases of SFML that sf::Drawable instances to hold x and y coordinates?
No, because as victorlevasseur has pointed out SFML has two diffrent classes for diffrent abstractions.
The sf::Transformable is just a class to handle position and size as well as 2D transformations on it, where as the sf::Drawable only serves as base class to make the drawing process more generic and give the ability to the programmer to create drawable objects themself without having to depend on anything else. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Andrei15193

  • Guest
Re: sf::Drawable
« Reply #3 on: September 01, 2012, 10:43:31 pm »
Hey,

Well the problem is that I need polymorphism. I have an array of sf::Drawables (sf::Text and sf::Sprite) and I'm trying to implement model/view so when the x of my model/view changes I would like all sf::Drawables to change their positions. The code below illustrates better what I'm trying to say:

#include <list>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>

class View{
private:
    // The views coordinates
    int _x, _y;
    // A list of drawable stuff
    std::list<const sf::Drawable*> _drawables;

protected:
    // Adds a drawable instance to the list
    // Pre:
    //      The instance given must exist at least as long as the
    //      current instance exists.
    // Post:
    //      The container of drawables now holds a reference to the given
    //      sf::Drawable instnace. Any changes to it will be reflected
    //      in the list since it refers to the same object.
    void _addDrawable(const sf::Drawable& drawable){
        _drawables.push_back(&drawable);
    }

    // Clears the list of drawables.
    // Post:
    //      The container of references to drawable instances is cleared.
    void _clearDrawables(){
        _drawables.clear();
    }

public:
    View(): _x(0), _y(0), _drawables(std::list<const sf::Drawable*>()){
    }

    View(int x, int y): _x(x), _y(y), _drawables(std::list<const sf::Drawable*>()){
    }

    View(const View& view): _x(view._x), _y(view._y), _drawables(std::list<const sf::Drawable*>()){
    }

    virtual ~View(){
    }

    virtual void update() = 0;

    virtual const View& operator =(const View& view) throw(std::bad_cast){
        const View& converted = dynamic_cast<const View&>(view);
        _x = view._x;
        _y = view._y;
        return *this;
    }

    int getX() const {return _x;}

    void setX(int x){
        /* Here is what I want:
        for (auto it = _drawables.begin(), end = _drawables.end(); it != end; it++){
            const sf::Vector2f& position = (*it)->getPosition();
            (*it)->setPosition(x + position.x - _x, position.y);
        }
        */

        _x = x;
    }

    int getY() const {return _y;}

    void setY(int y){
        /* Same for y
        for (auto it = _drawables.begin(), end = _drawables.end(); it != end; it++){
            const sf::Vector2f& position = (*it)->getPosition();
            (*it)->setPosition(position.x, y + position.y - _y);
        }
        */

        _y = y;
    }

    const std::list<const sf::Drawable*>& getDrawables() const {return _drawables;}
};

class MyView : public View{
private:
    sf::Font _myFont;
    sf::Text* _myDrawable;

    void _addDrawables(){
        _addDrawable(*_myDrawable);
    }

public:
    MyView() throw(std::exception): _myFont(sf::Font()), _myDrawable(nullptr){
        if (!_myFont.loadFromFile("font.ttf"))
            throw std::exception("Could not load font");
        _myDrawable = new sf::Text("MyText", _myFont);
        _addDrawables();
    }

    MyView(const MyView& myView): _myFont(myView._myFont), _myDrawable(nullptr){
        _myDrawable = new sf::Text(myView._myDrawable->getString(), _myFont);
        _addDrawables();
    }

    virtual ~MyView(){
        delete _myDrawable;
    }

    virtual void update(){
        _myDrawable->setString("Updated");
    }

    virtual const MyView& operator =(const MyView& myView) throw(std::bad_cast){
        const MyView& converted = dynamic_cast<const MyView&>(myView);
        View::operator =(converted);
        *_myDrawable = *converted._myDrawable;
        _myDrawable->setFont(_myFont);
        return *this;
    }
};

int main(){
    try{
        MyView myView;
        sf::RenderWindow window(sf::VideoMode(200, 200), "Drawables");
        sf::Event event;

        do{
            window.clear();
            const std::list<const sf::Drawable*>& drawables = myView.getDrawables();
            for (auto it = drawables.begin(), end = drawables.end(); it != end; it++)
                window.draw(**it);
            window.display();

            if (window.pollEvent(event))
                if (event.type == sf::Event::Closed)
                    window.close();
                else
                    if (event.type == sf::Event::KeyPressed)
                        myView.update();
        }while(window.isOpen());
        return EXIT_SUCCESS;
    }
    catch(...){
        return EXIT_FAILURE;
    }
}
 

sf::Transformable does not inherit sf::Drawable to be able to use it in this case. Can there be at least an intermediate class between sf::Drawable and sf::Text, sf::Sprite, sf::Shape? Let's say:

class Drawable2D : public Drawable, public Transformable{
};
 

And all classes that inherit Drawable and Transformable to derive from Drawable2D? If not I will need to use 2 containers, one of references to Drawables and one of references to Transformables.

victorlevasseur

  • Full Member
  • ***
  • Posts: 206
    • View Profile
Re: sf::Drawable
« Reply #4 on: September 01, 2012, 10:48:47 pm »
Maybe you can try to do a cast from sf::Drawable* to sf::Transformable* . I'm not sure of the result, but you can try.

Andrei15193

  • Guest
Re: sf::Drawable
« Reply #5 on: September 01, 2012, 10:54:14 pm »
That may work as long as my sf::Drawable is not a sf::VertexArray instance since the first is abstract.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10883
    • View Profile
    • development blog
    • Email
Re: sf::Drawable
« Reply #6 on: September 01, 2012, 10:57:34 pm »
Maybe you can try to do a cast from sf::Drawable* to sf::Transformable* . I'm not sure of the result, but you can try.
Don't do that under any circumstances... There's no guarantee that the sf::Drawable class that is held by your vector/list/etc. also derives from sf::Transformable. Additionally you'd need something like reintepret_cast which should always be avoided. ;)

I'm not quite sure what you want to do and I don't have to motivation to read & trying to understand your code... If your design doesn't work with SFML, then your design is probably not that good or needs to be adjusted.
On the other hand if you want to stick to your design, you can easily go and create your own modified version of SFML.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: sf::Drawable
« Reply #7 on: September 01, 2012, 11:03:35 pm »
Just wanting to point out that 1.6 did it this way (and it discouraged from inheriting drawable if you don't need transforms) so it's more like downgrade request.  ;) Not a snowball's chance in hell..
Back to C++ gamedev with SFML in May 2023

Andrei15193

  • Guest
Re: sf::Drawable
« Reply #8 on: September 01, 2012, 11:41:02 pm »
Hehe I know I wrote a lil bit to much code.

I can make my design work with SFML, that's not a problem. It's just that some subclasses of sf::Drawable have locations and I wanted a superclass for all those classes that's still a subclass of sf::Drawable to be able to use it as a valid argument to sf::Window::Draw(). But if it's a downgrade, okay.

I wrote a function that tests the inheritance of any two classes if anyone needs it:
template <class Derived1, class Derived2, class Type>
bool testDoubleInheritance(const Type& instance){
    return dynamic_cast<const Derived1*>(&instance) != nullptr && dynamic_cast<const Derived2*>(&instance) != nullptr;
}

// Usage:
int main(){
    if (testDoubleInheritance<A, B>(AandB()))
        // AandB is a subclass of A and B
    return 0;
}
 

I won't need 2 lists to fix the problem now, just conversions.