Update Logger & Timer

This commit is contained in:
Nomango 2019-12-25 18:07:57 +08:00
parent 5ba5e4525c
commit 11c43a0731
32 changed files with 725 additions and 498 deletions

View File

@ -38,7 +38,7 @@
<ClInclude Include="..\..\src\kiwano\core\keys.h" /> <ClInclude Include="..\..\src\kiwano\core\keys.h" />
<ClInclude Include="..\..\src\kiwano\core\Logger.h" /> <ClInclude Include="..\..\src\kiwano\core\Logger.h" />
<ClInclude Include="..\..\src\kiwano\core\ObjectBase.h" /> <ClInclude Include="..\..\src\kiwano\core\ObjectBase.h" />
<ClInclude Include="..\..\src\kiwano\core\RefCounter.hpp" /> <ClInclude Include="..\..\src\kiwano\core\RefCounter.h" />
<ClInclude Include="..\..\src\kiwano\core\Resource.h" /> <ClInclude Include="..\..\src\kiwano\core\Resource.h" />
<ClInclude Include="..\..\src\kiwano\core\SmartPtr.hpp" /> <ClInclude Include="..\..\src\kiwano\core\SmartPtr.hpp" />
<ClInclude Include="..\..\src\kiwano\core\Timer.h" /> <ClInclude Include="..\..\src\kiwano\core\Timer.h" />
@ -112,6 +112,7 @@
<ClCompile Include="..\..\src\kiwano\core\Library.cpp" /> <ClCompile Include="..\..\src\kiwano\core\Library.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Logger.cpp" /> <ClCompile Include="..\..\src\kiwano\core\Logger.cpp" />
<ClCompile Include="..\..\src\kiwano\core\ObjectBase.cpp" /> <ClCompile Include="..\..\src\kiwano\core\ObjectBase.cpp" />
<ClCompile Include="..\..\src\kiwano\core\RefCounter.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Resource.cpp" /> <ClCompile Include="..\..\src\kiwano\core\Resource.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Timer.cpp" /> <ClCompile Include="..\..\src\kiwano\core\Timer.cpp" />
<ClCompile Include="..\..\src\kiwano\core\TimerManager.cpp" /> <ClCompile Include="..\..\src\kiwano\core\TimerManager.cpp" />

View File

@ -63,9 +63,6 @@
<ClInclude Include="..\..\src\kiwano\core\EventListener.h"> <ClInclude Include="..\..\src\kiwano\core\EventListener.h">
<Filter>core</Filter> <Filter>core</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\core\RefCounter.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\core\Resource.h"> <ClInclude Include="..\..\src\kiwano\core\Resource.h">
<Filter>core</Filter> <Filter>core</Filter>
</ClInclude> </ClInclude>
@ -270,6 +267,9 @@
<ClInclude Include="..\..\src\kiwano\core\common.h"> <ClInclude Include="..\..\src\kiwano\core\common.h">
<Filter>core</Filter> <Filter>core</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\core\RefCounter.h">
<Filter>core</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\src\kiwano\ui\Button.cpp"> <ClCompile Include="..\..\src\kiwano\ui\Button.cpp">
@ -452,5 +452,8 @@
<ClCompile Include="..\..\src\kiwano\2d\TextActor.cpp"> <ClCompile Include="..\..\src\kiwano\2d\TextActor.cpp">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\core\RefCounter.cpp">
<Filter>core</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -38,7 +38,7 @@ namespace kiwano
void AudioEngine::SetupComponent() void AudioEngine::SetupComponent()
{ {
// KGE_LOG(L"Creating audio resources"); // KGE_SYS_LOG(L"Creating audio resources");
HRESULT hr = modules::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL); HRESULT hr = modules::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL);
@ -57,7 +57,7 @@ namespace kiwano
void AudioEngine::DestroyComponent() void AudioEngine::DestroyComponent()
{ {
// KGE_LOG(L"Destroying audio resources"); // KGE_SYS_LOG(L"Destroying audio resources");
if (mastering_voice_) if (mastering_voice_)
{ {

View File

@ -78,7 +78,7 @@ namespace kiwano
} }
else else
{ {
KGE_LOG(L"Load Mfplat.dll failed"); KGE_SYS_LOG(L"Load Mfplat.dll failed");
throw std::runtime_error("Load Mfplat.dll failed"); throw std::runtime_error("Load Mfplat.dll failed");
} }
@ -89,7 +89,7 @@ namespace kiwano
} }
else else
{ {
KGE_LOG(L"Load Mfreadwrite.dll failed"); KGE_SYS_LOG(L"Load Mfreadwrite.dll failed");
throw std::runtime_error("Load Mfreadwrite.dll failed"); throw std::runtime_error("Load Mfreadwrite.dll failed");
} }
} }

View File

@ -103,7 +103,7 @@ namespace kiwano
#if defined(KGE_DEBUG) #if defined(KGE_DEBUG)
if (ObjectBase::IsTracingLeaks()) if (ObjectBase::IsTracingLeaks())
{ {
ss << "Objects: " << ObjectBase::__GetTracingObjects().size() << std::endl; ss << "Objects: " << ObjectBase::GetTracingObjects().size() << std::endl;
} }
#endif #endif

View File

@ -43,7 +43,7 @@ namespace kiwano
public: public:
/// \~chinese /// \~chinese
/// @brief GIF²¥·ÅÑ­»·½áÊø»Øµ÷ /// @brief GIF²¥·ÅÑ­»·½áÊø»Øµ÷
using LoopDoneCallback = Function<void(int)>; using LoopDoneCallback = Function<void(int /* times */)>;
/// \~chinese /// \~chinese
/// @brief GIF²¥·Å½áÊø»Øµ÷ /// @brief GIF²¥·Å½áÊø»Øµ÷

View File

@ -38,12 +38,12 @@ namespace kiwano
void Stage::OnEnter() void Stage::OnEnter()
{ {
// KGE_LOG(L"Stage entered"); // KGE_SYS_LOG(L"Stage entered");
} }
void Stage::OnExit() void Stage::OnExit()
{ {
// KGE_LOG(L"Stage exited"); // KGE_SYS_LOG(L"Stage exited");
} }
} }

View File

