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

Transform.Translate does nothing

RoyAwesome opened this issue · comments

I'm using Core 3.1 Preview

The following code does nothing

Transform tf = new Transform(); tf.Translate(100, 100);

image

image

I expect the transform matrix to change when I translate it. This could be a core bug, but I'm not sure with Translate calling into native code.

For what it's worth, Scale and Rotate also do nothing. I just don't have a good test case for it.

This is going to be because the compiler is doing some defensive copies. Making the struct readonly might fix it (see this) but, even if it works, this is just a bad API design. Structs should almost always be immutable and just return the modified instance. Being readonly (including using that new modifier) will open up more optimizations than mutating the struct.

the compiler is doing some defensive copies. Making the struct readonly might fix it

Which struct are you referring to exactly?

Reading the CSFML code the point seems to be that the struct is modifiable, so readonly wouldn't really work. But the CSFML code also creates a completely new object, which seems to not properly translate back via ref struct to this assignment. 🤔

I was talking about the C# Transform struct. IMO it should be readonly and return the translated/scaled/etc instance instead. This is the recommended way to do things in C#.

commented

I can't recreate this issue... We sure this isn't because in the example the entire matrix is zero and therefore you're getting zero as the result? If you initialise with Transform.Identity for example you should see the values change.

@DangerRoss that would still be a bug because you would expect the above code to actually do something.

After testing, @DangerRoss 's workaround does not work for me. Same behavior.

commented

hmm I don't know then.

image

I've tried both .NET Core 3 and 3.1 preview with SFML from Nuget and a nonzero matrix changes for me, and a zero matrix does not. Makes me unsure if this issue is related to how the underlying API is handling Transform to CSFML even if it's not the recommended approach, as I wouldn't expect the values to change the behavior.

Ya know, I went and tested it again and it does work as you see. I wonder why I got a bad test. I probably chalk that up to me making a mistake. It does do for me exactly what DangerRoss has posted.

Ah, I didn't really think that far. Yes, a matrix of 0s should not change when you apply some transformation on it.

In C++ when you create a new instance of sf::Transform, we do actually create an identity matrix, which IMHO makes sense, as the "default" state of a matrix is its identity and not a null matrix.

@LaurentGomila should we change the constructor of the C# Transform class to return an identity matrix?

C#

var transform = new Transform();
Console.Out.WriteLine(transform.ToString());
[Transform] Matrix(0, 0, 0,0, 0, 0,0, 0, 0, )

(Potentially also clean up the ToString() implementation)

C++

auto transform = sf::Transform{};
std::cout << to_string(transform) << "\n"s; // Custom to_string function
Matrix [1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,]
commented

Keep in mind Transform is currently a struct and C# does not allow you to define a default constructor for structs :(

Ah, that explains then why it probably wasn't done so in the first place and the workaround is simple, just need to remember to use it: var transform = Transform.Identity;

I'll close this issue then for now.

Yep, it's a known limitation, and the workaround is indeed to initialize with Transform.Identity.

A comment or documentation note would be nice to prevent others from encountering this issue again :)

Would you be willing to provide a PR with such an addition?