SFML community forums

General => General discussions => Topic started by: Laurent on January 13, 2012, 02:33:10 pm

Title: The new time API
Post by: Laurent on January 13, 2012, 02:33:10 pm
Hi

Many users complained after I switched to milliseconds for time
http://www.sfml-dev.org/forum/viewtopic.php?t=4864
... this thread clearly shows that people need different resolutions and different types for representing time values.

I could of course provide the most precise (Uint64 nanoseconds) but that would not be simple --  user code would be pretty ugly.

So here is a proposal for a new time API, that is a little more verbose than before but should make everyone happy.

Code: [Select]
class Time
{
public:

    Time();
    float ToSeconds() const;
    Int32 ToMilliseconds() const;
    Int64 ToMicroseconds() const;

private:

    Int64 myMicroseconds;
};

Time Seconds(float amount);
Time Milliseconds(Int32 amount);
Time Microseconds(Int64 amount);

class Clock
{
public:

    Time GetElapsedTime() const;
    ...
}

void Sleep(Time duration);
// same in all functions that require/return a time value

User code:
Code: [Select]
sf::Clock clock;

sf::Time elapsed = clock.GetElapsedTime();
game.Update(elapsed.ToSeconds());

sf::Sleep(sf::Milliseconds(100));

sf::Time would be a time span, not a time point, so negative values would be allowed (hence the signed integers). It would have comparison and mathematical operators.
It could also support implicit conversions to/from std::chrono classes in the future.
Title: The new time API
Post by: Mario on January 13, 2012, 03:36:28 pm
Sounds good, although I'd tend to return a const reference to a Time member inside Clock (not sure about Time's structure).

What are the function calls after the class definition for? I'm a bit confused there.
Title: The new time API
Post by: Klaim on January 13, 2012, 03:38:48 pm
It would be fine, as far as the internal data is integer type to keep the precision.
Title: The new time API
Post by: Laurent on January 13, 2012, 04:16:22 pm
Quote
Sounds good, although I'd tend to return a const reference to a Time member inside Clock (not sure about Time's structure).

A time is an integer value, nothing more. But let's focus on the API please, not the details ;)

Quote
What are the function calls after the class definition for? I'm a bit confused there.

They construct time values. sf::Time has no constructor other than the default one, one must use one of these three functions.

Quote
It would be fine, as far as the internal data is integer type to keep the precision.

Internally it is of course a Int64 number of microseconds.
Title: The new time API
Post by: Ceylo on January 13, 2012, 04:24:35 pm
Looks fine to me :)
Title: Re: The new time API
Post by: Silvah on January 13, 2012, 06:29:15 pm
Quote from: "Laurent"
So here is a proposal for a new time API, that is a little more verbose than before but should make everyone happy.
It's almost certain that some people will not like it. You know, "omfg what u done its not simple anymore" ;)

As my opinion goes, it's okay.
Title: The new time API
Post by: Tex Killer on January 13, 2012, 07:57:06 pm
Yeah, I knew this would come. Totally endorsed.
Title: The new time API
Post by: Groogy on January 14, 2012, 12:43:04 am
This is very similar to how I implemented time in rimfrost engine. But we also have hierarchy timers. Though think that is over kill here.

Anyway you have my thumbs upp.
Title: The new time API
Post by: c0ffee on January 14, 2012, 01:08:06 am
Quote
"omfg what u done its not simple anymore"
Title: The new time API
Post by: julen26 on January 14, 2012, 02:24:30 am
It seems nice for me.
This way SFML still keeps satisfaying all of its users  :D
Title: The new time API
Post by: hayer on January 14, 2012, 02:32:33 am
I don't see any pause? :- (

And a interval with a callback like C# timers would be nice, but I guess I could just convert my old class.
Title: The new time API
Post by: eXpl0it3r on January 14, 2012, 02:42:47 am
Quote
Internally it is of course a Int64 number of microseconds.


Okay does that really remove the issue?

I mean you handle time still as Int64 which has the problem that you get 0 for all the function calls in between 0 and 1ms.
Which means that if I had a game loop that executes faster than 1ms I still would have to deal with the problem of 0.
Example: If I add every iteration the float of the passed time I'll constantly add 0+0+0+0+0, maybe occasionally get an 0.000001 in there but looking at my variable it would seem as if time has stopped.

