schveiguy / raylib-d

Resurrected copy of onroundit's raylib-d
zlib License
56 stars 14 forks source link

Object wrappers for Raylib structs #51

Open LiamM32 opened 5 months ago

LiamM32 commented 5 months ago

This is just an idea, borrowed from Raylib-CPP, to turn some Raylib structs into classes.

I don't think all of them should be. Vector2, Vector3, and Rectangle should certainly remain as structs. But Texture is an example of one that may be better as a class.

Of course, this would be a breaking change if we retain the old names. Perhaps the class for Texture can be called "ManagedTexture" (since Raylib-CPP calls the base Texture struct from Raylib "TextureUnmanaged").

LiamM32 commented 5 months ago

I know that you (schveiguy) wrote elsewhere that you're "not looking for a raylib-cpp style API reimagining" (not that that's really what this proposal is) but I think it's worth sharing how I successfully created such a class in my own project.

I think it makes sense for anything tied to GPU memory to be an object, so that whenever it's no longer in use, the garbage collector can pick it up and the GPU memory can be freed from the object's destructor.

Here is the class I made for OE-2D as a wrapper to the Texture2D struct. It was surprisingly fast to get my game working using this instead of Texture2D directly. Here is the definition I have, with some specific things removed:

class Sprite
{
    Texture2D texture;
    alias this = texture;
    string path;

    alias GLId = texture.id;

    this(string path) {
        texture = LoadTexture(path.toStringz);
        this.path = path;
    }

    this(Image image, string path = "") {
        texture = LoadTextureFromImage(image);
        this.path = path;
    }

    Texture opCast(Texture)() {
        return this.texture;
    }

    ~this() {
        if (IsWindowReady) UnloadTexture(texture);
    }
}

That being said, there is a reason for not including something like this in Raylib-D, which is that the implementation may depend too much on how the game loads textures.

For example, the definition above would make most sense if all textures are loaded at the same time, such as the beginning of a game level, and there isn't any index held continuously (Sprite[string] spritesByPath;), as that would prevent the collection of such objects by the garbage collector, even when not needed. It's for this reason that I may make this class in my game reference counted.

So my feeling at the moment is that adding such a thing to Raylib-D would make sense if we have come up with an implementation that's suited to a reasonably broad range of use cases, without having to give complicated usage instructions, but right now I'm not entirely confident that there is one.

schveiguy commented 5 months ago

I'm leaning towards saying this is outside the scope of raylib-d. That doesn't mean there is not a place for such things in the ecosystem. I just think this might be too high-level for the goals of this library.

To elaborate, I have written many different such objects for my various projects. Making the API elegant, and covering all the possible use cases, is really difficult. I don't want to say "this is the one true way for using object systems with raylib-d", when it could be wrong, or not fit into everyone's design. This would mean you may have to use raylib-d just for the raylib binding, but ignore the other stuff.

simple things, UFCS functions, operator overloads, dealing with strings vs. C char pointers, these are all fair game.