SFML / SFML.Net

Official binding of SFML for .Net languages

Home Page:https://www.sfml-dev.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Request for changing Shape.Draw() to call RenderTarget.Draw(vertice, ...) instead of directly call to the binding sfRenderWindow_drawShape()

nthana opened this issue · comments

At SFML.Net, Shape.cs :: Draw() method:

        public void Draw(RenderTarget target, RenderStates states)
        {
            states.Transform *= Transform;
            RenderStates.MarshalData marshaledStates = states.Marshal();

            if (target is RenderWindow)
            {
                sfRenderWindow_drawShape(( (RenderWindow)target ).CPointer, CPointer, ref marshaledStates);
            }
            else if (target is RenderTexture)
            {
                sfRenderTexture_drawShape(( (RenderTexture)target ).CPointer, CPointer, ref marshaledStates);
            }
        }

This method works on precisely two subtypes of RenderTarget, e.g. RenderWindow and RenderTexture. This prevent polymorphic use of the RenderTarget (whenever the RenderTarget argument happens to be other subtypes, this code may fail.).

The reason that I request this, specifically, is that I have planned to create a SpriteBatch class (In C#) as a subclass of RenderTarget. This batch object needs every draw calls to delegate into it, so that it can accumulate vertices and batch them. However, Shape.Draw(), as shown, prevents this accumulation.

Thank you for any responses in advance. :)

The implementation can't directly be changed, because the type specific drawShape or drawText or drawSprite functions actually call sf::Shape::draw() which can have a different implementation than simply gathering the vertex data and rendering it.

For example:

https://github.com/SFML/SFML/blob/e39f48742b702400424db46f3b28e8a09459ca38/src/SFML/Graphics/Shape.cpp#L212-L226

I don't think there's currently a way to create a "SpriteBatcher" that hooks in at the RenderTarget level in C#, because the "final" draw call onto the RenderTarget happens in C++ land and doesn't get called back up the stack into C#. So from the example the target.draw(m_vertices, states); will never hit your RenderTarget implementation, which is where you'd want to be to properly write a batcher.

RenderTarget SFML Net

Thank you so much for the response. I'm trying to digest the information. :)

After some thought and code inspections, I understand your points. Currently, SFML.Net doesn't have ways to access some C++ variables that Shape::draw() used, e.g. m_vertices and m_outlineVertices. So, (1) it will be hard to duplicate the logic from the method Shape::draw() in C++ into Shape.Draw() in C#. (2) it may not be efficient because of the number of small binding calls needed. And (3) it will create logic duplications that the code maintainers may not want.

So, in C# we cannot design a "SpriteBatcher" by subclassing the RenderTarget and expecting it to hook Draw() calls from Shape or Drawable objects. (This design of "SpriteBatcher" could be done in C++ SFML.)

For this request, I think it will take too much effort to do than I originally thought. So, I think you can close it for now. Thank you for your time. :)

Anyway, I like coding in C# and I like the class/responsibility design of SFML.

In the future, such as on SFML 3.0, could you consider the possibility to implement this request ? I volunteer to help what I could do in C#.

After some thought and code inspections, I understand your points. Currently, SFML.Net doesn't have ways to access some C++ variables that Shape::draw() used, e.g. m_vertices and m_outlineVertices.

The issue isn't really the access to certain properties, because we'll never duplicate the logic from SFML to SFML.Net. CSFML and SFML.Net will always remain "just" an interface on top - though I'm open for more C# native structures in SFML.Net 3.

In the future, such as on SFML 3.0, could you consider the possibility to implement this request ? I volunteer to help what I could do in C#.

We'd have to restructure the drawing within SFML.Net, by for example centralizing everything in a concrete implementation of RenderTarget, which you can override or similar.

I can't make any promises for SFML.Net 3. Usually, the community has a large say in what direction we'll be going. So if people are willing and invest the time (it needs quite some time over a longer period), we can certainly come up with something that's more flexible.

Closing this for now, as I currently don't see a way to approach this.

For a batcher, you'll most likely have to write something custom and it won't automatically support all the drawable.