update Time & Duration

This commit is contained in:
Nomango 2019-04-09 02:25:17 +08:00 committed by Nomango
parent de5a51462e
commit aa921e53ba
9 changed files with 155 additions and 131 deletions

View File

@ -63,8 +63,8 @@ namespace easy2d
{ {
E2D_NOT_USED(dt); E2D_NOT_USED(dt);
frame_time_.push_back(time::Now()); frame_time_.push_back(Time::Now());
while (frame_time_.back() - frame_time_.front() >= time::Second) while (frame_time_.back() - frame_time_.front() >= time::Sec)
{ {
frame_time_.erase(frame_time_.begin()); frame_time_.erase(frame_time_.begin());
} }

View File

@ -37,6 +37,6 @@ namespace easy2d
protected: protected:
TextPtr debug_text_; TextPtr debug_text_;
Array<TimePoint> frame_time_; Array<Time> frame_time_;
}; };
} }

View File

@ -28,65 +28,82 @@ namespace easy2d
namespace time namespace time
{ {
//------------------------------------------------------- //-------------------------------------------------------
// TimePoint // Time
//------------------------------------------------------- //-------------------------------------------------------
TimePoint::TimePoint() Time::Time()
{ {
} }
TimePoint::TimePoint(long dur) Time::Time(long dur)
: dur_(dur) : dur_(dur)
{ {
} }
const TimePoint TimePoint::operator+(const Duration & dur) const const Time Time::operator+(const Duration & dur) const
{ {
return TimePoint{ dur_ + dur.Milliseconds() }; return Time{ dur_ + dur.Milliseconds() };
} }
const TimePoint TimePoint::operator-(const Duration & dur) const const Time Time::operator-(const Duration & dur) const
{ {
return TimePoint{ dur_ - dur.Milliseconds() }; return Time{ dur_ - dur.Milliseconds() };
} }
TimePoint & TimePoint::operator+=(const Duration & other) Time & Time::operator+=(const Duration & other)
{ {
dur_ += other.Milliseconds(); dur_ += other.Milliseconds();
return (*this); return (*this);
} }
TimePoint & TimePoint::operator-=(const Duration &other) Time & Time::operator-=(const Duration &other)
{ {
dur_ -= other.Milliseconds(); dur_ -= other.Milliseconds();
return (*this); return (*this);
} }
const Duration TimePoint::operator-(const TimePoint & other) const const Duration Time::operator-(const Time & other) const
{ {
return Duration(dur_ - other.dur_); return Duration(dur_ - other.dur_);
} }
Time Time::Now() E2D_NOEXCEPT
{
static LARGE_INTEGER freq = {};
if (freq.QuadPart == 0LL)
{
// the function will always succceed on systems that run Windows XP or later
QueryPerformanceFrequency(&freq);
}
LARGE_INTEGER count;
QueryPerformanceCounter(&count);
const long long whole = (count.QuadPart / freq.QuadPart) * 1000LL;
const long long part = (count.QuadPart % freq.QuadPart) * 1000LL / freq.QuadPart;
return Time{ static_cast<long>(whole + part) };
}
//------------------------------------------------------- //-------------------------------------------------------
// Duration // Duration
//------------------------------------------------------- //-------------------------------------------------------
const Duration Millisecond = 1L; const Duration Ms = 1L;
const Duration Second = 1000 * Millisecond; const Duration Sec = 1000 * Ms;
const Duration Minute = 60 * Second; const Duration Min = 60 * Sec;
const Duration Hour = 60 * Minute; const Duration Hour = 60 * Min;
namespace namespace
{ {
const auto duration_regex = std::wregex(LR"([-+]?([0-9]*(\.[0-9]*)?[a-z]+)+)"); const auto duration_regex = std::wregex(LR"([-+]?([0-9]*(\.[0-9]*)?[a-z]+)+)");
typedef std::unordered_map<std::wstring, Duration> UnitMap; typedef std::unordered_map<String, Duration> UnitMap;
const auto unit_map = UnitMap const auto unit_map = UnitMap
{ {
{L"ms", Millisecond}, {L"ms", Ms},
{L"s", Second}, {L"s", Sec},
{L"m", Minute}, {L"m", Min},
{L"h", Hour} {L"h", Hour}
}; };
} }
@ -103,49 +120,53 @@ namespace easy2d
float Duration::Seconds() const float Duration::Seconds() const
{ {
long long sec = milliseconds_ / Second.milliseconds_; long sec = milliseconds_ / Sec.milliseconds_;
long long ms = milliseconds_ % Second.milliseconds_; long ms = milliseconds_ % Sec.milliseconds_;
return static_cast<float>(sec) + static_cast<float>(ms) / 1000.f; return static_cast<float>(sec) + static_cast<float>(ms) / 1000.f;
} }
float Duration::Minutes() const float Duration::Minutes() const
{ {
long long min = milliseconds_ / Minute.milliseconds_; long min = milliseconds_ / Min.milliseconds_;
long long ms = milliseconds_ % Minute.milliseconds_; long ms = milliseconds_ % Min.milliseconds_;
return static_cast<float>(min) + static_cast<float>(ms) / (60 * 1000.f); return static_cast<float>(min) + static_cast<float>(ms) / (60 * 1000.f);
} }
float Duration::Hours() const float Duration::Hours() const
{ {
long long hour = milliseconds_ / Hour.milliseconds_; long hour = milliseconds_ / Hour.milliseconds_;
long long ms = milliseconds_ % Hour.milliseconds_; long ms = milliseconds_ % Hour.milliseconds_;
return static_cast<float>(hour) + static_cast<float>(ms) / (60 * 60 * 1000.f); return static_cast<float>(hour) + static_cast<float>(ms) / (60 * 60 * 1000.f);
} }
std::wstring easy2d::time::Duration::ToString() const String easy2d::time::Duration::ToString() const
{ {
if (IsZero()) if (IsZero())
{ {
return std::wstring(L"0s"); return String(L"0s");
} }
std::wstring result; String result;
long long hour = milliseconds_ / Hour.milliseconds_; long total_ms = milliseconds_;
long long min = milliseconds_ / Minute.milliseconds_ - hour * 60; if (total_ms < 0)
long long sec = milliseconds_ / Second.milliseconds_ - (hour * 60 * 60 + min * 60); {
long long ms = milliseconds_ % Second.milliseconds_;
if (milliseconds_ < 0)
result.append(L"-"); result.append(L"-");
total_ms = -total_ms;
}
long hour = total_ms / Hour.milliseconds_;
long min = total_ms / Min.milliseconds_ - hour * 60;
long sec = total_ms / Sec.milliseconds_ - (hour * 60 * 60 + min * 60);
long ms = total_ms % Sec.milliseconds_;
if (hour) if (hour)
{ {
result.append(std::to_wstring(hour)).append(L"h"); result.append(easy2d::to_wstring(hour)).append(L"h");
result.append(std::to_wstring(min)).append(L"m"); result.append(easy2d::to_wstring(min)).append(L"m");
} }
else if(min) else if(min)
{ {
result.append(std::to_wstring(min)).append(L"m"); result.append(easy2d::to_wstring(min)).append(L"m");
} }
if (ms != 0) if (ms != 0)
@ -162,7 +183,7 @@ namespace easy2d
} }
else if (sec != 0) else if (sec != 0)
{ {
result.append(std::to_wstring(sec)).append(L"s"); result.append(easy2d::to_wstring(sec)).append(L"s");
} }
return result; return result;
} }
@ -340,51 +361,16 @@ namespace easy2d
return dur * val; return dur * val;
} }
std::wostream & easy2d::time::operator<<(std::wostream & out, const Duration & dur) Duration Duration::Parse(const String& str)
{
return out << dur.ToString();
}
std::wistream & easy2d::time::operator>>(std::wistream & in, Duration & dur)
{
std::wstring str;
in >> str;
dur = time::ParseDuration(str);
return in;
}
//-------------------------------------------------------
// Functions
//-------------------------------------------------------
TimePoint easy2d::time::Now() E2D_NOEXCEPT
{
static LARGE_INTEGER freq = {};
if (freq.QuadPart == 0LL)
{
// the function will always succceed on systems that run Windows XP or later
QueryPerformanceFrequency(&freq);
}
LARGE_INTEGER count;
QueryPerformanceCounter(&count);
const long long whole = (count.QuadPart / freq.QuadPart) * 1000LL;
const long long part = (count.QuadPart % freq.QuadPart) * 1000LL / freq.QuadPart;
return TimePoint{ static_cast<long>(whole + part) };
}
Duration easy2d::time::ParseDuration(const std::wstring & str)
{ {
size_t len = str.length(); size_t len = str.length();
size_t pos = 0; size_t pos = 0;
bool negative = false; bool negative = false;
Duration d; Duration d;
if (!std::regex_match(str, duration_regex)) if (!std::regex_match(str.c_str(), duration_regex))
{ {
E2D_ERROR_LOG(L"time::ParseDuration failed, invalid duration"); E2D_ERROR_LOG(L"Duration::Parse failed, invalid duration");
return Duration(); return Duration();
} }
@ -410,12 +396,12 @@ namespace easy2d
} }
} }
std::wstring num_str = str.substr(pos, i - pos); String num_str = str.substr(pos, i - pos);
pos = i; pos = i;
if (num_str.empty() || num_str == L".") if (num_str.empty() || num_str == L".")
{ {
E2D_ERROR_LOG(L"time::ParseDuration failed, invalid duration"); E2D_ERROR_LOG(L"Duration::Parse failed, invalid duration");
return Duration(); return Duration();
} }
@ -429,16 +415,16 @@ namespace easy2d
} }
} }
std::wstring unit_str = str.substr(pos, i - pos); String unit_str = str.substr(pos, i - pos);
pos = i; pos = i;
if (unit_map.find(unit_str) == unit_map.end()) if (unit_map.find(unit_str) == unit_map.end())
{ {
E2D_ERROR_LOG(L"time::ParseDuration failed, invalid duration"); E2D_ERROR_LOG(L"Duration::Parse failed, invalid duration");
return Duration(); return Duration();
} }
double num = std::stod(num_str); double num = std::wcstod(num_str.c_str(), nullptr);
Duration unit = unit_map.at(unit_str); Duration unit = unit_map.at(unit_str);
d += unit * num; d += unit * num;
} }

