diff --git a/core/os/os.cpp b/core/os/os.cpp index 7ba8c02e0c9..9b8c1e828fa 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -86,6 +86,9 @@ uint64_t OS::get_system_time_secs() const { uint64_t OS::get_system_time_msecs() const { return 0; } +double OS::get_subsecond_unix_time() const { + return 0.0; +} void OS::debug_break(){ // something diff --git a/core/os/os.h b/core/os/os.h index 97e31cee741..11a360cd51d 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -436,6 +436,7 @@ public: virtual uint64_t get_unix_time() const; virtual uint64_t get_system_time_secs() const; virtual uint64_t get_system_time_msecs() const; + virtual double get_subsecond_unix_time() const; // For use in Time::get_unix_time(). virtual void delay_usec(uint32_t p_usec) const = 0; virtual void add_frame_delay(bool p_can_draw); diff --git a/core/os/time.cpp b/core/os/time.cpp index c7d4b73c1c7..d726edbb118 100644 --- a/core/os/time.cpp +++ b/core/os/time.cpp @@ -392,7 +392,7 @@ Dictionary Time::get_time_zone_from_system() const { } double Time::get_unix_time_from_system() const { - return OS::get_singleton()->get_unix_time(); + return OS::get_singleton()->get_subsecond_unix_time(); } uint64_t Time::get_ticks_msec() const { diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index ef081a9d4b2..7a22fdc168a 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -552,6 +552,7 @@ Returns the current UNIX epoch timestamp in seconds. [b]Important:[/b] This is the system clock that the user can manually set. [b]Never use[/b] this method for precise time calculation since its results are also subject to automatic adjustments by the operating system. [b]Always use[/b] [method get_ticks_usec] or [method get_ticks_msec] for precise time calculation instead, since they are guaranteed to be monotonic (i.e. never decrease). + [b]Note:[/b] To get a floating point timestamp with sub-second precision, use [method Time.get_unix_time_from_system]. diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 22bcdc35dae..90e16506a2f 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -172,6 +172,12 @@ uint64_t OS_Unix::get_system_time_msecs() const { return uint64_t(tv_now.tv_sec) * 1000 + uint64_t(tv_now.tv_usec) / 1000; } +double OS_Unix::get_subsecond_unix_time() const { + struct timeval tv_now; + gettimeofday(&tv_now, nullptr); + return (double)tv_now.tv_sec + double(tv_now.tv_usec) / 1000000; +} + OS::Date OS_Unix::get_date(bool utc) const { time_t t = time(nullptr); struct tm lt; diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index f277bbbfc88..33596fa014e 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -80,6 +80,7 @@ public: virtual uint64_t get_unix_time() const; virtual uint64_t get_system_time_secs() const; virtual uint64_t get_system_time_msecs() const; + virtual double get_subsecond_unix_time() const; virtual void delay_usec(uint32_t p_usec) const; virtual uint64_t get_ticks_usec() const; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 813c7c1ee23..485468ce9da 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -549,6 +549,23 @@ uint64_t OS_UWP::get_unix_time() const { return (*(uint64_t *)&ft - *(uint64_t *)&fep) / 10000000; }; +double OS_UWP::get_subsecond_unix_time() const { + // 1 Windows tick is 100ns + const uint64_t WINDOWS_TICKS_PER_SECOND = 10000000; + const uint64_t TICKS_TO_UNIX_EPOCH = 116444736000000000LL; + + SYSTEMTIME st; + GetSystemTime(&st); + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + uint64_t ticks_time; + ticks_time = ft.dwHighDateTime; + ticks_time <<= 32; + ticks_time |= ft.dwLowDateTime; + + return (double)(ticks_time - TICKS_TO_UNIX_EPOCH) / WINDOWS_TICKS_PER_SECOND; +} + void OS_UWP::delay_usec(uint32_t p_usec) const { int msec = p_usec < 1000 ? 1 : p_usec / 1000; diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 04aa55d5f01..68e99da7350 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -193,6 +193,7 @@ public: virtual Time get_time(bool utc) const; virtual TimeZoneInfo get_time_zone_info() const; virtual uint64_t get_unix_time() const; + virtual double get_subsecond_unix_time() const; virtual bool can_draw() const; virtual Error set_cwd(const String &p_cwd); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 0002529f4ca..3a821b2b2b3 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -2579,6 +2579,23 @@ uint64_t OS_Windows::get_system_time_msecs() const { return (uint64_t)(ret / WINDOWS_TICK - MSEC_TO_UNIX_EPOCH); } +double OS_Windows::get_subsecond_unix_time() const { + // 1 Windows tick is 100ns + const uint64_t WINDOWS_TICKS_PER_SECOND = 10000000; + const uint64_t TICKS_TO_UNIX_EPOCH = 116444736000000000LL; + + SYSTEMTIME st; + GetSystemTime(&st); + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + uint64_t ticks_time; + ticks_time = ft.dwHighDateTime; + ticks_time <<= 32; + ticks_time |= ft.dwLowDateTime; + + return (double)(ticks_time - TICKS_TO_UNIX_EPOCH) / WINDOWS_TICKS_PER_SECOND; +} + void OS_Windows::delay_usec(uint32_t p_usec) const { if (p_usec < 1000) Sleep(1); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 451d463469e..abc369d27f9 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -520,6 +520,7 @@ public: virtual uint64_t get_unix_time() const; virtual uint64_t get_system_time_secs() const; virtual uint64_t get_system_time_msecs() const; + virtual double get_subsecond_unix_time() const; virtual bool can_draw() const; virtual Error set_cwd(const String &p_cwd);