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

Author Topic: pimpl + sf::Transformable = ..?  (Read 5555 times)

0 Members and 1 Guest are viewing this topic.

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
pimpl + sf::Transformable = ..?
« on: May 18, 2014, 09:41:40 pm »
Hello! :)

For the sfeMovie project I want to hide all implementation details to make the public API both cleaner and binary compatible for later additions.

To do so I've moved the implementation of the main class (Movie) into a pimpl (MovieImpl). Then each method of Movie forward calls to the pimpl. So far so good.

The issue is that the Movie class inherits from sf::Transformable and that one of my methods can modify the transformations (namely fitFrame()) of the Movie(Impl) object.

So here I can have transformations on 2 levels:
- on a Movie object, if the user uses one of setScale() / setPosition()
- on the MovieImpl object, through the fitFrame() call forwarded to the pimpl

I cannot forward calls for setPosition / setScale because these methods are not virtual. This is most probably a good point but here I get blocked. There can be transformations on 2 levels whereas I would like one transformation to overwrite the other and vis versa (just like several calls to setPosition() would do), and I would like to avoid putting the fitFrame() logic in the Movie class instead of MovieImpl…

Or maybe my class should rather inherit from a sf::Transformable subclass that defines this fitFrame() behaviour?

So this is mostly a design question and I wonder if anyone got into this issue :)
Thanks!
Ceylo
Want to play movies in your SFML application? Check out sfeMovie!

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: pimpl + sf::Transformable = ..?
« Reply #1 on: May 18, 2014, 10:16:39 pm »
I'm not sure if I fully understand it, but what prevents you from letting MovieImpl inherit sf::Transformable and providing forwarding functions in Movie?

If the idea is to hide implementation details (i.e. SFML), your public classes should not derive from them anyway.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
Re: pimpl + sf::Transformable = ..?
« Reply #2 on: May 18, 2014, 11:07:05 pm »
Well I want the internal implementation details to be hidden but the fact that the Movie class is a drawable is part of the public API: that's how it's supposed to be used. So I guess it makes sense to let this visible.

As for inheritance… let's say I overload all the Transformable method and forward the calls to the pimpl. And the user stores a list of transformable objecs (eg. all his visible objects). He wants to move all the objects of this list, through the setPosition() method. I guess the Transformable's implementation will be called, not the Movie's one. Am I right?
Want to play movies in your SFML application? Check out sfeMovie!

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: pimpl + sf::Transformable = ..?
« Reply #3 on: May 18, 2014, 11:41:23 pm »
Well I want the internal implementation details to be hidden but the fact that the Movie class is a drawable is part of the public API: that's how it's supposed to be used. So I guess it makes sense to let this visible.
Yes, indeed. So this applies also to sf::Transformable, not only sf::Drawable? Is every single method meaningful for your case, including rotation and origin? See also LSP.

And the user stores a list of transformable objecs (eg. all his visible objects).
Well, you can't do that anymore, if your Movie class doesn't inherit the sf::Transformable base class.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
Re: pimpl + sf::Transformable = ..?
« Reply #4 on: May 19, 2014, 12:33:56 am »
So this applies also to sf::Transformable, not only sf::Drawable?
Yes indeed.

Is every single method meaningful for your case, including rotation and origin? See also LSP.
I do not know how the Movie class is used, but I find it a pity to restrain the use case just because I can't simply inherit. The main use cases involve only moving and scaling but I can't think of everything. I don't think supporting only a subset of sf::Transformable should be the way to go.

Well, you can't do that anymore, if your Movie class doesn't inherit the sf::Transformable base class.
Which exactly what annoys me ;D . I would like to be able to inherit in some way or another to keep this kind of property.

Till now creating a Transformable subclass from which Movie inherits looks to be the only clean possible solution...
Want to play movies in your SFML application? Check out sfeMovie!

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: pimpl + sf::Transformable = ..?
« Reply #5 on: May 19, 2014, 12:46:04 am »
What exactly does fitFrame() do, and why does it need to modify the publicly accessible transform?  I assume the position/scale given by the user defines the "frame" we want the movie to fit in, so it seems like it wouldn't make any sense to modify that.  If there are internal transformations going on to decode the video or something (I have no idea how videos work) then shouldn't those be private sf::Transforms, separate from the one the public setters/getters access?

tl;dr I think we need to know a bit more about the problem.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: pimpl + sf::Transformable = ..?
« Reply #6 on: May 19, 2014, 01:00:09 am »
I do not know how the Movie class is used, but I find it a pity to restrain the use case just because I can't simply inherit. The main use cases involve only moving and scaling but I can't think of everything. I don't think supporting only a subset of sf::Transformable should be the way to go.
What I meant with LSP is, does every single operation of sf::Transformable make sense for the Movie class?