View File

@ -20,6 +20,9 @@
#pragma once #pragma once
#include "../macros.h" #include "../macros.h"
#include "../common/String.h"
#include <ostream>
#include <istream>
namespace easy2d namespace easy2d
{ {
@ -28,9 +31,9 @@ namespace easy2d
// 时间段 // 时间段
// //
// 时间段表示法: // 时间段表示法:
// 5 秒: time::Second * 5 // 5 秒: time::Sec * 5
// 1.5 小时: time::Hour * 1.5 // 1.5 小时: time::Hour * 1.5
// 3 小时 45 分 15 秒: time::Hour * 3 + time::Minute * 45 + time::Second * 15 // 3 小时 45 分 15 秒: time::Hour * 3 + time::Min * 45 + time::Sec * 15
// 在 VS2015 及更高版本可以使用 time literals: // 在 VS2015 及更高版本可以使用 time literals:
// 5 秒: 5_s // 5 秒: 5_s
// 1.5 小时: 1.5_h // 1.5 小时: 1.5_h
@ -60,7 +63,7 @@ namespace easy2d
inline bool IsZero() const { return milliseconds_ == 0LL; } inline bool IsZero() const { return milliseconds_ == 0LL; }
// 转为字符串 // 转为字符串
std::wstring ToString() const; String ToString() const;
inline operator bool() const { return !IsZero(); } inline operator bool() const { return !IsZero(); }
@ -102,60 +105,75 @@ namespace easy2d
friend const Duration operator/ (float, const Duration &); friend const Duration operator/ (float, const Duration &);
friend const Duration operator/ (double, const Duration &); friend const Duration operator/ (double, const Duration &);
friend std::wostream& operator<< (std::wostream &, const Duration &); public:
friend std::wistream& operator>> (std::wistream &, Duration &); // 时间段格式化
//
// 时间段字符串允许是有符号的浮点数, 并且带有时间单位后缀
// 例如: "300ms", "-1.5h", "2h45m"
// 允许的时间单位有 "ms", "s", "m", "h"
static Duration Parse(const String& parse_str);
template <typename _Char>
friend inline std::basic_ostream<_Char>& operator<<(std::basic_ostream<_Char>& out, const Duration& dur)
{
return out << dur.ToString();
}
template <typename _Char>
friend inline std::basic_istream<_Char>& operator>>(std::basic_istream<_Char>& in, Duration& dur)
{
String str;
if (in >> str)
{
dur = Duration::Parse(str);
}
return in;
}
private: private:
long milliseconds_; long milliseconds_;
}; };
/* 预定义的时间段 */ /* 预定义的时间段 */
E2D_API extern const Duration Millisecond; // 毫秒 E2D_API extern const Duration Ms; // 毫秒
E2D_API extern const Duration Second; // 秒 E2D_API extern const Duration Sec; // 秒
E2D_API extern const Duration Minute; // 分钟 E2D_API extern const Duration Min; // 分钟
E2D_API extern const Duration Hour; // 小时 E2D_API extern const Duration Hour; // 小时
// 时间 // 时间
// //
// 获取当前时间: TimePoint now = time::Now(); // 获取当前时间: Time now = Time::Now();
// 两时间相减, 得到一个 Duration 对象, 例如: // 两时间相减, 得到一个 Duration 对象, 例如:
// TimePoint t1, t2; // Time t1, t2;
// int ms = (t2 - t1).Milliseconds(); // 获取两时间相差的毫秒数 // int ms = (t2 - t1).Milliseconds(); // 获取两时间相差的毫秒数
// //
struct E2D_API TimePoint struct E2D_API Time
{ {
TimePoint(); Time();
TimePoint(long); Time(long);
// 是否是零时 // 是否是零时
inline bool IsZero() const { return dur_ == 0; } inline bool IsZero() const { return dur_ == 0; }
const TimePoint operator + (const Duration &) const; const Time operator + (const Duration &) const;
const TimePoint operator - (const Duration &) const; const Time operator - (const Duration &) const;
TimePoint& operator += (const Duration &); Time& operator += (const Duration &);
TimePoint& operator -= (const Duration &); Time& operator -= (const Duration &);
const Duration operator - (const TimePoint &) const; const Duration operator - (const Time &) const;
public:
// 获取当前时间
// 由于该时间点基于系统启动时间开始计算, 所以无法格式化该时间,
// 也无法获得该时间的 Unix 时间戳
static Time Now() E2D_NOEXCEPT;
private: private:
long dur_; long dur_;
}; };
// 获取当前时间
//
// 由于该时间点基于系统启动时间开始计算, 所以无法格式化该时间,
// 也无法获得该时间的 Unix 时间戳
E2D_API TimePoint Now() E2D_NOEXCEPT;
// 时间段格式化
//
// 时间段字符串允许是有符号的浮点数, 并且带有时间单位后缀
// 例如: "300ms", "-1.5h", "2h45m"
// 允许的时间单位有 "ms", "s", "m", "h"
E2D_API Duration ParseDuration(const std::wstring& parse_str);
} }
} }
@ -172,17 +190,17 @@ namespace easy2d
{ {
inline const easy2d::time::Duration operator "" _ms(long double val) inline const easy2d::time::Duration operator "" _ms(long double val)
{ {
return easy2d::time::Millisecond * val; return easy2d::time::Ms * val;
} }
inline const easy2d::time::Duration operator "" _s(long double val) inline const easy2d::time::Duration operator "" _s(long double val)
{ {
return easy2d::time::Second * val; return easy2d::time::Sec * val;
} }
inline const easy2d::time::Duration operator "" _m(long double val) inline const easy2d::time::Duration operator "" _m(long double val)
{ {
return easy2d::time::Minute * val; return easy2d::time::Min * val;
} }
inline const easy2d::time::Duration operator "" _h(long double val) inline const easy2d::time::Duration operator "" _h(long double val)
@ -192,17 +210,17 @@ namespace easy2d
inline const easy2d::time::Duration operator "" _ms(unsigned long long val) inline const easy2d::time::Duration operator "" _ms(unsigned long long val)
{ {
return easy2d::time::Millisecond * val; return easy2d::time::Ms * val;
} }
inline const easy2d::time::Duration operator "" _s(unsigned long long val) inline const easy2d::time::Duration operator "" _s(unsigned long long val)
{ {
return easy2d::time::Second * val; return easy2d::time::Sec * val;
} }
inline const easy2d::time::Duration operator "" _m(unsigned long long val) inline const easy2d::time::Duration operator "" _m(unsigned long long val)
{ {
return easy2d::time::Minute * val; return easy2d::time::Min * val;
} }
inline const easy2d::time::Duration operator "" _h(unsigned long long val) inline const easy2d::time::Duration operator "" _h(unsigned long long val)

View File

@ -351,6 +351,9 @@ namespace easy2d
std::basic_ostream<String::value_type>& operator<<(std::basic_ostream<String::value_type>& os, const String & str); std::basic_ostream<String::value_type>& operator<<(std::basic_ostream<String::value_type>& os, const String & str);
std::basic_istream<String::value_type>& operator>>(std::basic_istream<String::value_type>& is, String & str); std::basic_istream<String::value_type>& operator>>(std::basic_istream<String::value_type>& is, String & str);
std::basic_ostream<char>& operator<<(std::basic_ostream<char>& os, const String& str);
std::basic_istream<char>& operator>>(std::basic_istream<char>& is, String& str);
// //
// to_string functions // to_string functions
// //
@ -1236,6 +1239,21 @@ namespace easy2d
return is; return is;
} }
inline std::basic_ostream<char>& operator<<(std::basic_ostream<char>& os, const String& str)
{
return os << str.to_string();
}
inline std::basic_istream<char>& operator>>(std::basic_istream<char>& is, String& str)
{
std::string tmp;
if (is >> tmp)
{
str = tmp;
}
return is;
}
// //
// details of to_string functions // details of to_string functions
// //