Sure it can be fixed with always forcing to add a least 0.000001 and then sync it from time to time with the exact int and who ever needs performance below 1ms?

Just saying it doesn't fix all the issues...
Title: The new time API
Post by: Walker on January 14, 2012, 03:18:34 am
Looks good to me.

Quote from: "eXpl0it3r"
Quote
Internally it is of course a Int64 number of microseconds.


Okay does that really remove the issue?

I mean you handle time still as Int64 which has the problem that you get 0 for all the function calls in between 0 and 1ms.
Which means that if I had a game loop that executes faster than 1ms I still would have to deal with the problem of 0.
Example: If I add every iteration the float of the passed time I'll constantly add 0+0+0+0+0, maybe occasionally get an 0.000001 in there but looking at my variable it would seem as if time has stopped.

Sure it can be fixed with always forcing to add a least 0.000001 and then sync it from time to time with the exact int and who ever needs performance below 1ms?

Just saying it doesn't fix all the issues...


Looks like he would be storing microseconds in that int64, not milliseconds.
Title: The new time API
Post by: Tank on January 14, 2012, 09:53:02 am
Seems to be a good solution. And whoever thinks it's not simple anymore... wtf? ;-)
Title: The new time API
Post by: Hiura on January 14, 2012, 11:21:40 am
Quote from: "hayer"
I don't see any pause? :- (
Pause() in the Time class ? I wouldn't make any sense. As Laurent said :

Quote
sf::Time would be a time span


BTW : looks good!
Title: The new time API
Post by: Nexus on January 14, 2012, 11:30:35 am
The new time API looks nice :)

Quote from: "Hiura"
Pause() in the Time class ? I wouldn't make any sense.
He probably meant Pause() in the sf::Clock class. But then Laurent would put me out of work :P
Title: The new time API
Post by: Mario on January 14, 2012, 08:18:21 pm
Quote from: "Laurent"
Quote
What are the function calls after the class definition for? I'm a bit confused there.

They construct time values. sf::Time has no constructor other than the default one, one must use one of these three functions.


Are they meant to be classless or is that just in that "mockup"? I'd prefer seeing them as static members in Time with "From" as prefix (similar to "To...").
Title: The new time API
Post by: Laurent on January 14, 2012, 08:29:02 pm
Quote
Are they meant to be classless or is that just in that "mockup"? I'd prefer seeing them as static members in Time with "From" as prefix (similar to "To...").

The example is pretty explicit about their usage: they are free functions, yes.
Your solution would be definitely too verbose. And having similar functions but some as static and others as non-static, could be confusing.

Quote
I don't see any pause? :- (

sf::Clock is just provided for convenience, since the most common use case for time handling is measuring the elapsed time. It's not meant to provide fancy features. I could even remove this class and replace it with a sf::Time::Now() function -- but that would be slightly less "simple" ;)
Title: The new time API
Post by: Mario on January 14, 2012, 08:33:15 pm
Hm... I consider that pretty much standard and widely used (esp. in the .net and probably java world). It would be just a bit more sorted (having them not just sitting in the namespace).

Edit: Something like this would still look odd to me:
Code: [Select]
sf::Time &lastUse = sf::Second(someUnixTimeStampInt);
While this looks more obvious?
Code: [Select]
sf::Time &lastUse = sf::Time::FromSeconds(someUnixTimeStampInt);
Title: The new time API
Post by: Laurent on January 14, 2012, 08:36:08 pm
Quote
Hm... I consider that pretty much standard and widely used (esp. in the .net and probably java world)

These languages don't support non-member functions... So it's not "standard and widely used", it's just the only solution ;)

Quote
It would be just a bit more sorted

It's in the same header and doc page as sf::Time. How could it be more sorted? ;)
Title: The new time API
Post by: mateandmetal on January 14, 2012, 09:50:30 pm
new time api looks nice to me  :)
Title: The new time API
Post by: Klaim on January 14, 2012, 10:11:15 pm
About the pause() function : this is a real-time-passed clock system, not a virtual-time. That is good because now you can implement a virtual-time clock system specific to your game that would rely on the real-time clock.

I've done it before, it's easy to get right and you can even implement getting back in time if needed.
Title: The new time API
Post by: model76 on January 14, 2012, 10:18:33 pm
Looks very nice, Laurent.