By the way, have you considered splitting this class into a resource and a graphical representation, similar to sf::Texture and sf::Sprite? It may not be too useful to have multiple graphical representations because of streaming, but still I'd reflect about this approach.

Till now creating a Transformable subclass from which Movie inherits looks to be the only clean possible solution...
To be honest, 3 layers of class hierarchy to achieve something simple is far from clean to me :D

In general, I'm not a big fan of the Java style abstraction through inheritance. Your example shows one of its shortcomings. The sf::Transformable base class is not an interface (i.e. providing method signatures without implementation), it's a stateful base class with both data and implementation. That's why its methods are not virtual, they're not supposed to be overridden.

If you want to preserve sf::Transformable in your front-end Movie class as well as the possibility that the user sets attributes that directly affect the back-end MovieImpl, you won't get around querying Movie from MovieImpl whenever you need updated information. The simplest way would be passing a sf::Transformable& reference to MovieImpl.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: pimpl + sf::Transformable = ..?
« Reply #7 on: May 19, 2014, 01:11:16 am »
In particular, do any of the rotation methods of sf::Transformable make sense on an sfe::Movie?  Do you plan on supporting arbitrary video rotations? (is that even possible?)

For the record, as someone who will probably use sfe::Movie someday (whenever I have time to code again...) I would be perfectly fine with a Movie class that's Drawable but not Transformable, and instead takes an IntRect in a method like resizeToFrame().

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
Re: pimpl + sf::Transformable = ..?
« Reply #8 on: May 19, 2014, 08:07:20 pm »
What exactly does fitFrame() do, and why does it need to modify the publicly accessible transform?  I assume the position/scale given by the user defines the "frame" we want the movie to fit in, so it seems like it wouldn't make any sense to modify that.  If there are internal transformations going on to decode the video or something (I have no idea how videos work) then shouldn't those be private sf::Transforms, separate from the one the public setters/getters access?

tl;dr I think we need to know a bit more about the problem.
Given a sf::Rect (origin + size), it resizes and positions the movie so that it best fits that rect. For example, given a target rect of (0, 0, 400, 300) and a movie whose size is (200, 100), the movie will be positioned at (0, 50) with a size of (400, 200). Like in the attached image.

The user could indeed set the position / scale himself but it is not that simple because you have to take into account the aspect ratio of the movie and the aspect ratio of the target frame. So I wanted to provide an easy way for that.

Actually this is not related to decoding, only presentation :)

What I meant with LSP is, does every single operation of sf::Transformable make sense for the Movie class?
Yes they do, although not each of them is as much useful.

By the way, have you considered splitting this class into a resource and a graphical representation, similar to sf::Texture and sf::Sprite? It may not be too useful to have multiple graphical representations because of streaming, but still I'd reflect about this approach.
No, not yet. The most relevant use case would be to replace animated sprites but I don't know how much of an interest it is compared to classical animation systems with sprite sheets. Or maybe it comes of interest with high resolution + high framerate animations?

To be honest, 3 layers of class hierarchy to achieve something simple is far from clean to me :D
Yes I went a bit quick to the conclusion :) and the more I think of this solution, the more it looks like to a hidden way of doing the logic in Movie without saying it.

If you want to preserve sf::Transformable in your front-end Movie class as well as the possibility that the user sets attributes that directly affect the back-end MovieImpl, you won't get around querying Movie from MovieImpl whenever you need updated information. The simplest way would be passing a sf::Transformable& reference to MovieImpl.
This looks like a really great idea!!! I guess you've made me happy for the whole day :D

In particular, do any of the rotation methods of sf::Transformable make sense on an sfe::Movie?  Do you plan on supporting arbitrary video rotations? (is that even possible?)
Why not? What I'm seeing is that I'll need more work to get a subset of the transformations working rather than just fully supporting sf::Transformable.

For the record, as someone who will probably use sfe::Movie someday (whenever I have time to code again...) I would be perfectly fine with a Movie class that's Drawable but not Transformable, and instead takes an IntRect in a method like resizeToFrame().
Noted! :)
« Last Edit: May 19, 2014, 08:14:02 pm by Ceylo »
Want to play movies in your SFML application? Check out sfeMovie!

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
Re: pimpl + sf::Transformable = ..?
« Reply #9 on: May 25, 2014, 01:13:39 am »
In the end I gave the movie impl a sf::Transformable reference as suggested by Nexus and that worked fine :)
Just wanted to thank you all a lot!!
Want to play movies in your SFML application? Check out sfeMovie!