On a second thought, there is a simpler way: make the native implementation of a Drawable's draw method simply use the standard SFML mechanism. :)
However, trying to do this leads me to another problem:
The "RenderTarget" is passed to the Drawable's draw method as the first parameter. Now, RenderTarget is an abstract class / interface. In the Java object, I store the pointer to the native SFML object as a long integer value and I statically cast it back to a given pointer type like so:
jlong ptr = (...) //fetch from Java object
(sf::RenderWindow*)ptr
(where jlong is a typedef to a signed 64-bit integer)
The problem: I can not use this to cast the pointer to an abstract type like sf::RenderTarget, because the vtable pointer will still point to the vtable of the implementing class, in this case either sf::RenderTexture or sf::RenderWindow. Dynamic casting is not possible, because at compile time I do not have any type information except for the long int. I also do not know of any way to store type information in C++.
The only thing I can imagine that could work is, for abstract types, to define another pointer to be stored in the Java object that points to the same object cast up to the abstract type, and provide another method to retrieve that pointer. This would be possible in the object's construction chain, although it's certainly not pretty.
Done!
A simple example of what's possible now is the following, a text with a shadow:
public class ShadowText
extends Text
{ private Color shadowColor
= new Color(Color.
BLACK,
128); private Vector2f shadowOffset
= new Vector2f
(3,
3); public ShadowText
() { } public ShadowText
(@NotNull
String string, @NotNull
Font font
) { super(string, font
); } public ShadowText
(@NotNull
String string, @NotNull
Font font,
int characterSize
) { super(string, font, characterSize
); } public void setShadowAlpha
(int alpha
) { this.
shadowColor.
setAlpha(alpha
); } public void setShadowOffset
(Vector2f shadowOffset
) { this.
shadowOffset = shadowOffset
; } @Override
public void draw
(@NotNull RenderTarget target, @NotNull RenderStates states
) { Color color
= getColor
(); Vector2f pos
= getPosition
(); //Shadow setPosition
(pos.
x + shadowOffset.
x, pos.
y + shadowOffset.
y); setColor
(shadowColor
); super.
draw(target, states
); //Text setPosition
(pos
); setColor
(color
); super.
draw(target, states
); }}