@ -47,6 +47,8 @@ namespace kiwano
void Action::UpdateStep(Actor* target, Duration dt) void Action::UpdateStep(Actor* target, Duration dt)
{ {
KGE_ASSERT(target != nullptr && "Action target should NOT be nullptr!");
elapsed_ += dt; elapsed_ += dt;
if (status_ == Status::NotStarted) if (status_ == Status::NotStarted)
@ -72,7 +74,7 @@ namespace kiwano
if (status_ == Status::Done) if (status_ == Status::Done)
{ {
if (cb_done_) if (cb_done_)
cb_done_(); cb_done_(target);
if (detach_target_) if (detach_target_)
target->RemoveFromParent(); target->RemoveFromParent();
@ -84,7 +86,7 @@ namespace kiwano
void Action::Complete(Actor* target) void Action::Complete(Actor* target)
{ {
if (cb_loop_done_) if (cb_loop_done_)
cb_loop_done_(); cb_loop_done_(target);
if (loops_ >= 0 if (loops_ >= 0
&& loops_done_ >= loops_) && loops_done_ >= loops_)

View File

@ -55,7 +55,7 @@ namespace kiwano
public: public:
/// \~chinese /// \~chinese
/// @brief 动画结束时的回调函数 /// @brief 动画结束时的回调函数
using DoneCallback = Function<void()>; using DoneCallback = Function<void(Actor* /* target */)>;
Action(); Action();

View File

@ -28,39 +28,47 @@ namespace kiwano
* @{ * @{
*/ */
/**
* \~chinese
* @brief
*/
class KGE_API ActionManager class KGE_API ActionManager
{ {
public:
using Actions = IntrusiveList<ActionPtr>; using Actions = IntrusiveList<ActionPtr>;
public: /// \~chinese
// 添加动画 /// @brief 添加动画
Action* AddAction( Action* AddAction(ActionPtr action);
ActionPtr action
);
// 添加动画 /// \~chinese
Action* AddAction( /// @brief 添加动画
Action* action Action* AddAction(Action* action);
);
// 获取动画 /// \~chinese
Action* GetAction( /// @brief 获取指定名称的动画
String const& name /// @param name 动画名称
); Action* GetAction(String const& name);
// 继续所有暂停动画 /// \~chinese
/// @brief 继续所有暂停动画
void ResumeAllActions(); void ResumeAllActions();
// 暂停所有动画 /// \~chinese
/// @brief 暂停所有动画
void PauseAllActions(); void PauseAllActions();
// 停止所有动画 /// \~chinese
/// @brief 停止所有动画
void StopAllActions(); void StopAllActions();
// 获取所有动画 /// \~chinese
/// @brief 获取所有动画
Actions const& GetAllActions() const; Actions const& GetAllActions() const;
protected: protected:
/// \~chinese
/// @brief 更新动画
void UpdateActions(Actor* target, Duration dt); void UpdateActions(Actor* target, Duration dt);
private: private:

View File

@ -18,6 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <functional>
#include <kiwano/2d/action/ActionTween.h> #include <kiwano/2d/action/ActionTween.h>
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>

View File

@ -475,7 +475,7 @@ namespace kiwano
/// \~chinese /// \~chinese
/// @brief 动画回调函数 /// @brief 动画回调函数
/// @details 在动画更新时回调该函数第一个参数是执行动画的目标第二个参数是动画进度0.0 - 1.0 /// @details 在动画更新时回调该函数第一个参数是执行动画的目标第二个参数是动画进度0.0 - 1.0
using TweenFunc = Function<void(Actor*, float)>; using TweenFunc = Function<void(Actor* /* target */, float /* percent */)>;
/// \~chinese /// \~chinese
/// @brief 构造自定义动画 /// @brief 构造自定义动画

View File

@ -9,7 +9,7 @@
//#define KGE_ASSERT(EXPR) __noop // Disable asserts //#define KGE_ASSERT(EXPR) __noop // Disable asserts
//---- Define debug-output handler. Defaults to calling kiwano::logs::Messageln()/Warningln()/Errorln() //---- Define debug-output handler. Defaults to calling kiwano::logs::Messageln()/Warningln()/Errorln()
//#define KGE_LOG(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__) //#define KGE_SYS_LOG(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__)
//#define KGE_WARN(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__) //#define KGE_WARN(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__)
//#define KGE_ERROR(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__) //#define KGE_ERROR(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__)

View File

@ -122,7 +122,7 @@ namespace kiwano
virtual void HandleEvent(Event& evt) {} virtual void HandleEvent(Event& evt) {}
/// \~chinese /// \~chinese
/// @brief Windows 消息处理 /// @brief 处理 Windows 消息
virtual void HandleMessage(HWND, UINT32, WPARAM, LPARAM) {} virtual void HandleMessage(HWND, UINT32, WPARAM, LPARAM) {}
public: public:

View File

@ -104,7 +104,7 @@ namespace kiwano
> >
inline const _Ty& Cast() const inline const _Ty& Cast() const
{ {
return *dynamic_cast<const _Ty*>(this); return dynamic_cast<const _Ty&>(*this);
} }
/// \~chinese /// \~chinese
@ -116,7 +116,7 @@ namespace kiwano
> >
inline _Ty& Cast() inline _Ty& Cast()
{ {
return *dynamic_cast<_Ty*>(this); return dynamic_cast<_Ty&>(*this);
} }
/// \~chinese /// \~chinese

View File

@ -20,6 +20,7 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <ctime>
#include <kiwano/core/Logger.h> #include <kiwano/core/Logger.h>
@ -109,25 +110,29 @@ namespace
namespace kiwano namespace kiwano
{ {
namespace __console_colors namespace console_colors
{ {
const WORD _blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY; const WORD blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
const WORD _green = FOREGROUND_GREEN | FOREGROUND_INTENSITY; const WORD green = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
const WORD _red = FOREGROUND_RED | FOREGROUND_INTENSITY; const WORD red = FOREGROUND_RED | FOREGROUND_INTENSITY;
const WORD _yellow = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; const WORD yellow = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
const WORD _white = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; const WORD white = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
const WORD _blue_bg = _white | BACKGROUND_BLUE | BACKGROUND_INTENSITY; const WORD blue_bg = white | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
const WORD _green_bg = _white | BACKGROUND_GREEN | BACKGROUND_INTENSITY; const WORD green_bg = white | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
const WORD _red_bg = _white | BACKGROUND_RED | BACKGROUND_INTENSITY; const WORD red_bg = white | BACKGROUND_RED | BACKGROUND_INTENSITY;
const WORD _yellow_bg = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; const WORD yellow_bg = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
const WORD _white_bg = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; const WORD white_bg = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
const WORD _reset = _white; const WORD reset = white;
}
#define DECLARE_HANDLE_COLOR(NAME, HANDLE_NAME, COLOR)\ #define DECLARE_HANDLE_COLOR(NAME, HANDLE_NAME, COLOR)\
inline std::wostream& (NAME)(std::wostream& _out)\ inline std::wostream& (NAME)(std::wostream& _out)\
{ ::SetConsoleTextAttribute(::GetStdHandle(HANDLE_NAME), _##COLOR); return _out; } {\
::SetConsoleTextAttribute(::GetStdHandle(HANDLE_NAME), console_colors::##COLOR);\
return _out;\
}
#define DECLARE_COLOR(COLOR) \ #define DECLARE_COLOR(COLOR) \
DECLARE_HANDLE_COLOR(stdout_##COLOR, STD_OUTPUT_HANDLE, COLOR)\ DECLARE_HANDLE_COLOR(stdout_##COLOR, STD_OUTPUT_HANDLE, COLOR)\
@ -137,6 +142,8 @@ namespace kiwano
DECLARE_HANDLE_COLOR(stdout_##COLOR##_bg, STD_OUTPUT_HANDLE, COLOR##_bg)\ DECLARE_HANDLE_COLOR(stdout_##COLOR##_bg, STD_OUTPUT_HANDLE, COLOR##_bg)\
DECLARE_HANDLE_COLOR(stderr_##COLOR##_bg, STD_ERROR_HANDLE, COLOR##_bg) DECLARE_HANDLE_COLOR(stderr_##COLOR##_bg, STD_ERROR_HANDLE, COLOR##_bg)
namespace console_colors
{
DECLARE_COLOR(red); DECLARE_COLOR(red);
DECLARE_COLOR(green); DECLARE_COLOR(green);
DECLARE_COLOR(yellow); DECLARE_COLOR(yellow);
@ -149,9 +156,6 @@ namespace kiwano
DECLARE_BG_COLOR(yellow); DECLARE_BG_COLOR(yellow);
DECLARE_BG_COLOR(blue); DECLARE_BG_COLOR(blue);
DECLARE_BG_COLOR(white); DECLARE_BG_COLOR(white);
#undef DECLARE_COLOR
#undef DECLARE_BG_COLOR
} }
Logger::Logger() Logger::Logger()
@ -169,6 +173,98 @@ namespace kiwano
FreeAllocatedConsole(); FreeAllocatedConsole();
} }
void Logger::Printf(Level level, const wchar_t* format, ...)
{
if (!enabled_)
return;
StringStream sstream;
Prepare(level, sstream);
// Format message
if (format)
{
va_list args = nullptr;
va_start(args, format);
static wchar_t temp_buffer[1024 * 3 + 1];
const auto len = ::_vscwprintf(format, args) + 1;
::_vsnwprintf_s(temp_buffer, len, len, format, args);
sstream << ' ' << temp_buffer << L"\r\n";
va_end(args);
}
Output(level, sstream);
}
void Logger::Prepare(Level level, StringStream& sstream)
{
String prompt;
switch (level)
{
case Level::Info:
prompt = L"[INFO] ";
break;
case Level::System:
prompt = L"[SYSTEM] ";
break;
case Level::Warning:
prompt = L"[WARNING] ";
break;
case Level::Error:
prompt = L"[ERROR] ";
break;
}
// Prefix
sstream << L"[KIWANO] " << prompt;
// Timestamp
time_t unix = std::time(nullptr);
std::tm tmbuf;
localtime_s(&tmbuf, &unix);
sstream << std::put_time(&tmbuf, L"%H:%M:%S ");
}
void Logger::Output(Level level, StringStream& sstream)
{
OutputStream* ostream = nullptr;
ConsoleColor color = nullptr;
switch (level)
{
case Level::Info:
ostream = &output_stream_;
color = Closure(this, &Logger::DefaultOutputColor);
break;
case Level::System:
ostream = &output_stream_;
color = console_colors::stdout_blue;
break;
case Level::Warning:
ostream = &output_stream_;
color = console_colors::stdout_yellow_bg;
break;
case Level::Error:
ostream = &error_stream_;
color = console_colors::stderr_red_bg;
break;
}
// Printing
if (ostream)
{
auto output = sstream.str();
color(*ostream) << output << std::flush;
::OutputDebugStringW(output.c_str());
ResetConsoleColor();
}
}
void Logger::ResetOutputStream() void Logger::ResetOutputStream()
{ {
bool has_console = ::GetConsoleWindow() != nullptr; bool has_console = ::GetConsoleWindow() != nullptr;
@ -208,96 +304,6 @@ namespace kiwano
return error_stream_.rdbuf(buf); return error_stream_.rdbuf(buf);
} }
void Logger::Printf(const wchar_t* format, ...)
{
va_list args = nullptr;
va_start(args, format);
Outputf(output_stream_, Logger::DefaultOutputColor, nullptr, format, args);
va_end(args);
}
void Logger::Messagef(const wchar_t* format, ...)
{
using namespace __console_colors;
va_list args = nullptr;
va_start(args, format);
Outputf(output_stream_, stdout_blue, nullptr, format, args);
va_end(args);
}
void Logger::Warningf(const wchar_t* format, ...)
{
using namespace __console_colors;
va_list args = nullptr;
va_start(args, format);
Outputf(output_stream_, stdout_yellow_bg, L" Warning:", format, args);
va_end(args);
}
void Logger::Errorf(const wchar_t* format, ...)
{
using namespace __console_colors;
va_list args = nullptr;
va_start(args, format);
Outputf(error_stream_, stderr_red_bg, L" Error:", format, args);
va_end(args);
}
void Logger::Outputf(std::wostream& os, std::wostream& (*color)(std::wostream&), const wchar_t* prompt, const wchar_t* format, va_list args) const
{
if (enabled_)
{
std::wstring output = MakeOutputStringf(prompt, format, args);
os << color << output << std::flush;
::OutputDebugStringW(output.c_str());
ResetConsoleColor();
}
}
std::wstring Logger::MakeOutputStringf(const wchar_t* prompt, const wchar_t* format, va_list args) const
{
static wchar_t temp_buffer[1024 * 3 + 1];
StringStream ss;
ss << Logger::OutPrefix;
if (prompt)
ss << prompt;
if (format)
{
const auto len = ::_vscwprintf(format, args) + 1;
::_vsnwprintf_s(temp_buffer, len, len, format, args);
ss << ' ' << temp_buffer;
}
return ss.str();
}
std::wostream& Logger::OutPrefix(std::wostream& out)
{
out << L"[KIWANO] ";
time_t unix = std::time(nullptr);
std::tm tmbuf;
localtime_s(&tmbuf, &unix);
out << std::put_time(&tmbuf, L"%H:%M:%S");
return out;
}
void Logger::ShowConsole(bool show) void Logger::ShowConsole(bool show)
{ {
HWND current_console = ::GetConsoleWindow(); HWND current_console = ::GetConsoleWindow();

View File

@ -19,94 +19,115 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <ctime>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <kiwano/macros.h> #include <kiwano/macros.h>
#include <kiwano/core/common.h> #include <kiwano/core/common.h>
#ifndef KGE_LOG #ifndef KGE_SYS_LOG
# ifdef KGE_DEBUG # ifdef KGE_DEBUG
# define KGE_LOG(FORMAT, ...) ::kiwano::Logger::instance().Messagef((FORMAT ## "\n"), __VA_ARGS__) # define KGE_SYS_LOG(FORMAT, ...) ::kiwano::Logger::instance().Printf(::kiwano::Logger::Level::System, FORMAT, __VA_ARGS__)
# else # else
# define KGE_LOG __noop # define KGE_SYS_LOG __noop
# endif # endif
#endif #endif
#ifndef KGE_WARN #ifndef KGE_WARN
# define KGE_WARN(FORMAT, ...) ::kiwano::Logger::instance().Warningf((FORMAT ## "\n"), __VA_ARGS__) # define KGE_WARN(FORMAT, ...) ::kiwano::Logger::instance().Printf(::kiwano::Logger::Level::Warning, FORMAT, __VA_ARGS__)
#endif #endif
#ifndef KGE_ERROR #ifndef KGE_ERROR
# define KGE_ERROR(FORMAT, ...) ::kiwano::Logger::instance().Errorf((FORMAT ## "\n"), __VA_ARGS__) # define KGE_ERROR(FORMAT, ...) ::kiwano::Logger::instance().Printf(::kiwano::Logger::Level::Error, FORMAT, __VA_ARGS__)
#endif #endif
#ifndef KGE_PRINT #ifndef KGE_LOG
# define KGE_PRINT(...) ::kiwano::Logger::instance().Println(__VA_ARGS__) # define KGE_LOG(...) ::kiwano::Logger::instance().Println(::kiwano::Logger::Level::Info, __VA_ARGS__)
#endif #endif
#ifndef KGE_PRINTF #ifndef KGE_LOGF
# define KGE_PRINTF(FORMAT, ...) ::kiwano::Logger::instance().Printf((FORMAT), __VA_ARGS__) # define KGE_LOGF(FORMAT, ...) ::kiwano::Logger::instance().Printf(::kiwano::Logger::Level::Info, FORMAT, __VA_ARGS__)
#endif #endif
namespace kiwano namespace kiwano
{ {
/**
* \~chinese
* @brief
*/
class KGE_API Logger class KGE_API Logger
: public Singleton<Logger> : public Singleton<Logger>
{ {
friend Singleton<Logger>; friend Singleton<Logger>;
public: public:
// 显示或关闭控制台 /// \~chinese
/// @brief 日志级别
enum class Level
{
Info, ///< 信息
System, ///< 系统
Warning, ///< 警告
Error ///< 错误
};
/// \~chinese
/// @brief 输出流
using OutputStream = std::wostream;
/// \~chinese
/// @brief 控制台颜色
using ConsoleColor = Function<OutputStream& (OutputStream&)>;
/// \~chinese
/// @brief 显示或关闭控制台
void ShowConsole(bool show); void ShowConsole(bool show);
// 启用 Logger /// \~chinese
/// @brief 启用日志
void Enable(); void Enable();
// 禁用 Logger /// \~chinese
/// @brief 禁用日志
void Disable(); void Disable();
void Printf(const wchar_t* format, ...); /// \~chinese
/// @brief 打印日志
void Messagef(const wchar_t * format, ...); /// @param level 日志级别
/// @param format 格式字符串
void Warningf(const wchar_t* format, ...); void Printf(Level level, const wchar_t* format, ...);
void Errorf(const wchar_t* format, ...);
/// \~chinese
/// @brief 打印日志
/// @param level 日志级别
/// @param args 参数
template <typename ..._Args> template <typename ..._Args>
void Print(_Args&& ... args); void Print(Level level, _Args&& ... args);
/// \~chinese
/// @brief 打印一行日志
/// @param level 日志级别
/// @param args 参数
template <typename ..._Args> template <typename ..._Args>
void Println(_Args&& ... args); void Println(Level level, _Args&& ... args);
template <typename ..._Args>
void Message(_Args&& ... args);
template <typename ..._Args>
void Messageln(_Args&& ... args);
template <typename ..._Args>
void Warning(_Args&& ... args);
template <typename ..._Args>
void Warningln(_Args&& ... args);
template <typename ..._Args>
void Error(_Args&& ... args);
template <typename ..._Args>
void Errorln(_Args&& ... args);
/// \~chinese
/// @brief 获取输出流
std::wostream& GetOutputStream(); std::wostream& GetOutputStream();
/// \~chinese
/// @brief 获取错误流
std::wostream& GetErrorStream(); std::wostream& GetErrorStream();
/// \~chinese
/// @brief 重定向输出流
std::wstreambuf* RedirectOutputStreamBuffer(std::wstreambuf* buf); std::wstreambuf* RedirectOutputStreamBuffer(std::wstreambuf* buf);
/// \~chinese
/// @brief 重定向错误流
std::wstreambuf* RedirectErrorStreamBuffer(std::wstreambuf* buf); std::wstreambuf* RedirectErrorStreamBuffer(std::wstreambuf* buf);
/// \~chinese
/// @brief 重置输出流
void ResetOutputStream(); void ResetOutputStream();
private: private:
@ -114,76 +135,24 @@ namespace kiwano
~Logger(); ~Logger();
// void Prepare(Level level, StringStream& sstream);
// output functions
//
void Outputf(std::wostream& os, std::wostream&(*color)(std::wostream&), const wchar_t* prompt, const wchar_t* format, va_list args) const;
template <typename ..._Args> void Output(Level level, StringStream& sstream);
void OutputLine(std::wostream& os, std::wostream& (*color)(std::wostream&), const wchar_t* prompt, _Args&& ... args) const;
template <typename ..._Args>
void Output(std::wostream& os, std::wostream& (*color)(std::wostream&), const wchar_t* prompt, _Args&& ... args) const;
static std::wostream& OutPrefix(std::wostream& out);
//
// make string
//
std::wstring MakeOutputStringf(const wchar_t* prompt, const wchar_t* format, va_list args) const;
template <typename ..._Args>
std::wstring MakeOutputString(const wchar_t* prompt, _Args&& ... args) const;
//
// reset functions
//
void ResetConsoleColor() const; void ResetConsoleColor() const;
static std::wostream& DefaultOutputColor(std::wostream& out); OutputStream& DefaultOutputColor(OutputStream& out);
private: private:
bool enabled_; bool enabled_;
WORD default_stdout_color_; WORD default_stdout_color_;
WORD default_stderr_color_; WORD default_stderr_color_;
std::wostream output_stream_; OutputStream output_stream_;
std::wostream error_stream_; OutputStream error_stream_;
}; };
//
// details of Logger
//
namespace __console_colors
{
#define DECLARE_COLOR(COLOR)\
extern std::wostream&(stdout_##COLOR)(std::wostream&);\
extern std::wostream&(stderr_##COLOR)(std::wostream&);
#define DECLARE_BG_COLOR(COLOR)\
extern std::wostream&(stdout_##COLOR##_bg)(std::wostream&);\
extern std::wostream&(stderr_##COLOR##_bg)(std::wostream&);
DECLARE_COLOR(red);
DECLARE_COLOR(green);
DECLARE_COLOR(yellow);
DECLARE_COLOR(blue);
DECLARE_COLOR(white);
DECLARE_COLOR(reset);
DECLARE_BG_COLOR(red);
DECLARE_BG_COLOR(green);
DECLARE_BG_COLOR(yellow);
DECLARE_BG_COLOR(blue);
DECLARE_BG_COLOR(white);
#undef DECLARE_COLOR
#undef DECLARE_BG_COLOR
}
inline void Logger::Enable() inline void Logger::Enable()
{ {
enabled_ = true; enabled_ = true;
@ -195,97 +164,35 @@ namespace kiwano
} }
template <typename ..._Args> template <typename ..._Args>
inline void Logger::Print(_Args&& ... args) void Logger::Print(Level level, _Args&& ... args)
{ {
Output(output_stream_, Logger::DefaultOutputColor, nullptr, std::forward<_Args>(args)...); if (!enabled_)
return;
StringStream sstream;
Prepare(level, sstream);
// Format message
(void)std::initializer_list<int>{((sstream << ' ' << args), 0)...};
Output(level, sstream);
} }
template <typename ..._Args> template <typename ..._Args>
inline void Logger::Println(_Args&& ... args) void Logger::Println(Level level, _Args&& ... args)
{ {
OutputLine(output_stream_, Logger::DefaultOutputColor, nullptr, std::forward<_Args>(args)...); if (!enabled_)
} return;
template <typename ..._Args> StringStream sstream;
inline void Logger::Message(_Args&& ... args) Prepare(level, sstream);
{
using namespace __console_colors;
Output(output_stream_, stdout_blue, nullptr, std::forward<_Args>(args)...);
}
template <typename ..._Args> // Format message
inline void Logger::Messageln(_Args&& ... args) (void)std::initializer_list<int>{((sstream << ' ' << args), 0)...};
{
using namespace __console_colors;
OutputLine(output_stream_, stdout_blue, nullptr, std::forward<_Args>(args)...);
}
template <typename ..._Args> sstream << L"\r\n";
inline void Logger::Warning(_Args&& ... args)
{
using namespace __console_colors;
Output(output_stream_, stdout_yellow_bg, L"Warning:", std::forward<_Args>(args)...);
}
template <typename ..._Args> Output(level, sstream);
inline void Logger::Warningln(_Args&& ... args)
{
using namespace __console_colors;
OutputLine(output_stream_, stdout_yellow_bg, L"Warning:", std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::Error(_Args&& ... args)
{
using namespace __console_colors;
Output(error_stream_, stderr_red_bg, L"Error:", std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::Errorln(_Args&& ... args)
{
using namespace __console_colors;
OutputLine(error_stream_, stderr_red_bg, L"Error:", std::forward<_Args>(args)...);
}
template <typename ..._Args>
void Logger::OutputLine(std::wostream& os, std::wostream& (*color)(std::wostream&), const wchar_t* prompt, _Args&& ... args) const
{
if (enabled_)
{
Output(os, color, prompt, std::forward<_Args>(args)...);
os << std::endl;
::OutputDebugStringW(L"\r\n");
}
}
template <typename ..._Args>
void Logger::Output(std::wostream& os, std::wostream& (*color)(std::wostream&), const wchar_t* prompt, _Args&& ... args) const
{
if (enabled_)
{
std::wstring output = MakeOutputString(prompt, std::forward<_Args>(args)...);
os << color << output << std::flush;
::OutputDebugStringW(output.c_str());
ResetConsoleColor();
}
}
template <typename ..._Args>
std::wstring Logger::MakeOutputString(const wchar_t* prompt, _Args&& ... args) const
{
StringStream ss;
ss << Logger::OutPrefix;
if (prompt)
ss << prompt;
(void)std::initializer_list<int>{((ss << ' ' << args), 0)...};
return ss.str();
} }
inline void Logger::ResetConsoleColor() const inline void Logger::ResetConsoleColor() const
@ -294,9 +201,9 @@ namespace kiwano
::SetConsoleTextAttribute(::GetStdHandle(STD_ERROR_HANDLE), default_stderr_color_); ::SetConsoleTextAttribute(::GetStdHandle(STD_ERROR_HANDLE), default_stderr_color_);
} }
inline std::wostream& Logger::DefaultOutputColor(std::wostream& out) inline Logger::OutputStream& Logger::DefaultOutputColor(OutputStream& out)
{ {
::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), Logger::instance().default_stdout_color_); ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), default_stdout_color_);
return out; return out;
} }

View File

@ -28,32 +28,30 @@ namespace kiwano
{ {
bool tracing_leaks = false; bool tracing_leaks = false;
Vector<ObjectBase*> tracing_objects; Vector<ObjectBase*> tracing_objects;
uint32_t last_object_id = 0;
} }
uint32_t ObjectBase::last_object_id = 0;
ObjectBase::ObjectBase() ObjectBase::ObjectBase()
: tracing_leak_(false) : tracing_leak_(false)
, user_data_(nullptr) , user_data_()
, name_(nullptr) , name_(nullptr)
, id_(++last_object_id) , id_(++last_object_id)
{ {
#ifdef KGE_DEBUG #ifdef KGE_DEBUG
ObjectBase::AddObjectToTracingList(this);
ObjectBase::__AddObjectToTracingList(this);
#endif #endif
} }
ObjectBase::~ObjectBase() ObjectBase::~ObjectBase()
{ {
if (name_) if (name_)
{
delete name_; delete name_;
name_ = nullptr;
}
#ifdef KGE_DEBUG #ifdef KGE_DEBUG
ObjectBase::RemoveObjectFromTracingList(this);
ObjectBase::__RemoveObjectFromTracingList(this);
#endif #endif
} }
@ -112,36 +110,33 @@ namespace kiwano
void ObjectBase::DumpTracingObjects() void ObjectBase::DumpTracingObjects()
{ {
KGE_LOG(L"-------------------------- All Objects --------------------------"); KGE_SYS_LOG(L"-------------------------- All Objects --------------------------");
for (const auto object : tracing_objects) for (const auto object : tracing_objects)
{ {
KGE_LOG(L"%s", object->DumpObject().c_str()); KGE_SYS_LOG(L"%s", object->DumpObject().c_str());
} }
KGE_LOG(L"------------------------- Total size: %d -------------------------", tracing_objects.size()); KGE_SYS_LOG(L"------------------------- Total size: %d -------------------------", tracing_objects.size());
} }
Vector<ObjectBase*>& kiwano::ObjectBase::__GetTracingObjects() Vector<ObjectBase*>& ObjectBase::GetTracingObjects()
{ {
return tracing_objects; return tracing_objects;
} }
void ObjectBase::__AddObjectToTracingList(ObjectBase * obj) void ObjectBase::AddObjectToTracingList(ObjectBase * obj)
{ {
#ifdef KGE_DEBUG #ifdef KGE_DEBUG
if (tracing_leaks && !obj->tracing_leak_) if (tracing_leaks && !obj->tracing_leak_)
{ {
obj->tracing_leak_ = true; obj->tracing_leak_ = true;
tracing_objects.push_back(obj); tracing_objects.push_back(obj);
} }
#endif #endif
} }
void ObjectBase::__RemoveObjectFromTracingList(ObjectBase * obj) void ObjectBase::RemoveObjectFromTracingList(ObjectBase * obj)
{ {
#ifdef KGE_DEBUG #ifdef KGE_DEBUG
if (tracing_leaks && obj->tracing_leak_) if (tracing_leaks && obj->tracing_leak_)
{ {
obj->tracing_leak_ = false; obj->tracing_leak_ = false;
@ -152,7 +147,6 @@ namespace kiwano
tracing_objects.erase(iter); tracing_objects.erase(iter);
} }
} }
#endif #endif
} }

View File

@ -21,34 +21,55 @@
#pragma once #pragma once
#include <kiwano/macros.h> #include <kiwano/macros.h>
#include <kiwano/core/common.h> #include <kiwano/core/common.h>
#include <kiwano/core/RefCounter.hpp> #include <kiwano/core/RefCounter.h>
#include <kiwano/core/SmartPtr.hpp> #include <kiwano/core/SmartPtr.hpp>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(ObjectBase); KGE_DECLARE_SMART_PTR(ObjectBase);
/**
* \~chinese
* @brief
*/
class KGE_API ObjectBase class KGE_API ObjectBase
: public virtual RefCounter : public virtual RefCounter
{ {
public: public:
/// \~chinese
/// @brief 构造基础对象
ObjectBase(); ObjectBase();
virtual ~ObjectBase(); virtual ~ObjectBase();
const Any& GetUserData() const; /// \~chinese
/// @brief 设置对象名
void SetName(String const& name);
void SetUserData(Any const& data); /// \~chinese
/// @brief 获取对象名
String GetName() const;
void SetName(String const& name); /// \~chinese
/// @brief 判断对象的名称是否相同
/// @param name 需要判断的名称
bool IsName(String const& name) const;
String DumpObject(); /// \~chinese
/// @brief 获取用户数据
const Any& GetUserData() const;
inline String GetName() const { if (name_) return *name_; return String(); } /// \~chinese
/// @brief 设置用户数据
void SetUserData(Any const& data);
inline bool IsName(String const& name) const { return name_ ? (*name_ == name) : name.empty(); } /// \~chinese
/// @brief 获取对象ID
uint32_t GetObjectID() const;
inline uint32_t GetObjectID() const { return id_; } /// \~chinese
/// @brief 序列化对象
String DumpObject();
public: public:
static bool IsTracingLeaks(); static bool IsTracingLeaks();
@ -59,12 +80,12 @@ namespace kiwano
static void DumpTracingObjects(); static void DumpTracingObjects();
public: static Vector<ObjectBase*>& GetTracingObjects();
static Vector<ObjectBase*>& __GetTracingObjects();
static void __AddObjectToTracingList(ObjectBase*); private:
static void AddObjectToTracingList(ObjectBase*);
static void __RemoveObjectFromTracingList(ObjectBase*); static void RemoveObjectFromTracingList(ObjectBase*);
private: private:
bool tracing_leak_; bool tracing_leak_;
@ -72,6 +93,11 @@ namespace kiwano
String* name_; String* name_;
const uint32_t id_; const uint32_t id_;
static uint32_t last_object_id;
}; };
inline String ObjectBase::GetName() const { if (name_) return *name_; return String(); }
inline bool ObjectBase::IsName(String const& name) const { return name_ ? (*name_ == name) : name.empty(); }
inline uint32_t ObjectBase::GetObjectID() const { return id_; }
} }

View File

@ -0,0 +1,46 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <kiwano/core/RefCounter.h>
namespace kiwano
{
RefCounter::RefCounter()
: ref_count_(0)
{
}
RefCounter::~RefCounter()
{
}
void RefCounter::Retain()
{
++ref_count_;
}
void RefCounter::Release()
{
--ref_count_;
if (ref_count_ <= 0)
delete this;
}
}

View File

@ -24,29 +24,37 @@
namespace kiwano namespace kiwano
{ {
/**
* \~chinese
* @brief
*/
class KGE_API RefCounter class KGE_API RefCounter
: protected Noncopyable : protected Noncopyable
{ {
public: public:
// 增加引用计数 /// \~chinese
inline void Retain() { ++ref_count_; } /// @brief 增加引用计数
void Retain();
// 减少引用计数 /// \~chinese
inline void Release() /// @brief 减少引用计数
{ void Release();
if (--ref_count_ <= 0)
delete this;
}
// 获取引用计数 /// \~chinese
inline long GetRefCount() const { return ref_count_; } /// @brief 获取引用计数
long GetRefCount() const;
protected: protected:
RefCounter() : ref_count_(0) {} RefCounter();
virtual ~RefCounter() {} virtual ~RefCounter();
private: private:
long ref_count_; long ref_count_;
}; };
inline long RefCounter::GetRefCount() const
{
return ref_count_;
}
} }

View File

@ -29,7 +29,6 @@ namespace kiwano
: id_(0) : id_(0)
, type_(nullptr) , type_(nullptr)
{ {
} }
Resource::Resource(uint32_t id, const wchar_t* type) Resource::Resource(uint32_t id, const wchar_t* type)

View File

@ -24,41 +24,54 @@
namespace kiwano namespace kiwano
{ {
// 资源 /**
// * \~chinese
// 资源是保存在 exe 中的二进制数据 * @brief
// 例如, 一份音频资源的类型为 L"WAVE", 名称标识符为 IDR_WAVE_1, * @details
// 那么可以这样指定该资源: Resource(IDR_WAVE_1, L"WAVE"); * exe
// * L"WAVE" IDR_WAVE_1:
// 了解资源的更多信息: https://docs.microsoft.com/en-us/windows/desktop/menurc/resources * @code
// * Resource(IDR_WAVE_1, L"WAVE");
* @endcode
* : https://docs.microsoft.com/en-us/windows/desktop/menurc/resources
*/
class KGE_API Resource class KGE_API Resource
{ {
public: public:
// 二进制数据 /// \~chinese
/// @brief 资源的二进制数据
struct Data struct Data
{ {
void* buffer; void* buffer; ///< 资源数据
uint32_t size; uint32_t size; ///< 资源数据大小
inline Data() : buffer(nullptr), size(0) {} Data();
inline operator bool() const { return buffer && size; } operator bool() const;
}; };
/// \~chinese
/// @brief 构造资源
Resource(); Resource();
Resource( /// \~chinese
uint32_t id, /* 资源 ID */ /// @brief 构造资源
const wchar_t* type /* 资源类型 */ /// @param id 资源 ID
); /// @param type 资源类型
Resource(uint32_t id, const wchar_t* type);
// 获取二进制数据 /// \~chinese
Resource::Data GetData() const; /// @brief 获取资源的二进制数据
/// @return 资源数据
Resource::Data GetData() const;
inline uint32_t GetId() const { return id_; } /// \~chinese
/// @brief 获取资源 ID
uint32_t GetId() const;
inline const wchar_t* GetType() const { return type_; } /// \~chinese
/// @brief 获取资源类型
const wchar_t* GetType() const;
private: private:
uint32_t id_; uint32_t id_;
@ -66,4 +79,25 @@ namespace kiwano
mutable Resource::Data data_; mutable Resource::Data data_;
}; };
inline Resource::Data::Data()
: buffer(nullptr)
, size(0)
{
}
inline Resource::Data::operator bool() const
{
return buffer != nullptr && size;
}
inline uint32_t Resource::GetId() const
{
return id_;
}
inline const wchar_t* Resource::GetType() const
{
return type_;
}
} }

View File

@ -20,11 +20,15 @@
#pragma once #pragma once
#include <kiwano/core/common.h> #include <kiwano/core/common.h>
#include <kiwano/core/RefCounter.hpp> #include <kiwano/core/RefCounter.h>
namespace kiwano namespace kiwano
{ {
struct DefaultIntrusivePtrProxy /**
* \~chinese
* @brief
*/
struct DefaultSmartPtrRefProxy
{ {
static inline void add_ref(RefCounter* ptr) static inline void add_ref(RefCounter* ptr)
{ {
@ -37,13 +41,17 @@ namespace kiwano
} }
}; };
/**
* \~chinese
* @brief
*/
template <typename _Ty> template <typename _Ty>
using SmartPtr = IntrusivePtr<_Ty, DefaultIntrusivePtrProxy>; using SmartPtr = IntrusivePtr<_Ty, DefaultSmartPtrRefProxy>;
} }
#ifndef KGE_DECLARE_SMART_PTR #ifndef KGE_DECLARE_SMART_PTR
#define KGE_DECLARE_SMART_PTR(CLASS)\ #define KGE_DECLARE_SMART_PTR(CLASS)\
class CLASS;\ class CLASS;\
using CLASS##Ptr = ::kiwano::SmartPtr< CLASS > typedef ::kiwano::SmartPtr< CLASS > CLASS##Ptr;
#endif #endif

View File

@ -22,68 +22,64 @@
namespace kiwano namespace kiwano
{ {
Timer::Timer(Callback const& func, Duration delay, int times, String const& name)
Timer::Timer()
: running_(true) : running_(true)
, removeable_(false)
, run_times_(0) , run_times_(0)
, total_times_(times) , total_times_(0)
, delay_(delay) , interval_(0)
, callback_(func) , elapsed_(0)
, delta_() , callback_()
{
}
Timer::Timer(Callback const& cb, Duration interval, int times)
: Timer(String(), cb, interval, times)
{
}
Timer::Timer(String const& name, Callback const& cb, Duration interval, int times)
: Timer()
{ {
SetName(name); SetName(name);
SetCallback(cb);
SetInterval(interval);
SetTotalRunTimes(times);
} }
void Timer::Start() void Timer::Update(Duration dt)
{ {
running_ = true;
}
void Timer::Stop()
{
running_ = false;
}
void Timer::Update(Duration dt, bool& remove_after_update)
{
if (!running_)
return;
if (total_times_ == 0) if (total_times_ == 0)
{ {
remove_after_update = true; Remove();
return; return;
} }
if (!delay_.IsZero()) if (IsRunning())
{ {
delta_ += dt; if (!interval_.IsZero())
if (delta_ < delay_) {
return; elapsed_ += dt;
} if (elapsed_ < interval_)
return;
}
++run_times_; if (callback_)
callback_(this, elapsed_);
if (callback_) ++run_times_;
{ elapsed_ = 0;
callback_();
}
if (run_times_ == total_times_) if (run_times_ == total_times_)
{ Remove();
remove_after_update = true;
return;
} }
} }
void Timer::Reset() void Timer::Reset()
{ {
delta_ = Duration{}; elapsed_ = 0;
run_times_ = 0; run_times_ = 0;
} }
bool Timer::IsRunning() const
{
return running_;
}
} }

View File

@ -19,8 +19,6 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <functional>
#include <kiwano/core/ObjectBase.h> #include <kiwano/core/ObjectBase.h>
#include <kiwano/core/time.h> #include <kiwano/core/time.h>
@ -30,7 +28,9 @@ namespace kiwano
KGE_DECLARE_SMART_PTR(Timer); KGE_DECLARE_SMART_PTR(Timer);
// 定时任务 /// \~chinese
/// @brief 定时器
/// @details 定时器用于每隔一段时间执行一次回调函数,且可以指定执行总次数
class KGE_API Timer class KGE_API Timer
: public ObjectBase : public ObjectBase
, protected IntrusiveListItem<TimerPtr> , protected IntrusiveListItem<TimerPtr>
@ -38,36 +38,155 @@ namespace kiwano
friend class TimerManager; friend class TimerManager;
friend IntrusiveList<TimerPtr>; friend IntrusiveList<TimerPtr>;
using Callback = Function<void()>;
public: public:
Timer( /// \~chinese
Callback const& func, /* 执行函数 */ /// @brief 定时器回调函数
Duration delay, /* 时间间隔(秒) */ /// @details 回调函数第一个参数是定时器自身,第二个参数是距离上次更新的时间间隔
int times = -1, /* 执行次数(设 -1 为永久执行) */ using Callback = Function<void(Timer* /* self */, Duration /* dt */)>;
String const& name = L"" /* 任务名称 */
);
// 启动任务 /// \~chinese
/// @brief 构造空定时器
Timer();
/// \~chinese
/// @brief 构造定时器
/// @param cb 回调函数
/// @param interval 时间间隔
/// @param times 执行次数(设 -1 为永久执行)
Timer(Callback const& cb, Duration interval, int times = -1);
/// \~chinese
/// @brief 构造定时器
/// @param name 名称
/// @param cb 回调函数
/// @param interval 时间间隔
/// @param times 执行次数(设 -1 为永久执行)
Timer(String const& name, Callback const& cb, Duration interval, int times = -1);
/// \~chinese
/// @brief 启动定时器
void Start(); void Start();
// 停止任务 /// \~chinese
/// @brief 停止定时器
void Stop(); void Stop();
// 任务是否正在执行 /// \~chinese
/// @brief 移除定时器
void Remove();
/// \~chinese
/// @brief 定时器是否在运行
bool IsRunning() const; bool IsRunning() const;
private: /// \~chinese
void Update(Duration dt, bool& remove_after_update); /// @brief 定时器是否可移除
bool IsRemoveable() const;
/// \~chinese
/// @brief 获取定时器执行过回调函数的次数
int GetRunTimes() const;
/// \~chinese
/// @brief 获取定时器执行回调函数的总次数
int GetTotalRunTimes() const;
/// \~chinese
/// @brief 设置定时器执行回调函数的总次数
void SetTotalRunTimes(int times);
/// \~chinese
/// @brief 获取定时器执行时间间隔
Duration GetInterval() const;
/// \~chinese
/// @brief 设置定时器执行时间间隔
void SetInterval(Duration interval);
/// \~chinese
/// @brief 获取定时器回调函数
Callback GetCallback() const;
/// \~chinese
/// @brief 设置定时器回调函数
void SetCallback(const Callback& callback);
private:
/// \~chinese
/// @brief 更新定时器
void Update(Duration dt);
/// \~chinese
/// @brief 重置定时器
void Reset(); void Reset();
private: private:
bool running_; bool running_;
int run_times_; bool removeable_;
int total_times_; int run_times_;
Duration delay_; int total_times_;
Duration delta_; Duration interval_;
Duration elapsed_;
Callback callback_; Callback callback_;
}; };
inline void Timer::Start()
{
running_ = true;
}
inline void Timer::Stop()
{
running_ = false;
}
inline void Timer::Remove()
{
removeable_ = true;
}
inline bool Timer::IsRunning() const
{
return running_;
}
inline bool Timer::IsRemoveable() const
{
return removeable_;
}
inline int Timer::GetRunTimes() const
{
return run_times_;
}
inline int Timer::GetTotalRunTimes() const
{
return total_times_;
}
inline void Timer::SetTotalRunTimes(int times)
{
total_times_ = times;
}
inline Duration Timer::GetInterval() const
{
return interval_;
}
inline void Timer::SetInterval(Duration interval)
{
interval_ = interval;
}
inline Timer::Callback Timer::GetCallback() const
{
return callback_;
}
inline void Timer::SetCallback(const Timer::Callback& callback)
{
callback_ = callback;
}
} }

View File

@ -33,17 +33,21 @@ namespace kiwano
{ {
next = timer->next_item(); next = timer->next_item();
bool remove_after_update = false; timer->Update(dt);
timer->Update(dt, remove_after_update);
if (remove_after_update) if (timer->IsRemoveable())
timers_.remove(timer); timers_.remove(timer);
} }
} }
Timer* TimerManager::AddTimer(Timer::Callback const& func, Duration delay, int times, String const& name) Timer* TimerManager::AddTimer(Timer::Callback const& cb, Duration interval, int times)
{ {
TimerPtr timer = new Timer(func, delay, times, name); return AddTimer(String(), cb, interval, times);
}
Timer* TimerManager::AddTimer(String const& name, Timer::Callback const& cb, Duration interval, int times)
{
TimerPtr timer = new Timer(name, cb, interval, times);
return AddTimer(timer); return AddTimer(timer);
} }
@ -99,7 +103,7 @@ namespace kiwano
next = timer->next_item(); next = timer->next_item();
if (timer->IsName(name)) if (timer->IsName(name))
{ {
timers_.remove(timer); timer->Remove();
} }
} }
} }

View File

@ -23,52 +23,67 @@
namespace kiwano namespace kiwano
{ {
/**
* \~chinese
* @brief
*/
class KGE_API TimerManager class KGE_API TimerManager
{ {
public:
using Timers = IntrusiveList<TimerPtr>; using Timers = IntrusiveList<TimerPtr>;
public: /// \~chinese
// 添加定时器 /// @brief 添加定时器
Timer* AddTimer( /// @param cb 回调函数
Timer::Callback const& func, /* 执行函数 */ /// @param interval 时间间隔
Duration delay, /* 时间间隔(秒) */ /// @param times 执行次数(设 -1 为永久执行)
int times = -1, /* 执行次数(设 -1 为永久执行) */ Timer* AddTimer(Timer::Callback const& cb, Duration interval, int times = -1);
String const& name = L"" /* 任务名称 */
);
// 添加定时器 /// \~chinese
Timer* AddTimer( /// @brief 添加定时器
TimerPtr timer /// @param name 定时器名称
); /// @param cb 回调函数
/// @param interval 时间间隔
/// @param times 执行次数(设 -1 为永久执行)
Timer* AddTimer(String const& name, Timer::Callback const& cb, Duration interval, int times = -1);
// 启动任务 /// \~chinese
void StartTimers( /// @brief 添加定时器
String const& timer_name Timer* AddTimer(TimerPtr timer);
);
// 停止任务 /// \~chinese
void StopTimers( /// @brief 启动定时器
String const& timer_name void StartTimers(String const& timer_name);
);
// 移除任务 /// \~chinese
/// @brief 停止定时器
void StopTimers(String const& timer_name);
/// \~chinese
/// @brief 移除定时器
void RemoveTimers( void RemoveTimers(
String const& timer_name String const& timer_name
); );
// 启动所有任务 /// \~chinese
/// @brief 启动所有定时器
void StartAllTimers(); void StartAllTimers();
// 停止所有任务 /// \~chinese
/// @brief 停止所有定时器
void StopAllTimers(); void StopAllTimers();
// 移除所有任务 /// \~chinese
/// @brief 移除所有定时器
void RemoveAllTimers(); void RemoveAllTimers();
// 获取所有任务 /// \~chinese
/// @brief 获取所有定时器
const Timers& GetAllTimers() const; const Timers& GetAllTimers() const;
protected: protected:
/// \~chinese
/// @brief 更新定时器
void UpdateTimers(Duration dt); void UpdateTimers(Duration dt);
private: private:

View File

@ -33,67 +33,117 @@
namespace kiwano namespace kiwano
{ {
/// \~chinese
/// @brief 字符串容器
using String = oc::wstring; using String = oc::wstring;
/// \~chinese
/// @brief 字符串流
using StringStream = std::wstringstream; using StringStream = std::wstringstream;
/// \~chinese
/// @brief 线性数组容器
template <typename _Ty, typename... _Args> template <typename _Ty, typename... _Args>
using Vector = oc::vector<_Ty, _Args...>; using Vector = oc::vector<_Ty, _Args...>;
/// \~chinese
/// @brief 链表容器
template <typename _Ty, typename... _Args> template <typename _Ty, typename... _Args>
using List = std::list<_Ty, _Args...>; using List = std::list<_Ty, _Args...>;
/// \~chinese
/// @brief 队列容器
template <typename _Ty, typename... _Args> template <typename _Ty, typename... _Args>
using Queue = std::queue<_Ty, _Args...>; using Queue = std::queue<_Ty, _Args...>;
/// \~chinese
/// @brief 集合容器
template <typename _Ty, typename... _Args> template <typename _Ty, typename... _Args>
using Set = std::set<_Ty, _Args...>; using Set = std::set<_Ty, _Args...>;
/// \~chinese
/// @brief 对容器
template <typename _Ty1, typename _Ty2> template <typename _Ty1, typename _Ty2>
using Pair = std::pair<_Ty1, _Ty2>; using Pair = std::pair<_Ty1, _Ty2>;
/// \~chinese
/// @brief 无序集合容器
template <typename _Ty, typename... _Args> template <typename _Ty, typename... _Args>
using UnorderedSet = std::unordered_set<_Ty, _Args...>; using UnorderedSet = std::unordered_set<_Ty, _Args...>;
/// \~chinese
/// @brief 栈容器
template <typename _Ty, typename... _Args> template <typename _Ty, typename... _Args>
using Stack = std::stack<_Ty, _Args...>; using Stack = std::stack<_Ty, _Args...>;
/// \~chinese
/// @brief 字符串容器
template <typename _Kty, typename _Ty, typename... _Args> template <typename _Kty, typename _Ty, typename... _Args>
using Map = std::map<_Kty, _Ty, _Args...>; using Map = std::map<_Kty, _Ty, _Args...>;
/// \~chinese
/// @brief 字符串容器
template <typename _Kty, typename _Ty, typename... _Args> template <typename _Kty, typename _Ty, typename... _Args>
using UnorderedMap = std::unordered_map<_Kty, _Ty, _Args...>; using UnorderedMap = std::unordered_map<_Kty, _Ty, _Args...>;
/// \~chinese
/// @brief 函数封装器
/// @par
/// 使用函数封装器可以储存、复制和调用任何可调用目标,示例代码如下:
/// @code
/// Function<bool(int)> func1 = StaticFunc; // bool StaticFunc(int x);
/// Function<bool(int)> func2 = Closure(&t, &T::Func); // bool T::Func(int x);
/// Function<bool(int)> func3 = T::StaticFunc; // static bool T::StaticFunc(int x);
/// Function<bool(int)> func4 = [](int x) -> bool {}; // Lambda function
/// Function<bool(int)> func5 = std::bind(&T::Func, &t); // std::bind
/// Function<bool(int)> func5 = Callable(); // Callable objects: struct Callable { bool operator()(int x) {} };
/// @endcode
template <typename _FuncTy> template <typename _FuncTy>
using Function = oc::function<_FuncTy>; using Function = oc::function<_FuncTy>;
/// \~chinese
/// @brief 单值容器
using Any = oc::any; using Any = oc::any;
/// \~chinese
/// @brief JSON对象容器
using Json = oc::basic_json<Map, Vector, String, int, double, bool, std::allocator>; using Json = oc::basic_json<Map, Vector, String, int, double, bool, std::allocator>;
/// \~chinese
/// @brief 单例模板
template <typename _Ty> template <typename _Ty>
using Singleton = oc::singleton<_Ty>; using Singleton = oc::singleton<_Ty>;
/// \~chinese
/// @brief 侵入式链表容器
template <typename _Ty> template <typename _Ty>
using IntrusiveList = oc::intrusive_list<_Ty>; using IntrusiveList = oc::intrusive_list<_Ty>;
/// \~chinese
/// @brief 侵入式链表元素
template <typename _Ty> template <typename _Ty>
using IntrusiveListItem = oc::intrusive_list_item<_Ty>; using IntrusiveListItem = oc::intrusive_list_item<_Ty>;
/// \~chinese
/// @brief 侵入式智能指针
template <typename _Ty, typename _RefProxyTy> template <typename _Ty, typename _RefProxyTy>
using IntrusivePtr = oc::intrusive_ptr<_Ty, _RefProxyTy>; using IntrusivePtr = oc::intrusive_ptr<_Ty, _RefProxyTy>;
/// \~chinese
/// @brief 不可拷贝对象
using Noncopyable = oc::noncopyable; using Noncopyable = oc::noncopyable;
// Closure /// \~chinese
/// @brief 闭包函数
template<typename _Ty, typename _Uty, typename _Ret, typename... _Args> template<typename _Ty, typename _Uty, typename _Ret, typename... _Args>
inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...)) inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...))
{ {
return oc::closure(ptr, func); return oc::closure(ptr, func);
} }
/// \~chinese
/// @brief 闭包函数
template<typename _Ty, typename _Uty, typename _Ret, typename... _Args> template<typename _Ty, typename _Uty, typename _Ret, typename... _Args>
inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...) const) inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...) const)
{ {

View File

@ -27,7 +27,7 @@ namespace kiwano
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @details * @par
* : * :
* @code * @code
* time::Second * 5 // 5 秒 * time::Second * 5 // 5 秒

View File

@ -383,11 +383,11 @@ namespace kiwano
{ {
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
{ {
// KGE_LOG(L"Window minimized"); // KGE_SYS_LOG(L"Window minimized");
} }
else else
{ {
// KGE_LOG(L"Window resized"); // KGE_SYS_LOG(L"Window resized");
Window::instance().UpdateWindowRect(); Window::instance().UpdateWindowRect();
@ -425,7 +425,7 @@ namespace kiwano
case WM_SETTEXT: case WM_SETTEXT:
{ {
// KGE_LOG(L"Window title changed"); // KGE_SYS_LOG(L"Window title changed");
WindowTitleChangedEvent evt; WindowTitleChangedEvent evt;
evt.title = reinterpret_cast<const wchar_t*>(lparam); evt.title = reinterpret_cast<const wchar_t*>(lparam);
@ -435,13 +435,13 @@ namespace kiwano
case WM_SETICON: case WM_SETICON:
{ {
// KGE_LOG(L"Window icon changed"); // KGE_SYS_LOG(L"Window icon changed");
} }
break; break;
case WM_DISPLAYCHANGE: case WM_DISPLAYCHANGE:
{ {
// KGE_LOG(L"The display resolution has changed"); // KGE_SYS_LOG(L"The display resolution has changed");
::InvalidateRect(hwnd, nullptr, FALSE); ::InvalidateRect(hwnd, nullptr, FALSE);
} }
@ -455,7 +455,7 @@ namespace kiwano
case WM_CLOSE: case WM_CLOSE:
{ {
// KGE_LOG(L"Window is closing"); // KGE_SYS_LOG(L"Window is closing");
if (!app->OnClosing()) if (!app->OnClosing())
{ {
@ -468,7 +468,7 @@ namespace kiwano
case WM_DESTROY: case WM_DESTROY:
{ {
KGE_LOG(L"Window was destroyed"); KGE_SYS_LOG(L"Window was destroyed");
app->Quit(); app->Quit();
app->OnDestroy(); app->OnDestroy();

View File

@ -50,7 +50,7 @@ namespace kiwano
void Renderer::SetupComponent() void Renderer::SetupComponent()
{ {
KGE_LOG(L"Creating device resources"); KGE_SYS_LOG(L"Creating device resources");
hwnd_ = Window::instance().GetHandle(); hwnd_ = Window::instance().GetHandle();
output_size_ = Window::instance().GetSize(); output_size_ = Window::instance().GetSize();
@ -128,7 +128,7 @@ namespace kiwano
void Renderer::DestroyComponent() void Renderer::DestroyComponent()
{ {
KGE_LOG(L"Destroying device resources"); KGE_SYS_LOG(L"Destroying device resources");
RenderTarget::DiscardDeviceResources(); RenderTarget::DiscardDeviceResources();