mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-22 06:41:08 +00:00
[lua] Add Timer() type (fix #3251)
This commit is contained in:
parent
835aa3f83d
commit
c2f8335891
@ -209,6 +209,7 @@ if(ENABLE_SCRIPTING)
|
||||
script/tile_class.cpp
|
||||
script/tileset_class.cpp
|
||||
script/tilesets_class.cpp
|
||||
script/timer_class.cpp
|
||||
script/tool_class.cpp
|
||||
script/values.cpp
|
||||
script/version_class.cpp
|
||||
|
@ -192,6 +192,7 @@ void register_theme_classes(lua_State* L);
|
||||
void register_tile_class(lua_State* L);
|
||||
void register_tileset_class(lua_State* L);
|
||||
void register_tilesets_class(lua_State* L);
|
||||
void register_timer_class(lua_State* L);
|
||||
void register_tool_class(lua_State* L);
|
||||
void register_version_class(lua_State* L);
|
||||
void register_websocket_class(lua_State* L);
|
||||
@ -472,6 +473,7 @@ Engine::Engine()
|
||||
register_tile_class(L);
|
||||
register_tileset_class(L);
|
||||
register_tilesets_class(L);
|
||||
register_timer_class(L);
|
||||
register_tool_class(L);
|
||||
register_version_class(L);
|
||||
#if ENABLE_WEBSOCKET
|
||||
|
171
src/app/script/timer_class.cpp
Normal file
171
src/app/script/timer_class.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022-2023 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/script/engine.h"
|
||||
#include "app/script/luacpp.h"
|
||||
#include "ui/timer.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace app {
|
||||
namespace script {
|
||||
|
||||
namespace {
|
||||
|
||||
class Timer : public ui::Timer {
|
||||
public:
|
||||
Timer() : ui::Timer(100) { }
|
||||
|
||||
int runningRef() const {
|
||||
return m_runningRef;
|
||||
}
|
||||
|
||||
void refTimer(lua_State* L) {
|
||||
if (m_runningRef == LUA_REFNIL) {
|
||||
lua_pushvalue(L, 1);
|
||||
m_runningRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
}
|
||||
|
||||
void unrefTimer(lua_State* L) {
|
||||
if (m_runningRef != LUA_REFNIL) {
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, m_runningRef);
|
||||
m_runningRef = LUA_REFNIL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Reference used to keep the timer alive (so it's not garbage
|
||||
// collected) when it's running.
|
||||
int m_runningRef = LUA_REFNIL;
|
||||
};
|
||||
|
||||
int Timer_new(lua_State* L)
|
||||
{
|
||||
auto timer = push_new<Timer>(L);
|
||||
|
||||
if (lua_istable(L, 1)) {
|
||||
auto type = lua_getfield(L, 1, "interval");
|
||||
if (type != LUA_TNIL)
|
||||
timer->setInterval(std::max(1, int(lua_tonumber(L, -1) * 1000.0)));
|
||||
lua_pop(L, 1);
|
||||
|
||||
type = lua_getfield(L, 1, "ontick");
|
||||
if (type == LUA_TFUNCTION) {
|
||||
lua_pushvalue(L, -1); // Copy the function in the stack
|
||||
lua_setuservalue(L, -3); // Put the function as uservalue of the timer
|
||||
|
||||
timer->Tick.connect(
|
||||
[timer, L]() {
|
||||
if (timer->runningRef() == LUA_REFNIL)
|
||||
return;
|
||||
|
||||
try {
|
||||
// Get the timer, and get the function that is inside the
|
||||
// timer uservalue
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, timer->runningRef());
|
||||
lua_getuservalue(L, -1);
|
||||
if (lua_isfunction(L, -1)) {
|
||||
if (lua_pcall(L, 0, 0, 0)) {
|
||||
if (const char* s = lua_tostring(L, -1))
|
||||
App::instance()
|
||||
->scriptEngine()
|
||||
->consolePrint(s);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_pop(L, 1); // Pop the value which should have been a function
|
||||
}
|
||||
lua_pop(L, 1); // Pop timer
|
||||
}
|
||||
catch (const std::exception& ex) {
|
||||
App::instance()
|
||||
->scriptEngine()
|
||||
->consolePrint(ex.what());
|
||||
}
|
||||
});
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Timer_gc(lua_State* L)
|
||||
{
|
||||
auto obj = get_obj<Timer>(L, 1);
|
||||
obj->~Timer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Timer_start(lua_State* L)
|
||||
{
|
||||
auto obj = get_obj<Timer>(L, 1);
|
||||
obj->start();
|
||||
obj->refTimer(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Timer_stop(lua_State* L)
|
||||
{
|
||||
auto obj = get_obj<Timer>(L, 1);
|
||||
obj->stop();
|
||||
obj->unrefTimer(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Timer_get_interval(lua_State* L)
|
||||
{
|
||||
const auto timer = get_obj<Timer>(L, 1);
|
||||
lua_pushnumber(L, double(timer->interval()) / 1000.0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Timer_set_interval(lua_State* L)
|
||||
{
|
||||
const auto timer = get_obj<Timer>(L, 1);
|
||||
int interval = int(lua_tonumber(L, 2) * 1000.0);
|
||||
timer->setInterval(std::max(1, interval));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Timer_get_isRunning(lua_State* L)
|
||||
{
|
||||
const auto timer = get_obj<Timer>(L, 1);
|
||||
lua_pushboolean(L, timer->isRunning());
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg Timer_methods[] = {
|
||||
{ "__gc", Timer_gc },
|
||||
{ "start", Timer_start },
|
||||
{ "stop", Timer_stop },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
const Property Timer_properties[] = {
|
||||
{ "interval", Timer_get_interval, Timer_set_interval },
|
||||
{ "isRunning", Timer_get_isRunning, nullptr },
|
||||
{ nullptr, nullptr, nullptr }
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
DEF_MTNAME(Timer);
|
||||
|
||||
void register_timer_class(lua_State* L)
|
||||
{
|
||||
REG_CLASS(L, Timer);
|
||||
REG_CLASS_NEW(L, Timer);
|
||||
REG_CLASS_PROPERTIES(L, Timer);
|
||||
}
|
||||
|
||||
} // namespace script
|
||||
} // namespace app
|
Loading…
x
Reference in New Issue
Block a user