View File

@ -328,9 +328,9 @@ namespace easy2d
void Application::Update() void Application::Update()
{ {
static auto last = time::Now(); static auto last = Time::Now();
const auto now = time::Now(); const auto now = Time::Now();
const auto dt = (now - last) * time_scale_; const auto dt = (now - last) * time_scale_;
last = now; last = now;

View File

@ -141,7 +141,7 @@ namespace easy2d
if (collecting_data_) if (collecting_data_)
{ {
status_.start = time::Now(); status_.start = Time::Now();
status_.primitives = 0; status_.primitives = 0;
} }
@ -186,7 +186,7 @@ namespace easy2d
if (collecting_data_) if (collecting_data_)
{ {
status_.duration = time::Now() - status_.start; status_.duration = Time::Now() - status_.start;
} }
return hr; return hr;
} }

View File

@ -33,7 +33,7 @@ namespace easy2d
{ {
struct RenderStatus struct RenderStatus
{ {
TimePoint start; Time start;
Duration duration; Duration duration;
int primitives; int primitives;
}; };

View File

@ -2,17 +2,19 @@
#include "easy2d.h" #include "easy2d.h"
using namespace easy2d;
const int WINDOW_WIDTH = 640; const int WINDOW_WIDTH = 640;
const int WINDOW_HEIGHT = 480; const int WINDOW_HEIGHT = 480;
class MainScene class MainScene
: public easy2d::Scene : public Scene
{ {
public: public:
MainScene() MainScene()
{ {
// 创建文字节点 // 创建文字节点
easy2d::TextPtr text = new easy2d::Text(L"Hello Easy2D!"); TextPtr text = new Text(L"Hello Easy2D!");
// 设置节点大小为文字布局大小 // 设置节点大小为文字布局大小
text->SetSize(text->GetLayoutSize()); text->SetSize(text->GetLayoutSize());
// 修改节点位置, 使节点在屏幕上居中 // 修改节点位置, 使节点在屏幕上居中
@ -29,10 +31,10 @@ int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
try try
{ {
// 创建 Easy2D 程序实例 // 创建 Easy2D 程序实例
easy2d::Application app; Application app;
// 创建初始化选项 // 创建初始化选项
easy2d::Options options; Options options;
// 设置窗口宽高 // 设置窗口宽高
options.width = WINDOW_WIDTH; options.width = WINDOW_WIDTH;
options.height = WINDOW_HEIGHT; options.height = WINDOW_HEIGHT;
@ -40,7 +42,7 @@ int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
app.Init(options); app.Init(options);
// 创建场景并进入 // 创建场景并进入
easy2d::ScenePtr scene = new MainScene; ScenePtr scene = new MainScene;
app.EnterScene(scene); app.EnterScene(scene);
// 运行 // 运行