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);
frame_time_.push_back(time::Now());
while (frame_time_.back() - frame_time_.front() >= time::Second)
frame_time_.push_back(Time::Now());
while (frame_time_.back() - frame_time_.front() >= time::Sec)
{
frame_time_.erase(frame_time_.begin());
}

View File

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

View File

@ -28,65 +28,82 @@ namespace easy2d
namespace time
{
//-------------------------------------------------------
// TimePoint
// Time
//-------------------------------------------------------
TimePoint::TimePoint()
Time::Time()
{
}
TimePoint::TimePoint(long dur)
Time::Time(long 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();
return (*this);
}
TimePoint & TimePoint::operator-=(const Duration &other)
Time & Time::operator-=(const Duration &other)
{
dur_ -= other.Milliseconds();
return (*this);
}
const Duration TimePoint::operator-(const TimePoint & other) const
const Duration Time::operator-(const Time & other) const
{
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
//-------------------------------------------------------
const Duration Millisecond = 1L;
const Duration Second = 1000 * Millisecond;
const Duration Minute = 60 * Second;
const Duration Hour = 60 * Minute;
const Duration Ms = 1L;
const Duration Sec = 1000 * Ms;
const Duration Min = 60 * Sec;
const Duration Hour = 60 * Min;
namespace
{
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
{
{L"ms", Millisecond},
{L"s", Second},
{L"m", Minute},
{L"ms", Ms},
{L"s", Sec},
{L"m", Min},
{L"h", Hour}
};
}
@ -103,49 +120,53 @@ namespace easy2d
float Duration::Seconds() const
{
long long sec = milliseconds_ / Second.milliseconds_;
long long ms = milliseconds_ % Second.milliseconds_;
long sec = milliseconds_ / Sec.milliseconds_;
long ms = milliseconds_ % Sec.milliseconds_;
return static_cast<float>(sec) + static_cast<float>(ms) / 1000.f;
}
float Duration::Minutes() const
{
long long min = milliseconds_ / Minute.milliseconds_;
long long ms = milliseconds_ % Minute.milliseconds_;
long min = milliseconds_ / Min.milliseconds_;
long ms = milliseconds_ % Min.milliseconds_;
return static_cast<float>(min) + static_cast<float>(ms) / (60 * 1000.f);
}
float Duration::Hours() const
{
long long hour = milliseconds_ / Hour.milliseconds_;
long long ms = milliseconds_ % Hour.milliseconds_;
long hour = milliseconds_ / Hour.milliseconds_;
long ms = milliseconds_ % Hour.milliseconds_;
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())
{
return std::wstring(L"0s");
return String(L"0s");
}
std::wstring result;
long long hour = milliseconds_ / Hour.milliseconds_;
long long min = milliseconds_ / Minute.milliseconds_ - hour * 60;
long long sec = milliseconds_ / Second.milliseconds_ - (hour * 60 * 60 + min * 60);
long long ms = milliseconds_ % Second.milliseconds_;
if (milliseconds_ < 0)
String result;
long total_ms = milliseconds_;
if (total_ms < 0)
{
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)
{
result.append(std::to_wstring(hour)).append(L"h");
result.append(std::to_wstring(min)).append(L"m");
result.append(easy2d::to_wstring(hour)).append(L"h");
result.append(easy2d::to_wstring(min)).append(L"m");
}
else if(min)
{
result.append(std::to_wstring(min)).append(L"m");
result.append(easy2d::to_wstring(min)).append(L"m");
}
if (ms != 0)
@ -162,7 +183,7 @@ namespace easy2d
}
else if (sec != 0)
{
result.append(std::to_wstring(sec)).append(L"s");
result.append(easy2d::to_wstring(sec)).append(L"s");
}
return result;
}
@ -340,51 +361,16 @@ namespace easy2d
return dur * val;
}
std::wostream & easy2d::time::operator<<(std::wostream & out, const Duration & dur)
{
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)
Duration Duration::Parse(const String& str)
{
size_t len = str.length();
size_t pos = 0;
bool negative = false;
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();
}
@ -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;
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();
}
@ -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;
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();
}
double num = std::stod(num_str);
double num = std::wcstod(num_str.c_str(), nullptr);
Duration unit = unit_map.at(unit_str);
d += unit * num;
}

View File

@ -20,6 +20,9 @@
#pragma once
#include "../macros.h"
#include "../common/String.h"
#include <ostream>
#include <istream>
namespace easy2d
{
@ -28,9 +31,9 @@ namespace easy2d
// 时间段
//
// 时间段表示法:
// 5 秒: time::Second * 5
// 5 秒: time::Sec * 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:
// 5 秒: 5_s
// 1.5 小时: 1.5_h
@ -60,7 +63,7 @@ namespace easy2d
inline bool IsZero() const { return milliseconds_ == 0LL; }
// 转为字符串
std::wstring ToString() const;
String ToString() const;
inline operator bool() const { return !IsZero(); }
@ -102,60 +105,75 @@ namespace easy2d
friend const Duration operator/ (float, const Duration &);
friend const Duration operator/ (double, const Duration &);
friend std::wostream& operator<< (std::wostream &, const Duration &);
friend std::wistream& operator>> (std::wistream &, Duration &);
public:
// 时间段格式化
//
// 时间段字符串允许是有符号的浮点数, 并且带有时间单位后缀
// 例如: "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:
long milliseconds_;
};
/* 预定义的时间段 */
E2D_API extern const Duration Millisecond; // 毫秒
E2D_API extern const Duration Second; // 秒
E2D_API extern const Duration Minute; // 分钟
E2D_API extern const Duration Hour; // 小时
E2D_API extern const Duration Ms; // 毫秒
E2D_API extern const Duration Sec; // 秒
E2D_API extern const Duration Min; // 分钟
E2D_API extern const Duration Hour; // 小时
// 时间
//
// 获取当前时间: TimePoint now = time::Now();
// 获取当前时间: Time now = Time::Now();
// 两时间相减, 得到一个 Duration 对象, 例如:
// TimePoint t1, t2;
// Time t1, t2;
// 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; }
const TimePoint operator + (const Duration &) const;
const TimePoint operator - (const Duration &) const;
const Time operator + (const Duration &) const;
const Time operator - (const Duration &) const;
TimePoint& operator += (const Duration &);
TimePoint& operator -= (const Duration &);
Time& 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:
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)
{
return easy2d::time::Millisecond * val;
return easy2d::time::Ms * 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)
{
return easy2d::time::Minute * val;
return easy2d::time::Min * 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)
{
return easy2d::time::Millisecond * val;
return easy2d::time::Ms * 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)
{
return easy2d::time::Minute * val;
return easy2d::time::Min * 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_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
//
@ -1236,6 +1239,21 @@ namespace easy2d
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
//

View File

@ -328,9 +328,9 @@ namespace easy2d
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_;
last = now;

View File

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

View File

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

View File

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