I would drop the "To" though, as it indicates a conversion, which may not always be the case. Besides, for simplicity, the user shouldn't have to care about such details.
Title: The new time API
Post by: Groogy on January 14, 2012, 10:58:24 pm
Quote from: "model76"
Looks very nice, Laurent.

I would drop the "To" though, as it indicates a conversion, which may not always be the case. Besides, for simplicity, the user shouldn't have to care about such details.


Agreed, "As" would be a better convention I think because it instead implies that you view something in another way instead of converting to. Though I guess that's my preference. You could do it without having a prefix as well.

Code: [Select]

Time time = /* Foobar */
time.AsSeconds();
time.AsMilliSeconds();
time.AsMicroSeconds();


It gives a cleaner readability too I think because it's more natural. You don't say "Time to seconds" you say "Time as seconds"
Title: The new time API
Post by: Laurent on January 14, 2012, 11:16:51 pm
Hmm, "As" sounds good yes.

I won't drop the prefix, because it makes it clear that the function returns the whole time value, not the seconds/milliseconds/microseconds part of it.
Title: The new time API
Post by: Nexus on January 15, 2012, 12:16:14 am
Quote from: "Mario"
Hm... I consider that pretty much standard and widely used (esp. in the .net and probably java world). It would be just a bit more sorted (having them not just sitting in the namespace).
I think global functions are perfectly fine for this. In C++, we fortunately don't have to put everything in classes ;)

Quote from: "Mario"
Edit: Something like this would still look odd to me:
Code: [Select]
sf::Time &lastUse = sf::Second(someUnixTimeStampInt);
Same to me. No wonder with a reference to a temporary :D

Quote from: "Laurent"
Hmm, "As" sounds good yes.
I also like it. But are there other similar functions in SFML that begin with "To"? Or maybe a future sf::Time::ToStdDuration() interacting with Chrono?
Title: The new time API
Post by: Laurent on January 15, 2012, 09:55:31 am
Quote
But are there other similar functions in SFML that begin with "To"?

"To" functions usually apply to small utility classes that can be converted to another type, and SFML has very few of them. As far as I remember, there are "To" functions only in sf::String and sf::Utf.

Quote
Or maybe a future sf::Time::ToStdDuration() interacting with Chrono?

If I add such a conversion in the future, it will most likely be implicit. Since the type std::duration holds the semantic ("it's a duration"), unlike sf::Int32 which doesn't make it clear that you'll get milliseconds, there's no need have an explicit conversion function.
Code: [Select]
std::duration<...> d = clock.GetElapsedTime();
...looks good enough to me.

Same for the other way round:
Code: [Select]
sf::Sleep(std::seconds(1));
Title: The new time API
Post by: Silvah on January 16, 2012, 03:57:36 pm
Quote from: "Laurent"
Your solution would be definitely too verbose.
Well, I'd rather give the functions verbose names than unclear ones. "Seconds"? What does it do with seconds? Ah, let's see in the docs... it returns a Time object that represents given amount of seconds. Okay. But "Time::FromSeconds" (or "TimeFromSeconds" or anything that explicitly states what the function does) makes that clear from the beginning.

And while it may seem consistent with the standard library, it's actually not. You see, std::seconds is a type that stores some duration in seconds, so it's pretty obvious name for it. It's not a named constructor.
Title: The new time API
Post by: Laurent on January 16, 2012, 04:14:33 pm
Free functions are less clear the very first time you see them, while static member functions are confusing everytime you deal with a sf::Time instance (FromSeconds is static, ToSeconds is not -- the kind of thing that you never remember). I even expect users to post messages on the forum to ask why time.FromSeconds(n) doesn't modify their time variable.

And static functions are still very verbose. Making functions clear is the top priority, but there's a limit at which verbosity becomes important too.

Quote
And while it may seem consistent with the standard library, it's actually not. You see, std::seconds is a type that stores some duration in seconds, so it's pretty obvious name for it. It's not a named constructor.

