624 lines
16 KiB
C++
624 lines
16 KiB
C++
/*
|
|
* Copyright (C) EdgeTX
|
|
*
|
|
* Based on code named
|
|
* opentx - https://github.com/opentx/opentx
|
|
* th9x - http://code.google.com/p/th9x
|
|
* er9x - http://code.google.com/p/er9x
|
|
* gruvin9x - http://code.google.com/p/gruvin9x
|
|
*
|
|
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "lua_widget.h"
|
|
|
|
#include "lua_api.h"
|
|
#include "lua_event.h"
|
|
#include "lua_widget_factory.h"
|
|
#include "lua_states.h"
|
|
|
|
#include "touch.h"
|
|
#include "view_main.h"
|
|
#include "os/time.h"
|
|
#include "keys.h"
|
|
|
|
#define MAX_INSTRUCTIONS (20000 / 100)
|
|
|
|
LuaScriptManager *luaScriptManager = nullptr;
|
|
|
|
#if defined(HARDWARE_TOUCH)
|
|
uint32_t LuaEventHandler::downTime = 0;
|
|
uint32_t LuaEventHandler::tapTime = 0;
|
|
uint32_t LuaEventHandler::tapCount = 0;
|
|
tmr10ms_t LuaEventHandler::swipeTimeOut = 0;
|
|
coord_t LuaEventHandler::_startX;
|
|
coord_t LuaEventHandler::_startY;
|
|
bool LuaEventHandler::_sliding = false;
|
|
#endif
|
|
|
|
void LuaEventHandler::event_cb(lv_event_t* e)
|
|
{
|
|
auto obj = lv_event_get_target(e);
|
|
auto win = (Window*)lv_obj_get_user_data(obj);
|
|
if (!win) return;
|
|
|
|
const lv_event_code_t code = lv_event_get_code(e);
|
|
if (code == LV_EVENT_KEY) {
|
|
uint32_t key = *(uint32_t*)lv_event_get_param(e);
|
|
if (key == LV_KEY_LEFT) {
|
|
win->onEvent(EVT_ROTARY_LEFT);
|
|
} else if (key == LV_KEY_RIGHT) {
|
|
win->onEvent(EVT_ROTARY_RIGHT);
|
|
}
|
|
} else if (code == LV_EVENT_LONG_PRESSED) {
|
|
lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
|
|
if (indev_type != LV_INDEV_TYPE_POINTER) {
|
|
// Do not use `lv_indev_wait_release()` as some LUA scripts
|
|
// rely on EVT_KEY_BREAK(KEY_ENTER) being generated on key release
|
|
luaPushEvent(EVT_KEY_LONG(KEY_ENTER));
|
|
}
|
|
}
|
|
#if defined(HARDWARE_TOUCH)
|
|
else if (code == LV_EVENT_PRESSED || code == LV_EVENT_PRESSING) {
|
|
|
|
lv_area_t obj_coords;
|
|
lv_obj_get_coords(obj, &obj_coords);
|
|
|
|
lv_point_t point_act;
|
|
lv_indev_t* click_source = (lv_indev_t*)lv_event_get_param(e);
|
|
lv_indev_get_point(click_source, &point_act);
|
|
|
|
// Ignore event from keypad
|
|
if (point_act.x < 0 || point_act.y < 0) return;
|
|
|
|
lv_point_t rel_pos;
|
|
rel_pos.x = point_act.x - obj_coords.x1;
|
|
rel_pos.y = point_act.y - obj_coords.y1;
|
|
|
|
if (code == LV_EVENT_PRESSING) {
|
|
lv_point_t vect_act;
|
|
lv_indev_get_vect(click_source, &vect_act);
|
|
|
|
if ((abs(vect_act.x) >= SLIDE_RANGE) || (abs(vect_act.y) >= SLIDE_RANGE))
|
|
_sliding = true;
|
|
|
|
if (!_sliding) return;
|
|
TRACE_WINDOWS("LuaWidget touch slide");
|
|
|
|
// If we already have a SLIDE going, then accumulate slide values instead
|
|
// of allocating an empty slot
|
|
LuaEventData* const es = luaGetEventSlot(EVT_TOUCH_SLIDE);
|
|
if (es) {
|
|
es->event = EVT_TOUCH_SLIDE;
|
|
es->touchX = rel_pos.x;
|
|
es->touchY = rel_pos.y;
|
|
es->startX = _startX;
|
|
es->startY = _startY;
|
|
es->slideX += vect_act.x;
|
|
es->slideY += vect_act.y;
|
|
TRACE("EVT_TOUCH_SLIDE [%d,%d]", rel_pos.x, rel_pos.y);
|
|
}
|
|
} else {
|
|
LuaEventData* const es = luaGetEventSlot();
|
|
if (es) {
|
|
es->event = EVT_TOUCH_FIRST;
|
|
es->touchX = rel_pos.x;
|
|
es->touchY = rel_pos.y;
|
|
TRACE("EVT_TOUCH_FIRST [%d,%d]", rel_pos.x, rel_pos.y);
|
|
}
|
|
|
|
_startX = rel_pos.x;
|
|
_startY = rel_pos.y;
|
|
|
|
downTime = time_get_ms();
|
|
}
|
|
} else if (code == LV_EVENT_RELEASED) {
|
|
// tap count handling
|
|
uint32_t now = time_get_ms();
|
|
if (now - downTime <= LUA_TAP_TIME) {
|
|
if (now - tapTime > LUA_TAP_TIME) {
|
|
tapCount = 1;
|
|
} else {
|
|
tapCount++;
|
|
}
|
|
tapTime = now;
|
|
} else {
|
|
tapCount = 0;
|
|
}
|
|
|
|
LuaEventData* const es = luaGetEventSlot();
|
|
if (es && downTime) {
|
|
downTime = 0;
|
|
es->event = EVT_TOUCH_BREAK;
|
|
TRACE("EVT_TOUCH_BREAK");
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void LuaEventHandler::onClickedEvent()
|
|
{
|
|
#if defined(HARDWARE_TOUCH)
|
|
auto click_source = lv_indev_get_act();
|
|
bool is_pointer = lv_indev_get_type(click_source) == LV_INDEV_TYPE_POINTER;
|
|
if (is_pointer) {
|
|
lv_point_t point_act;
|
|
lv_indev_get_point(click_source, &point_act);
|
|
|
|
LuaEventData* const es = luaGetEventSlot();
|
|
if (!es) return;
|
|
|
|
if (tapCount > 0) {
|
|
es->event = EVT_TOUCH_TAP;
|
|
es->tapCount = tapCount;
|
|
es->touchX = point_act.x;
|
|
es->touchY = point_act.y;
|
|
}
|
|
|
|
_sliding = false;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
luaPushEvent(EVT_KEY_BREAK(KEY_ENTER));
|
|
}
|
|
|
|
void LuaEventHandler::onCancelEvent() {
|
|
luaPushEvent(EVT_KEY_BREAK(KEY_EXIT));
|
|
}
|
|
|
|
void LuaEventHandler::onLuaEvent(event_t event)
|
|
{
|
|
luaPushEvent(event);
|
|
}
|
|
|
|
void LuaEventHandler::setupHandler(Window* w)
|
|
{
|
|
lv_obj_t* obj = w->getLvObj();
|
|
lv_obj_add_event_cb(obj, LuaEventHandler::event_cb, LV_EVENT_ALL, nullptr);
|
|
}
|
|
|
|
void LuaEventHandler::removeHandler(Window* w)
|
|
{
|
|
lv_obj_t* obj = w->getLvObj();
|
|
lv_obj_remove_event_cb(obj, LuaEventHandler::event_cb);
|
|
}
|
|
|
|
void LuaWidget::redraw_cb(lv_event_t* e)
|
|
{
|
|
lv_obj_t* target = lv_event_get_target(e);
|
|
|
|
LuaWidget* widget = (LuaWidget*)lv_obj_get_user_data(target);
|
|
|
|
if (widget && !widget->useLvglLayout()) {
|
|
lv_draw_ctx_t* draw_ctx = lv_event_get_draw_ctx(e);
|
|
|
|
lv_area_t a, clipping, obj_coords;
|
|
lv_area_copy(&a, draw_ctx->buf_area);
|
|
lv_area_copy(&clipping, draw_ctx->clip_area);
|
|
lv_obj_get_coords(target, &obj_coords);
|
|
|
|
auto w = a.x2 - a.x1 + 1;
|
|
auto h = a.y2 - a.y1 + 1;
|
|
|
|
TRACE_WINDOWS("Draw %s", widget->getWindowDebugString().c_str());
|
|
|
|
BitmapBuffer buf = {BMP_RGB565, (uint16_t)w, (uint16_t)h,
|
|
(uint16_t*)draw_ctx->buf};
|
|
|
|
buf.setDrawCtx(draw_ctx);
|
|
|
|
buf.setOffset(obj_coords.x1 - a.x1, obj_coords.y1 - a.y1);
|
|
buf.setClippingRect(clipping.x1 - a.x1, clipping.x2 + 1 - a.x1,
|
|
clipping.y1 - a.y1, clipping.y2 + 1 - a.y1);
|
|
|
|
auto save = luaScriptManager;
|
|
luaScriptManager = widget;
|
|
widget->refresh(&buf);
|
|
luaScriptManager = save;
|
|
}
|
|
}
|
|
|
|
LuaWidget::LuaWidget(const WidgetFactory* factory, Window* parent,
|
|
const rect_t& rect, int screenNum, int zoneNum,
|
|
int zoneRectDataRef, int optionsDataRef,
|
|
int createFunctionRef, const std::string& path) :
|
|
Widget(factory, parent, rect, screenNum, zoneNum),
|
|
zoneRectDataRef(zoneRectDataRef), optionsDataRef(optionsDataRef),
|
|
errorMessage(nullptr)
|
|
{
|
|
// Push create function
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, createFunctionRef);
|
|
// Push stored zone for 'create' call
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, zoneRectDataRef);
|
|
// Push stored options for 'create' call
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, optionsDataRef);
|
|
// Push widget folder path
|
|
lua_pushstring(lsWidgets, path.c_str());
|
|
|
|
auto save = luaScriptManager;
|
|
luaScriptManager = this;
|
|
|
|
if (lua_pcall(lsWidgets, 3, 1, 0) == LUA_OK) {
|
|
luaScriptContextRef = luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
|
|
} else {
|
|
luaScriptContextRef = LUA_REFNIL;
|
|
setErrorMessage("create()");
|
|
}
|
|
|
|
luaScriptManager = save;
|
|
|
|
if (useLvglLayout()) {
|
|
update();
|
|
} else {
|
|
lv_obj_add_event_cb(lvobj, LuaWidget::redraw_cb, LV_EVENT_DRAW_MAIN,
|
|
nullptr);
|
|
}
|
|
|
|
onClosing([=]() {
|
|
luaL_unref(lsWidgets, LUA_REGISTRYINDEX, zoneRectDataRef);
|
|
if (errorMessage)
|
|
free(errorMessage);
|
|
});
|
|
}
|
|
|
|
void LuaWidget::onClicked()
|
|
{
|
|
if (!fullscreen) {
|
|
ButtonBase::onClicked();
|
|
return;
|
|
}
|
|
|
|
LuaScriptManager::onClickedEvent();
|
|
}
|
|
|
|
void LuaWidget::onCancel()
|
|
{
|
|
if (!fullscreen) {
|
|
ButtonBase::onCancel();
|
|
return;
|
|
}
|
|
|
|
LuaScriptManager::onCancelEvent();
|
|
}
|
|
|
|
void LuaWidget::foreground()
|
|
{
|
|
if (closeFS) {
|
|
closeFS = false;
|
|
setFullscreen(false);
|
|
}
|
|
|
|
// Check widget is at least partially visible
|
|
if (isOnScreen()) {
|
|
if (useLvglLayout()) {
|
|
auto save = luaScriptManager;
|
|
PROTECT_LUA() {
|
|
luaScriptManager = this;
|
|
refresh(nullptr);
|
|
if (!errorMessage) {
|
|
if (!callRefs(lsWidgets)) {
|
|
setErrorMessage("foreground calRefs error");
|
|
}
|
|
}
|
|
refreshInstructionsPercent = instructionsPercent;
|
|
} else {
|
|
setErrorMessage("foreground protect Lua error");
|
|
}
|
|
luaScriptManager = save;
|
|
UNPROTECT_LUA();
|
|
} else {
|
|
// Force call to redraw_cb()
|
|
invalidate();
|
|
}
|
|
}
|
|
|
|
#if defined(DEBUG_WINDOWS)
|
|
TRACE_WINDOWS("# refresh: %s", getWindowDebugString().c_str());
|
|
#endif
|
|
}
|
|
|
|
void LuaWidget::updateWithoutRefresh()
|
|
{
|
|
if (lsWidgets == 0 || errorMessage || luaFactory()->updateFunction == LUA_REFNIL) return;
|
|
|
|
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaFactory()->updateFunction);
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaScriptContextRef);
|
|
|
|
auto widgetData = getPersistentData();
|
|
|
|
// Get options table and update values
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, optionsDataRef);
|
|
int i = 0;
|
|
for (const WidgetOption* option = getOptionDefinitions(); option->name; option++, i++) {
|
|
switch (option->type) {
|
|
case WidgetOption::String:
|
|
case WidgetOption::File:
|
|
lua_pushstring(lsWidgets, widgetData->getString(i).c_str());
|
|
break;
|
|
case WidgetOption::Integer:
|
|
case WidgetOption::Switch:
|
|
lua_pushinteger(lsWidgets, widgetData->getSignedValue(i));
|
|
break;
|
|
default:
|
|
lua_pushinteger(lsWidgets, widgetData->getUnsignedValue(i));
|
|
break;
|
|
}
|
|
lua_setfield(lsWidgets, -2, option->name);
|
|
}
|
|
|
|
auto save = luaScriptManager;
|
|
luaScriptManager = this;
|
|
|
|
if (lua_pcall(lsWidgets, 2, 0, 0) != 0)
|
|
setErrorMessage("update()");
|
|
|
|
luaScriptManager = save;
|
|
}
|
|
|
|
void LuaWidget::update()
|
|
{
|
|
updateWithoutRefresh();
|
|
|
|
Widget::update();
|
|
|
|
auto save = luaScriptManager;
|
|
luaScriptManager = this;
|
|
|
|
if (useLvglLayout()) {
|
|
if (!lv_obj_has_flag(lvobj, LV_OBJ_FLAG_HIDDEN)) {
|
|
lv_area_t a;
|
|
lv_obj_get_coords(lvobj, &a);
|
|
// Check widget is at least partially visible
|
|
if (a.x2 >= 0 && a.x1 < LCD_W) {
|
|
PROTECT_LUA() {
|
|
if (!callRefs(lsWidgets)) {
|
|
setErrorMessage("update callRefs error");
|
|
}
|
|
} else {
|
|
setErrorMessage("update protect Lua error");
|
|
}
|
|
UNPROTECT_LUA();
|
|
}
|
|
}
|
|
}
|
|
|
|
luaScriptManager = save;
|
|
}
|
|
|
|
// Update table on top of Lua stack - set entry with name 'idx' to value 'val'
|
|
// Return true if value has changed
|
|
bool LuaWidget::updateTable(const char* idx, int val)
|
|
{
|
|
bool update = false;
|
|
|
|
// Check existing value (or invalid value)
|
|
lua_getfield(lsWidgets, -1, idx);
|
|
if (lua_isnumber(lsWidgets, -1)) {
|
|
int v = lua_tointeger(lsWidgets, -1);
|
|
update = (v != val);
|
|
} else {
|
|
// Force table update
|
|
update = true;
|
|
}
|
|
lua_pop(lsWidgets, 1);
|
|
|
|
if (update) {
|
|
lua_pushinteger(lsWidgets, val);
|
|
lua_setfield(lsWidgets, -2, idx);
|
|
}
|
|
|
|
return update;
|
|
}
|
|
|
|
void LuaWidget::updateZoneRect(rect_t rect, bool updateUI)
|
|
{
|
|
if (lsWidgets) {
|
|
// Update widget zone with current size and position
|
|
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, zoneRectDataRef);
|
|
|
|
bool changed = false;
|
|
|
|
if (updateTable("w", rect.w)) changed = true;
|
|
if (updateTable("h", rect.h)) changed = true;
|
|
if (updateTable("xabs", rect.x)) changed = true;
|
|
if (updateTable("yabs", rect.y)) changed = true;
|
|
|
|
lua_pop(lsWidgets, 1);
|
|
|
|
if (changed && updateUI)
|
|
updateWithoutRefresh();
|
|
}
|
|
}
|
|
|
|
void LuaWidget::onFullscreen(bool enable)
|
|
{
|
|
if (enable) {
|
|
setupHandler(this);
|
|
} else {
|
|
removeHandler(this);
|
|
luaEmptyEventBuffer();
|
|
}
|
|
}
|
|
|
|
void LuaWidget::setErrorMessage(const char* funcName)
|
|
{
|
|
constexpr int err_len = 255;
|
|
|
|
const char* lua_err = lua_tostring(lsWidgets, -1);
|
|
TRACE("Error in widget %s %s function: %s", factory->getName(), funcName,
|
|
lua_err);
|
|
TRACE("Widget disabled");
|
|
|
|
if (!errorMessage)
|
|
errorMessage = (char*)malloc(err_len + 1);
|
|
|
|
if (errorMessage) {
|
|
snprintf(errorMessage, err_len, "ERROR in %s: %s", funcName, lua_err);
|
|
errorMessage[err_len] = '\0';
|
|
}
|
|
}
|
|
|
|
void LuaWidget::luaShowError()
|
|
{
|
|
setErrorMessage("widget");
|
|
}
|
|
|
|
const char* LuaWidget::getErrorMessage() const { return errorMessage; }
|
|
|
|
void LuaWidget::refresh(BitmapBuffer* dc)
|
|
{
|
|
if (lsWidgets == 0 || luaFactory()->refreshFunction == LUA_REFNIL) return;
|
|
|
|
if (errorMessage) {
|
|
if (dc) {
|
|
dc->drawTextLines(0, 0, fullscreen ? LCD_W : rect.w,
|
|
fullscreen ? LCD_H : rect.h, errorMessage,
|
|
FONT(XS) | COLOR_THEME_WARNING);
|
|
} else {
|
|
if (errorLabel == nullptr) {
|
|
errorLabel = etx_label_create(lvobj, FONT_XS_INDEX);
|
|
lv_obj_set_pos(errorLabel, 0, 0);
|
|
lv_obj_set_size(errorLabel, width(), height());
|
|
lv_label_set_long_mode(errorLabel, LV_LABEL_LONG_WRAP);
|
|
etx_txt_color(errorLabel, COLOR_THEME_WARNING_INDEX);
|
|
etx_bg_color(errorLabel, COLOR_THEME_SECONDARY3_INDEX);
|
|
etx_obj_add_style(errorLabel, styles->bg_opacity_75, LV_PART_MAIN);
|
|
}
|
|
lv_label_set_text(errorLabel, errorMessage);
|
|
}
|
|
return;
|
|
}
|
|
|
|
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaFactory()->refreshFunction);
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaScriptContextRef);
|
|
|
|
// Pass key event to fullscreen Lua widget
|
|
LuaEventData evt;
|
|
luaNextEvent(&evt);
|
|
|
|
if (fullscreen) {
|
|
lua_pushinteger(lsWidgets, evt.event);
|
|
} else
|
|
lua_pushnil(lsWidgets);
|
|
|
|
#if defined(HARDWARE_TOUCH)
|
|
if (fullscreen && IS_TOUCH_EVENT(evt.event)) {
|
|
luaPushTouchEventTable(lsWidgets, &evt);
|
|
} else
|
|
#endif
|
|
lua_pushnil(lsWidgets);
|
|
|
|
// Enable drawing into the current LCD buffer
|
|
luaLcdBuffer = dc;
|
|
|
|
// This little hack is needed to not interfere with the LCD usage of preempted
|
|
// scripts
|
|
bool lla = luaLcdAllowed;
|
|
luaLcdAllowed = true;
|
|
|
|
if (lua_pcall(lsWidgets, 3, 0, 0) != 0) {
|
|
setErrorMessage("refresh()");
|
|
}
|
|
// Remove LCD
|
|
luaLcdAllowed = lla;
|
|
luaLcdBuffer = nullptr;
|
|
}
|
|
|
|
void LuaWidget::background()
|
|
{
|
|
if (lsWidgets == 0 || errorMessage) return;
|
|
|
|
if (luaFactory()->backgroundFunction != LUA_REFNIL) {
|
|
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaFactory()->backgroundFunction);
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaScriptContextRef);
|
|
auto save = luaScriptManager;
|
|
luaScriptManager = this;
|
|
if (lua_pcall(lsWidgets, 1, 0, 0) != 0) {
|
|
setErrorMessage("background()");
|
|
}
|
|
luaScriptManager = save;
|
|
}
|
|
}
|
|
|
|
void LuaWidget::onEvent(event_t event)
|
|
{
|
|
if (fullscreen) {
|
|
LuaScriptManager::onLuaEvent(event);
|
|
}
|
|
Widget::onEvent(event);
|
|
}
|
|
|
|
void LuaWidget::clear()
|
|
{
|
|
clearRefs(lsWidgets);
|
|
Widget::clear();
|
|
}
|
|
|
|
bool LuaWidget::useLvglLayout() const { return luaFactory()->useLvglLayout(); }
|
|
|
|
bool LuaWidget::isAppMode() const
|
|
{
|
|
return ((WidgetsContainer*)parent)->isAppMode();
|
|
}
|
|
|
|
void LuaScriptManager::saveLvglObjectRef(int ref)
|
|
{
|
|
if (tempParent)
|
|
tempParent->saveLvglObjectRef(ref);
|
|
else
|
|
lvglObjectRefs.push_back(ref);
|
|
}
|
|
|
|
void LuaScriptManager::clearRefs(lua_State *L)
|
|
{
|
|
for (size_t i = 0; i < lvglObjectRefs.size(); i += 1) {
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, lvglObjectRefs[i]);
|
|
auto p = LvglWidgetObjectBase::checkLvgl(L, -1);
|
|
lua_pop(L, 1);
|
|
if (p) p->clearRefs(L);
|
|
}
|
|
lvglObjectRefs.clear();
|
|
}
|
|
|
|
bool LuaScriptManager::callRefs(lua_State *L)
|
|
{
|
|
for (size_t i = 0; i < lvglObjectRefs.size(); i += 1) {
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, lvglObjectRefs[i]);
|
|
auto p = LvglWidgetObjectBase::checkLvgl(L, -1);
|
|
lua_pop(L, 1);
|
|
if (p) if (!p->callRefs(L)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void LuaScriptManager::createTelemetryQueue()
|
|
{
|
|
if (luaInputTelemetryFifo == nullptr) {
|
|
luaInputTelemetryFifo = new TelemetryQueue();
|
|
registerTelemetryQueue(luaInputTelemetryFifo);
|
|
}
|
|
}
|
|
|
|
LuaScriptManager::~LuaScriptManager()
|
|
{
|
|
luaL_unref(lsWidgets, LUA_REGISTRYINDEX, luaScriptContextRef);
|
|
if (luaInputTelemetryFifo != nullptr) {
|
|
destroyTelemetryQueue(luaInputTelemetryFifo);
|
|
luaInputTelemetryFifo = nullptr;
|
|
}
|
|
}
|