std::seconds won't be better if the function that you're calling expects a template std::duration argument, or another specialized time class. Which might happen quite often.
Title: The new time API
Post by: Silvah on January 17, 2012, 05:42:02 pm
Quote from: "Laurent"
Free functions are less clear the very first time you see them, while static member functions are confusing everytime you deal with a sf::Time instance (FromSeconds is static, ToSeconds is not -- the kind of thing that you never remember). I even expect users to post messages on the forum to ask why time.FromSeconds(n) doesn't modify their time variable.
You missed the point. I don't care whether it's static or not. It's all about the very name:
Quote from: "Silvah"
But "Time::FromSeconds" (or "TimeFromSeconds" or anything that explicitly states what the function does) makes that clear from the beginning.


Quote from: "Laurent"
std::seconds won't be better if the function that you're calling expects a template std::duration argument, or another specialized time class
Er, what do you mean?
Title: The new time API
Post by: Laurent on January 17, 2012, 06:17:47 pm
Quote
You missed the point. I don't care whether it's static or not. It's all about the very name

Ok, I get it now.
But, seriously, what could sf::Seconds(n) return, other than a time value of n seconds? In actual code, the context will make it even more obvious. Seconds are time, it's implicit. "TimeFromSeconds" even looks weird, because seconds are already time. If sf::Seconds returned something else than a time value, ok, it would be very confusing. But it doesn't.
So do we really need all this extra verbosity? I don't think so.

Quote
Er, what do you mean?

You said that the STL API was clearer because std::seconds is a class. It's true: if the function that you're calling expects a std::seconds argument, it's clear that you must construct a std::seconds instance. But if it expects a std::duration<...>, a std::milliseconds or whatever other than std::seconds (which is likely to happen), then it's not clearer than SFML's solution, you still need to read the documentation to figure out what to do.
Title: The new time API
Post by: Silvah on January 17, 2012, 06:54:54 pm
Quote from: "Laurent"
But, seriously, what could sf::Seconds(n) return, other than a time value of n seconds?
In fact, I have a hard time getting its meaning. I can't think of any thing that call could do. Including returning a time of n seconds. It's just too imprecise.

Quote from: "Laurent"
Seconds are time, it's implicit. "TimeFromSeconds" even looks weird, because seconds are already time.
That's disputable, actually. The definition of time is very abstract and vague. The definition of second is very precise. You know, the second is a unit of measurement of time (defined to, well, something). So, you have a number of seconds (a specific thing), and convert it to some abstract thing (namely, to time). Makes some sense, given that the end user isn't supposed to know how the time is defined internally (just like we don't how the universe represents the time internally) ;)

Quote from: "Laurent"
You said that the STL API was clearer because std::seconds is a class. It's true: if the function that you're calling expects a std::seconds argument, it's clear that you must construct a std::seconds instance. But if it expects a std::duration<...>, a std::milliseconds or whatever other than std::seconds (which is likely to happen), then it's not clearer than SFML's solution, you still need to read the documentation to figure out what to do.
The first thing one would try is probably to construct a std::seconds object and let the compiler worry about the (implicit) conversion. And this really works. But I don't see what does it have to do with what we're talking about. Its name is clearer because it's a class; the fact that it's in fact a typedef to a template has some nasty implications, that's right, but these are beyond the scope of what we're currently focusing on.


As an aside, a minor nitpick that's not meant to be treated very seriously (it just shows how relative things that we think are obvious can be): what's the result of "an hour + two minutes"? Sixty-two minutes? Why not fifty-eight minutes? In some cultures, the past is in front of you (because you can see it) and the future is behind you (because you can't). And you add, so you go forward, so you effectively subtract the time ;)
Title: The new time API
Post by: Laurent on January 17, 2012, 08:13:33 pm
Quote
In fact, I have a hard time getting its meaning. I can't think of any thing that call could do. Including returning a time of n seconds. It's just too imprecise.

If you think of it as a named constructor for a time class (whether it is named sf::Seconds of sf::Time doesn't really matter), I think it's clear enough. It's not a function that does something.

Quote
That's disputable, actually. The definition of time is very abstract and vague. The definition of second is very precise. You know, the second is a unit of measurement of time (defined to, well, something). So, you have a number of seconds (a specific thing), and convert it to some abstract thing (namely, to time). Makes some sense, given that the end user isn't supposed to know how the time is defined internally (just like we don't how the universe represents the time internally)

You want a certain amount of seconds -> you call sf::Seconds. I think it's really straightforward. Adding "Time" to the function name would add confusion. At least that's my opinion and I'm not convinced by your arguments so far ;)

Quote
The first thing one would try is probably to construct a std::seconds object and let the compiler worry about the (implicit) conversion.

How does the user know about the std::seconds class if it doesn't appear in the function prototype?

Quote
But I don't see what does it have to do with what we're talking about.

You said that SFML tries to mimic the STL in a bad (or less clear) way. I think it's wrong, the same issues apply with the STL API.

Quote
As an aside, a minor nitpick that's not meant to be treated very seriously (it just shows how relative things that we think are obvious can be): what's the result of "an hour + two minutes"? Sixty-two minutes? Why not fifty-eight minutes? In some cultures, the past is in front of you (because you can see it) and the future is behind you (because you can't). And you add, so you go forward, so you effectively subtract the time

I think it's simpler than what you think: if you add two values of a certain unit, you must use mathematical addition. And you end up with a new value of the same unit which is the sum of both operands.
If I understand correctly, your point would apply if we tried to add a time span to a time point (like "what's the result of 11:52 plus 2 minutes?). But here we add a time span to another time span -- we get a bigger time span.
Title: The new time API
Post by: Mario on January 17, 2012, 11:40:12 pm
I think I know what Silvah is trying to point out (correct me if I'm wrong):

A "time" could be several things. It could mean a duration as well as a specific point in time (as in 5:00 pm). That's more or less ambiguous.

What I'd be doing would be calling the basic time object Duration and then renaming Clock to Stopwatch.

---

Actually, thinking about it, it could get even more interesting and making the rework even more awesome:

sf::Duration: Defines a specific duration like 5 seconds, 10 minutes or 50 µs.

sf::Clock: Abstract base class for the following classes (not sure about this one).

sf::Stopwatch: Essentially the current sf::Clock class. It allows you to start a timer and then determine the amount of time that has passed.

sf::Timer: A class allowing you to start a timer that will trigger a new event once some specific time has passed. The event data includes a pointer (or reference?) to this object, allowing identification/control. I'm not really sure how this should work, to be honest, it might as well be some extension to windows instead (window.SetTimeout(myidentifier,somedurationobject)).
Title: The new time API
Post by: Laurent on January 18, 2012, 08:13:01 am
Quote
A "time" could be several things. It could mean a duration as well as a specific point in time (as in 5:00 pm). That's more or less ambiguous.

There's absolutely no concept of time point in SFML, so the ambiguity is very reduced.

Quote
What I'd be doing would be calling the basic time object Duration

I have no strong argument against it, but sf::Time looks better :D

Quote
and then renaming Clock to Stopwatch.

I recently learnt that StopWatch is a better name, but it seems that sf::Clock is ok too.

Quote
sf::Clock: Abstract base class for the following classes (not sure about this one).

An abstract class here? Why?

Quote
sf::Timer: A class allowing you to start a timer that will trigger a new event once some specific time has passed.

SFML doesn't support "events" (signals/slots). And it's too high level anyway, what we're talking about is a simple (and thus unique) way of measuring and handling time.
Title: The new time API
Post by: Silvah on January 18, 2012, 06:26:15 pm
Quote from: "Laurent"
It's not a function that does something.
But it is a function that does something, it returns an object ;)

Quote from: "Laurent"
You want a certain amount of seconds -> you call sf::Seconds. I think it's really straightforward.
I think it's not, the name is too vague. But I guess I have said that already.

Quote from: "Laurent"
Adding "Time" to the function name would add confusion. At least that's my opinion and I'm not convinced by your arguments so far ;)
Have I already said that you missed the point, by any chance?
Quote from: "Silvah"
But "Time::FromSeconds" (or "TimeFromSeconds" or anything that explicitly states what the function does) makes that clear from the beginning.
While I agree that the names I proposed aren't the most fortunate ones, they're not the only possibilities. Hopefully someone who knows English better than I do can come up with something better. So maybe we should focus on inventing better name instead?

Quote from: "Laurent"
How does the user know about the std::seconds class if it doesn't appear in the function prototype?
The user knows because it's the thing that one uses to store seconds. And then the user tries to pass it into something which expects other units. And lo! it happens to work. Hooray for trial and error! ;)

Quote from: "Laurent"
You said that SFML tries to mimic the STL in a bad (or less clear) way. I think it's wrong, the same issues apply with the STL API.
These issues are not the same. They're related, yes, but they're slightly different and their causes have nothing to do with each other.
Title: The new time API
Post by: Laurent on January 18, 2012, 08:13:32 pm
Hmm... let's try to work differently ;)

Who else has an opinion about the function names? Clear and concise, or too vague?

Who (native english speakers?) can suggest better names?

You'd better answer if you want to see SFML 2.0 soon :twisted: :lol:
Title: The new time API
Post by: Tex Killer on January 18, 2012, 09:08:28 pm
Quote from: "Laurent"
Who else has an opinion about the function names? Clear and concise, or too vague?


I think he has a point... Not a very strong one, but a point that counts towards the simplicity of trial and error...

You write sf::Time and hit the completion shortcut of your IDE: you get sf::TimeFromSeconds, sf::TimeFromMilliseconds and sf::TimeFromMicroseconds on the sugestion list.

But I wouldn't mind if it ends as you made so far.
Title: The new time API
Post by: Hiura on January 18, 2012, 09:27:24 pm
For what it is worth, here's my ideas.

First, it was proposed to change sf::Clock name (to StopWatch or something else). IMHO, I think it is NOT a good idea : sf::Clock came in SFML 1 and changing its name for something "only a little bit better" would confuse most people. There won't be any benefit.

Now, about the sf::Time class : I would suggest sf::TimeSpan instead. It's maybe not the most crucial thing here. However, these 4 last letters clearly state that you won't be able to get the current day or the week, or get the next leap year, etc...

There is also the problem of ToSeconds(), or, as proposed above, AsSeconds(). Personally, I would prefer TotalSeconds instead because there's no meaning of conversion : we only extract the number of seconds from the time span. In fact, this is how Microsoft does it in C# with TimeSpan (http://msdn.microsoft.com/en-us/library/system.timespan_properties.aspx).

You discussed about making Seconds(), Milliseconds(), and Microseconds() static functions of sf::Time or free function instead. Because I have relatively little experience on this topic I decided to look around what was the best and found this article (http://drdobbs.com/184401197) :
Quote
[...]
This analysis applies to any kind of member functions, including static ones. Adding a static member function to a class when its functionality could be implemented as a non-friend non-member decreases encapsulation by exactly the same amount as does adding a non-static member function. One implication of this is that it's generally a bad idea to move a free function into a class as a static member just to show that it's related to the class. [...]


However, I 'm not sure what name fit the best. sf::TimeFromSeconds (or TimeSpanFronSeconds) is long but has no ambiguity and is straightforward. But Seconds seems enough in most context : like sf::Sleep(sf::Seconds(1)).

Sorry if I'm not focused on the real issue.
Title: The new time API
Post by: Groogy on January 18, 2012, 09:27:55 pm
Quote from: "Laurent"
You'd better answer if you want to see SFML 2.0 soon :twisted: :lol:


Damn you!

 I can understand his point. But I feel your arguments are more correct. Kind of hard to speak my mind from the phone. But take it as a base that I will always like the solution that makes it sound more like speech. Take time.As* for example.

I hope I count as well since I started with English around the age of 8.

EXPANSION:

Alright now that I'm on my Laptop instead I would like to expand this a little more.

From my understanding this is the proposed convention from Silvah:
Code: [Select]
time = sf::Time::FromSeconds(N);This to me reads as: "time equal to time from N seconds"
Could cut away the second time but it still become "time equal to from N seconds"

This is why I like Laurents version more as it becomes:
Code: [Select]
time = sf::Seconds(N); which in my eyes reads as "time equal to N seconds". And to me this feels a lot more natural.

And I can't see the ambiguity that other's see with having these functions in the global space. But since people are seeing things. It means that it isn't perfect. But I urge that you do something similar. I really love it when you can read the code as normal English speech and it goes hand in hand with readability, some programming paradigms like polymorphism and in some cases it can also solve ambiguity just as how it is solved in real life language. Though of course sometimes you can still be confused in real life because you missed the context as the sentence was said in. But doing that in code is much harder in my opinion because the text is there starring you in the face while words float away and you have to guess what you missed.

Just adding an example and "translating it":
Code: [Select]
sf::Time time = sf::Seconds( N  ); // time is equal to N seconds
printf( "%f", time.AsMicroSeconds() ); // Print the time as micro seconds
myCountDown -= clock.GetElapsedTime(); // The countdown is subtracted with the elapsed time.
if( myCountDown <= sf::Seconds( 0 ) ) // If the countdown is less or equal to 0 seconds then do stuff
    doStuff();
Title: The new time API
Post by: model76 on January 18, 2012, 09:46:25 pm
I really like "AsSeconds", as Groogy suggested. It's short, and it explains what it does perfectly.
"TotalSeconds" is not only longer, but it also introduces ambiguity, as it could be understood as "the seconds component of the time duration".

I also see Silvah's point. TimeFromSeconds is self-explanatory, while Seconds is not. It is also a long name, but is that really such a big problem in this case? Is it likely to often be used in a context where the long name makes the code hard to read?

Also, I think I would personally find TimeFromSeconds easier to remember, because it starts with Time. I often have a hard time remembering names, so code completion helps me a lot.
Title: The new time API
Post by: Ceylo on January 18, 2012, 09:51:10 pm
So much discussion... for a little innocent name.. :(
Title: The new time API
Post by: model76 on January 18, 2012, 11:53:03 pm
You are right, it probably isn't that important, but Laurent is holding SFML 2.0 hostage!  :(  :wink:
Title: The new time API
Post by: Tex Killer on January 19, 2012, 03:41:21 am
Quote from: "Groogy"
Code: [Select]
if( myCountDown <= sf::Seconds( 0 ) ) // If the countdown is less or equal to 0 seconds then do stuff
    doStuff();

Not that it matters much, but I don't think this would work as I think you wanted it to... It would only check if the myCountDown clock haven't yet passed one single microsecond, as the time instance with 1 microsecond is bigger than the one with 0.
Title: The new time API
Post by: Laurent on January 19, 2012, 07:54:50 am
Quote
Not that it matters much, but I don't think this would work as I think you wanted it to... It would only check if the myCountDown clock haven't yet passed one single microsecond, as the time instance with 1 microsecond is bigger than the one with 0.

As the name and comment imply, I think the myCountDown variable decreases until it reaches zero. So the code is ok.
Title: The new time API
Post by: Tex Killer on January 19, 2012, 09:15:04 am
Well, am I not dumb?  :lol:

I've read each line of the code separately.
Title: The new time API
Post by: Groogy on January 19, 2012, 01:08:17 pm
Also functioning code wasn't my point but the fact that you can read the code as normal English. Ruby is based on this concept. Example:
Code: [Select]
10.times do
  print "Hello World!"
end
Reading that becomes "10 times print hello world!" or even "10 times do action print hello world!" (If you take to note that the do-notation in Ruby is a lambda function)

As soon as you add more text to a name to "reduce ambiguity", reading it becomes harder. Now of course not everyone might approve of how I do it to solve ambiguity and increase readability. But since SFML is supposed to be simple I think having it close to English speech makes it that by default. As having the code written as this forces the user to maintain it simple, readable and the context in the code can be derived from the surrounding code just like in a book.
Title: The new time API
Post by: Silvah on January 19, 2012, 07:50:44 pm
Quote from: "Groogy"
From my understanding this is the proposed convention from Silvah:
Code: [Select]
time = sf::Time::FromSeconds(N);
I wasn't the one who proposed this. Mario was (http://sfml-dev.org/forum/viewtopic.php?p=44504#44504).

Quote from: "Ceylo"
So much discussion... for a little innocent name.. :(
No wonder, naming is the hardest thing in programming :D
Title: The new time API
Post by: Nexus on January 19, 2012, 08:48:57 pm
While I agree that function names should be intuitive, I wouldn't exaggerate. Long names are more difficult to read, write and remember; in my opinion they are only worth the drawbacks when they really increase the expressivity.

And I think that
Code: [Select]
sf::Time time = sf::Seconds(4);is perfectly expressive, as well as
Code: [Select]
sf::Sleep(sf::Seconds(4));
On the other side, things like
Code: [Select]
sf::Time t = sf::Time::FromSeconds(4);or
Code: [Select]
sf::Sleep(sf::Time::FromSeconds(4))are heavy and contain duplicate information, but don't give us more information about the semantics. At least no useful one -- we see that a sf::Time object is constructed, but since sf::Time is the only SFML time class, this is  obvious. Additionally, the exactly returned type isn't that important.

Also concerning sf::TimeSpan: While it is useful to differ between time points and time spans (like duration in Boost/Std), SFML doesn't have this concept, so I consider sf::Time general enough.
Title: The new time API
Post by: Laurent on January 19, 2012, 11:53:56 pm
I've pushed the new API. I didn't change anything, except the prefix: "To" is now "As".
Title: The new time API
Post by: Groogy on January 20, 2012, 01:16:58 am
Quote from: "Laurent"
I've pushed the new API. I didn't change anything, except the prefix: "To" is now "As".

My work here is done  8)
Title: The new time API
Post by: Mario on January 20, 2012, 01:14:35 pm
As it's no longer possible to just use "sf::Sleep(0);" to allow context switches (or I missed something new other than calling "sf::Sleep(sf::Seconds(0));"?), how about adding something like "sf::Idle();" or "sf::Sleep(sf::Idle);" just doing that? Just a bit lazy here.
Title: The new time API
Post by: Laurent on January 20, 2012, 01:21:03 pm
There's a special Time::Zero value
Code: [Select]
sf::Sleep(sf::Time::Zero);
Is that enough?

If I implemented an "Idle" thing it would have to be specialized according to the OS, Sleep(0) is not strictly equivalent. And by the way, it would probably be named sf::Yield().
Title: The new time API
Post by: Mario on January 20, 2012, 04:11:47 pm
Sounds reasonable enough.
Title: The new time API
Post by: Nexus on January 20, 2012, 07:41:33 pm
Quote from: "Laurent"
I've pushed the new API. I didn't change anything, except the prefix: "To" is now "As".
Sounds great, I'm looking forward to update and adapt everything in Thor :)
(really)
Title: The new time API
Post by: Nexus on January 21, 2012, 01:19:54 pm
What do you think about an operator that returns the ratio between two times?
Code: [Select]
float operator/ (sf::Time lhs, sf::Time rhs)
{
    return lhs.AsSeconds() / rhs.AsSeconds();
}

By the way, why don't you pass sf::Time objects by value? You do it also for sf::Uint64. 8 bytes to copy is negligible, considering that references usually consume also 4 or 8 bytes. However, pass by value doesn't imply the dereferencing cost, and code becomes more beautiful without const&. In the end, you can only win :)
Title: The new time API
Post by: Laurent on January 21, 2012, 01:42:38 pm
Quote
What do you think about an operator that returns the ratio between two times?

What would it mean?

Quote
By the way, why don't you pass sf::Time objects by value?

I have no idea, I already do it for all other functions :lol:
Title: The new time API
Post by: Nexus on January 21, 2012, 01:48:19 pm
Quote from: "Laurent"
What would it mean?
Generally, the operator/ can be used to find out what fraction of a time span has already passed. A concrete use case looks like this:
Code: [Select]
// Returns particle lifetime progress in [0, 1]
float GetPassedRatio(const Particle& particle)
{
return GetPassedLifetime(particle) / GetTotalLifetime(particle);
}


Quote from: "Laurent"
I have no idea, I already do it for all other functions :lol:
A search&replace is performed fast :D
Title: The new time API
Post by: Laurent on January 21, 2012, 03:43:34 pm
Quote
Generally, the operator/ can be used to find out what fraction of a time span has already passed.

Ok. But what if one wants an integer division? Isn't it better to let users choose what type they want to manipulate for this specific use case?

Quote
A search&replace is performed fast

Yep, I'll do it.
Title: The new time API
Post by: Nexus on January 21, 2012, 07:59:02 pm
I thought this operation will be natural from a mathematical point of view, if we are able to multiply times with factors.
Code: [Select]
time1         == factor * time2
time1 / time2 == factor

However I see that there is a problem because there are operator* overloads for float and sf::Uint64...

I'm not sure whether two overloads are a good idea anyway, since it makes multiplications ambiguous for other factor types. But I also understand that providing only sf::Uint64 is too unflexible, and only float might lead to loss of precision...

In Boost.Chrono, the division of two duration<T> objects yields T as return type. Hmm, tricky :?
Title: The new time API
Post by: Groogy on January 21, 2012, 11:23:20 pm
I think leaving it to the user is better because there is only headache along this path. If you really want it I wouldn't do it as an operator as it's return type is not the same.