1201 lines
33 KiB
C++
1201 lines
33 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 "opentx.h"
|
|
#include "slider.h"
|
|
#include "toggleswitch.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetObjectBase::getParams(lua_State *L, int index)
|
|
{
|
|
luaL_checktype(L, index, LUA_TTABLE);
|
|
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
|
int top = lua_gettop(L);
|
|
parseParam(L, lua_tostring(L, -2));
|
|
// Replace value on Lua stack if consumed by parseParam
|
|
if (top != lua_gettop(L)) lua_pushnil(L);
|
|
}
|
|
}
|
|
|
|
bool LvglWidgetObjectBase::pcallFunc(lua_State *L, int getFuncRef, int nretval)
|
|
{
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, getFuncRef);
|
|
return lua_pcall(L, 0, nretval, 0) == 0;
|
|
}
|
|
|
|
void LvglWidgetObjectBase::pcallSimpleFunc(lua_State *L, int funcRef)
|
|
{
|
|
if (funcRef) {
|
|
PROTECT_LUA()
|
|
{
|
|
if (!pcallFunc(L, funcRef, 1)) {
|
|
lvglManager->luaShowError();
|
|
}
|
|
}
|
|
UNPROTECT_LUA();
|
|
}
|
|
}
|
|
|
|
bool LvglWidgetObjectBase::pcallUpdateBool(lua_State *L, int getFuncRef,
|
|
std::function<void(bool)> update)
|
|
{
|
|
if (getFuncRef) {
|
|
int t = lua_gettop(L);
|
|
if (pcallFunc(L, getFuncRef, 1)) {
|
|
bool val = lua_toboolean(L, -1);
|
|
update(val);
|
|
lua_settop(L, t);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool LvglWidgetObjectBase::pcallUpdate1Int(lua_State *L, int getFuncRef,
|
|
std::function<void(int)> update)
|
|
{
|
|
if (getFuncRef) {
|
|
int t = lua_gettop(L);
|
|
if (pcallFunc(L, getFuncRef, 1)) {
|
|
int val = luaL_checkunsigned(L, -1);
|
|
update(val);
|
|
lua_settop(L, t);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool LvglWidgetObjectBase::pcallUpdate2Int(lua_State *L, int getFuncRef,
|
|
std::function<void(int, int)> update)
|
|
{
|
|
if (getFuncRef) {
|
|
int t = lua_gettop(L);
|
|
if (pcallFunc(L, getFuncRef, 2)) {
|
|
int v1 = luaL_checkunsigned(L, -2);
|
|
int v2 = luaL_checkunsigned(L, -1);
|
|
update(v1, v2);
|
|
lua_settop(L, t);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int LvglWidgetObjectBase::pcallGetIntVal(lua_State *L, int getFuncRef)
|
|
{
|
|
int val = 0;
|
|
if (getFuncRef) {
|
|
int t = lua_gettop(L);
|
|
PROTECT_LUA()
|
|
{
|
|
if (pcallFunc(L, getFuncRef, 1)) {
|
|
val = luaL_checkinteger(L, -1);
|
|
} else {
|
|
lvglManager->luaShowError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lvglManager->luaShowError();
|
|
}
|
|
UNPROTECT_LUA();
|
|
lua_settop(L, t);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
void LvglWidgetObjectBase::pcallSetIntVal(lua_State *L, int setFuncRef, int val)
|
|
{
|
|
if (setFuncRef) {
|
|
int t = lua_gettop(L);
|
|
PROTECT_LUA()
|
|
{
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, setFuncRef);
|
|
lua_pushinteger(L, val);
|
|
bool rv = lua_pcall(L, 1, 0, 0) == 0;
|
|
if (!rv) {
|
|
lvglManager->luaShowError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lvglManager->luaShowError();
|
|
}
|
|
UNPROTECT_LUA();
|
|
lua_settop(L, t);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetObjectBase::clearRef(lua_State *L, int ref)
|
|
{
|
|
if (ref) luaL_unref(L, LUA_REGISTRYINDEX, ref);
|
|
}
|
|
|
|
void LvglWidgetObjectBase::build(lua_State *L) {}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool LvglWidgetObject::callRefs(lua_State *L)
|
|
{
|
|
if (!pcallUpdate1Int(L, getColorFunction,
|
|
[=](int color) { setColor(color); }))
|
|
return false;
|
|
if (!pcallUpdateBool(L, getVisibleFunction,
|
|
[=](bool visible) { window->show(visible); }))
|
|
return false;
|
|
if (!pcallUpdate2Int(L, getSizeFunction,
|
|
[=](int w, int h) { setSize(w, h); }))
|
|
return false;
|
|
if (!pcallUpdate2Int(L, getPosFunction, [=](int x, int y) { setPos(x, y); }))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void LvglWidgetObject::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, getColorFunction);
|
|
clearRef(L, getVisibleFunction);
|
|
clearRef(L, getSizeFunction);
|
|
clearRef(L, getPosFunction);
|
|
}
|
|
|
|
void LvglWidgetObject::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "x")) {
|
|
x = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "y")) {
|
|
y = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "w")) {
|
|
w = luaL_checkinteger(L, -1);
|
|
if (w == 0) w = LV_SIZE_CONTENT;
|
|
} else if (!strcmp(key, "h")) {
|
|
h = luaL_checkinteger(L, -1);
|
|
if (h == 0) h = LV_SIZE_CONTENT;
|
|
} else if (!strcmp(key, "color")) {
|
|
if (lua_isfunction(L, -1)) {
|
|
getColorFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
color = luaL_checkunsigned(L, -1);
|
|
color = flagsRGB(color);
|
|
}
|
|
} else if (!strcmp(key, "visible")) {
|
|
getVisibleFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else if (!strcmp(key, "size")) {
|
|
getSizeFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else if (!strcmp(key, "pos")) {
|
|
getPosFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
}
|
|
}
|
|
|
|
int LvglWidgetObject::getRef(lua_State *L)
|
|
{
|
|
LvglWidgetObject **p =
|
|
(LvglWidgetObject **)lua_newuserdata(L, sizeof(LvglWidgetObject *));
|
|
*p = this;
|
|
luaL_getmetatable(L, LVGL_METATABLE);
|
|
lua_setmetatable(L, -2);
|
|
|
|
// Save reference
|
|
auto ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
lvglManager->saveLvglObjectRef(ref);
|
|
|
|
return ref;
|
|
}
|
|
|
|
void LvglWidgetObject::push(lua_State *L)
|
|
{
|
|
// Save reference
|
|
auto ref = getRef(L);
|
|
// Push userdata back into Lua stack (return object)
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
|
|
}
|
|
|
|
void LvglWidgetObject::update(lua_State *L)
|
|
{
|
|
getParams(L, 2);
|
|
refresh();
|
|
}
|
|
|
|
void LvglWidgetObject::refresh()
|
|
{
|
|
setPos(x, y);
|
|
setSize(w, h);
|
|
setColor(color);
|
|
}
|
|
|
|
void LvglWidgetObject::setPos(coord_t x, coord_t y)
|
|
{
|
|
this->x = x;
|
|
this->y = y;
|
|
if (window) window->setPos(x, y);
|
|
}
|
|
|
|
void LvglWidgetObject::setSize(coord_t w, coord_t h)
|
|
{
|
|
this->w = w;
|
|
this->h = h;
|
|
if (window) window->setSize(w, h);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetBorderedObject::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "thickness")) {
|
|
thickness = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "filled")) {
|
|
filled = lua_toboolean(L, -1);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetBorderedObject::setColor(LcdFlags color)
|
|
{
|
|
if (color != currentColor) {
|
|
currentColor = color;
|
|
if (filled)
|
|
lv_obj_set_style_bg_color(window->getLvObj(),
|
|
makeLvColor(flagsRGB(color)), LV_PART_MAIN);
|
|
else
|
|
lv_obj_set_style_border_color(window->getLvObj(),
|
|
makeLvColor(flagsRGB(color)), LV_PART_MAIN);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetBorderedObject::build(lua_State *L)
|
|
{
|
|
window =
|
|
new Window(lvglManager->getCurrentParent(), {x, y, w, h}, lv_obj_create);
|
|
lv_obj_add_flag(window->getLvObj(), LV_OBJ_FLAG_EVENT_BUBBLE);
|
|
if (luaLvglManager->isWidget()) {
|
|
lv_obj_clear_flag(window->getLvObj(), LV_OBJ_FLAG_CLICKABLE);
|
|
} else {
|
|
etx_scrollbar(window->getLvObj());
|
|
}
|
|
setColor(color);
|
|
if (filled) {
|
|
lv_obj_set_style_bg_opa(window->getLvObj(), LV_OPA_COVER, LV_PART_MAIN);
|
|
} else {
|
|
lv_obj_set_style_border_opa(window->getLvObj(), LV_OPA_COVER, LV_PART_MAIN);
|
|
lv_obj_set_style_border_width(window->getLvObj(), thickness, LV_PART_MAIN);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetRoundObject::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "radius")) {
|
|
if (lua_isfunction(L, -1))
|
|
getRadiusFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
else
|
|
radius = luaL_checkunsigned(L, -1);
|
|
} else {
|
|
LvglWidgetBorderedObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
bool LvglWidgetRoundObject::callRefs(lua_State *L)
|
|
{
|
|
if (!pcallUpdate1Int(L, getRadiusFunction, [=](int val) { setRadius(val); }))
|
|
return false;
|
|
return LvglWidgetObject::callRefs(L);
|
|
}
|
|
|
|
void LvglWidgetRoundObject::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, getRadiusFunction);
|
|
LvglWidgetObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetRoundObject::setPos(coord_t x, coord_t y)
|
|
{
|
|
LvglWidgetObject::setPos(x - radius, y - radius);
|
|
}
|
|
|
|
void LvglWidgetRoundObject::setRadius(coord_t r)
|
|
{
|
|
// Set position to center
|
|
x += radius;
|
|
y += radius;
|
|
radius = r;
|
|
w = radius * 2;
|
|
h = radius * 2;
|
|
setPos(x, y);
|
|
setSize(w, h);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetLabel::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "text")) {
|
|
if (lua_isfunction(L, -1))
|
|
getTextFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
else
|
|
txt = luaL_checkstring(L, -1);
|
|
} else if (!strcmp(key, "font")) {
|
|
if (lua_isfunction(L, -1))
|
|
getFontFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
else
|
|
font = luaL_checkunsigned(L, -1);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
bool LvglWidgetLabel::callRefs(lua_State *L)
|
|
{
|
|
int t = lua_gettop(L);
|
|
if (getTextFunction) {
|
|
if (pcallFunc(L, getTextFunction, 1)) {
|
|
const char *s = luaL_checkstring(L, -1);
|
|
setText(s);
|
|
lua_settop(L, t);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
if (!pcallUpdate1Int(L, getFontFunction, [=](int val) { setFont(val); }))
|
|
return false;
|
|
return LvglWidgetObject::callRefs(L);
|
|
}
|
|
|
|
void LvglWidgetLabel::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, getTextFunction);
|
|
clearRef(L, getFontFunction);
|
|
LvglWidgetObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetLabel::setText(const char *s)
|
|
{
|
|
uint32_t h = hash(s, strlen(s));
|
|
if (h != textHash) {
|
|
txt = s;
|
|
textHash = h;
|
|
lv_label_set_text(window->getLvObj(), s);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetLabel::setColor(LcdFlags color)
|
|
{
|
|
if (color != currentColor) {
|
|
currentColor = color;
|
|
lv_obj_set_style_text_color(window->getLvObj(),
|
|
makeLvColor(flagsRGB(color)), LV_PART_MAIN);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetLabel::setFont(LcdFlags font)
|
|
{
|
|
this->font = font;
|
|
lv_obj_set_style_text_align(window->getLvObj(),
|
|
(font & RIGHT) ? LV_TEXT_ALIGN_RIGHT
|
|
: (font & CENTERED) ? LV_TEXT_ALIGN_CENTER
|
|
: LV_TEXT_ALIGN_LEFT,
|
|
LV_PART_MAIN);
|
|
lv_obj_set_style_text_font(window->getLvObj(), getFont(font), LV_PART_MAIN);
|
|
}
|
|
|
|
void LvglWidgetLabel::build(lua_State *L)
|
|
{
|
|
window = new Window(lvglManager->getCurrentParent(), {x, y, w, h},
|
|
lv_label_create);
|
|
setText(txt);
|
|
setColor(color);
|
|
setFont(font);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetRectangle::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "rounded")) {
|
|
rounded = luaL_checkunsigned(L, -1);
|
|
} else {
|
|
LvglWidgetBorderedObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetRectangle::build(lua_State *L)
|
|
{
|
|
LvglWidgetBorderedObject::build(L);
|
|
if (rounded) {
|
|
lv_obj_set_style_radius(window->getLvObj(),
|
|
(rounded >= thickness) ? rounded : thickness,
|
|
LV_PART_MAIN);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetCircle::build(lua_State *L)
|
|
{
|
|
// Reset position to corner
|
|
setPos(x, y);
|
|
// Set width & height
|
|
setRadius(radius);
|
|
LvglWidgetBorderedObject::build(L);
|
|
lv_obj_set_style_radius(window->getLvObj(), LV_RADIUS_CIRCLE, LV_PART_MAIN);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetArc::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "startAngle")) {
|
|
if (lua_isfunction(L, -1))
|
|
getStartAngleFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
else
|
|
startAngle = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "endAngle")) {
|
|
if (lua_isfunction(L, -1))
|
|
getEndAngleFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
else
|
|
endAngle = luaL_checkunsigned(L, -1);
|
|
} else {
|
|
LvglWidgetRoundObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetArc::setColor(LcdFlags color)
|
|
{
|
|
if (color != currentColor) {
|
|
currentColor = color;
|
|
lv_obj_set_style_arc_color(window->getLvObj(), makeLvColor(flagsRGB(color)),
|
|
LV_PART_INDICATOR);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetArc::setStartAngle(coord_t angle)
|
|
{
|
|
lv_arc_set_start_angle(window->getLvObj(), angle);
|
|
}
|
|
|
|
void LvglWidgetArc::setEndAngle(coord_t angle)
|
|
{
|
|
lv_arc_set_end_angle(window->getLvObj(), angle);
|
|
}
|
|
|
|
bool LvglWidgetArc::callRefs(lua_State *L)
|
|
{
|
|
if (!pcallUpdate1Int(L, getStartAngleFunction,
|
|
[=](int val) { setStartAngle(val); }))
|
|
return false;
|
|
if (!pcallUpdate1Int(L, getEndAngleFunction,
|
|
[=](int val) { setEndAngle(val); }))
|
|
return false;
|
|
return LvglWidgetRoundObject::callRefs(L);
|
|
}
|
|
|
|
void LvglWidgetArc::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, getStartAngleFunction);
|
|
clearRef(L, getEndAngleFunction);
|
|
LvglWidgetRoundObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetArc::build(lua_State *L)
|
|
{
|
|
// Reset position to corner
|
|
setPos(x, y);
|
|
// Set width & height
|
|
setRadius(radius);
|
|
window =
|
|
new Window(lvglManager->getCurrentParent(), {x, y, w, h}, lv_arc_create);
|
|
lv_obj_add_flag(window->getLvObj(), LV_OBJ_FLAG_EVENT_BUBBLE);
|
|
lv_obj_clear_flag(window->getLvObj(), LV_OBJ_FLAG_CLICKABLE);
|
|
setColor(color);
|
|
lv_arc_set_bg_angles(window->getLvObj(), 0, 360);
|
|
lv_arc_set_range(window->getLvObj(), 0, 360);
|
|
lv_arc_set_angles(window->getLvObj(), 0, 360);
|
|
setStartAngle(startAngle);
|
|
setEndAngle(endAngle);
|
|
lv_obj_remove_style(window->getLvObj(), NULL, LV_PART_KNOB);
|
|
lv_obj_set_style_arc_opa(window->getLvObj(), LV_OPA_TRANSP, LV_PART_MAIN);
|
|
lv_obj_set_style_arc_width(window->getLvObj(), thickness, LV_PART_MAIN);
|
|
lv_obj_set_style_arc_opa(window->getLvObj(), LV_OPA_COVER, LV_PART_INDICATOR);
|
|
lv_obj_set_style_arc_width(window->getLvObj(), thickness, LV_PART_INDICATOR);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetImage::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "file")) {
|
|
filename = luaL_checkstring(L, -1);
|
|
} else if (!strcmp(key, "fill")) {
|
|
fillFrame = lua_toboolean(L, -1);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetImage::build(lua_State *L)
|
|
{
|
|
window = new StaticImage(lvglManager->getCurrentParent(), {x, y, w, h},
|
|
filename.c_str(), fillFrame);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class LvglWidgetScaleIndicator : public LvglWidgetObjectBase
|
|
{
|
|
public:
|
|
LvglWidgetScaleIndicator() {}
|
|
|
|
virtual void buildIndicator(lv_obj_t *parent, lv_meter_scale_t *scale) = 0;
|
|
|
|
protected:
|
|
lv_obj_t *meter = nullptr;
|
|
lv_meter_indicator_t *indic = nullptr;
|
|
};
|
|
|
|
class LvglWidgetScaleArc : public LvglWidgetScaleIndicator
|
|
{
|
|
public:
|
|
LvglWidgetScaleArc(lua_State *L) { getParams(L, -1); }
|
|
|
|
bool callRefs(lua_State *L) override
|
|
{
|
|
if (!pcallUpdate1Int(L, getStartPosFunction, [=](int val) {
|
|
lv_meter_set_indicator_start_value(meter, indic, val);
|
|
}))
|
|
return false;
|
|
if (!pcallUpdate1Int(L, getEndPosFunction, [=](int val) {
|
|
lv_meter_set_indicator_end_value(meter, indic, val);
|
|
}))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void clearRefs(lua_State *L) override
|
|
{
|
|
clearRef(L, getStartPosFunction);
|
|
clearRef(L, getEndPosFunction);
|
|
}
|
|
|
|
void buildIndicator(lv_obj_t *parent, lv_meter_scale_t *scale) override
|
|
{
|
|
meter = parent;
|
|
|
|
indic =
|
|
lv_meter_add_arc(meter, scale, w, makeLvColor(flagsRGB(color)), rmod);
|
|
if (hasStart) lv_meter_set_indicator_start_value(meter, indic, startPos);
|
|
if (hasEnd) lv_meter_set_indicator_end_value(meter, indic, endPos);
|
|
}
|
|
|
|
protected:
|
|
uint8_t w = 0;
|
|
int8_t rmod = 0;
|
|
LcdFlags color = COLOR_THEME_PRIMARY1;
|
|
bool hasStart = false, hasEnd = false;
|
|
int16_t startPos = 0, endPos = 0;
|
|
|
|
int getStartPosFunction = 0;
|
|
int getEndPosFunction = 0;
|
|
|
|
void parseParam(lua_State *L, const char *key) override
|
|
{
|
|
if (!strcmp(key, "w")) {
|
|
w = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "rmod")) {
|
|
rmod = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "startPos")) {
|
|
if (lua_isfunction(L, -1))
|
|
getStartPosFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
else {
|
|
hasStart = true;
|
|
startPos = luaL_checkinteger(L, -1);
|
|
}
|
|
} else if (!strcmp(key, "endPos")) {
|
|
if (lua_isfunction(L, -1))
|
|
getEndPosFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
else {
|
|
hasEnd = true;
|
|
endPos = luaL_checkinteger(L, -1);
|
|
}
|
|
} else if (!strcmp(key, "color")) {
|
|
color = luaL_checkunsigned(L, -1);
|
|
}
|
|
}
|
|
};
|
|
|
|
class LvglWidgetScaleLines : public LvglWidgetScaleIndicator
|
|
{
|
|
public:
|
|
LvglWidgetScaleLines(lua_State *L) { getParams(L, -1); }
|
|
|
|
bool callRefs(lua_State *L) override
|
|
{
|
|
if (!pcallUpdate1Int(L, getStartPosFunction, [=](int val) {
|
|
lv_meter_set_indicator_start_value(meter, indic, val);
|
|
}))
|
|
return false;
|
|
if (!pcallUpdate1Int(L, getEndPosFunction, [=](int val) {
|
|
lv_meter_set_indicator_end_value(meter, indic, val);
|
|
}))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void clearRefs(lua_State *L) override
|
|
{
|
|
clearRef(L, getStartPosFunction);
|
|
clearRef(L, getEndPosFunction);
|
|
}
|
|
|
|
void buildIndicator(lv_obj_t *parent, lv_meter_scale_t *scale) override
|
|
{
|
|
meter = parent;
|
|
|
|
indic = lv_meter_add_scale_lines(
|
|
meter, scale, makeLvColor(flagsRGB(startColor)),
|
|
makeLvColor(flagsRGB(endColor)), localFade, wmod);
|
|
if (hasStart) lv_meter_set_indicator_start_value(meter, indic, startPos);
|
|
if (hasEnd) lv_meter_set_indicator_end_value(meter, indic, endPos);
|
|
}
|
|
|
|
protected:
|
|
int8_t wmod = 0;
|
|
LcdFlags startColor = COLOR_THEME_PRIMARY1, endColor = COLOR_THEME_PRIMARY1;
|
|
bool hasStart = false, hasEnd = false;
|
|
int16_t startPos = 0, endPos = 0;
|
|
bool localFade = false;
|
|
|
|
int getStartPosFunction = 0;
|
|
int getEndPosFunction = 0;
|
|
|
|
void parseParam(lua_State *L, const char *key) override
|
|
{
|
|
if (!strcmp(key, "wmod")) {
|
|
wmod = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "startPos")) {
|
|
if (lua_isfunction(L, -1)) {
|
|
getStartPosFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
hasStart = true;
|
|
startPos = luaL_checkinteger(L, -1);
|
|
}
|
|
} else if (!strcmp(key, "endPos")) {
|
|
if (lua_isfunction(L, -1)) {
|
|
getEndPosFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
hasEnd = true;
|
|
endPos = luaL_checkinteger(L, -1);
|
|
}
|
|
} else if (!strcmp(key, "startColor")) {
|
|
startColor = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "endColor")) {
|
|
endColor = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "localFade")) {
|
|
localFade = lua_toboolean(L, -1);
|
|
}
|
|
}
|
|
};
|
|
|
|
class LvglWidgetScaleNeedle : public LvglWidgetScaleIndicator
|
|
{
|
|
public:
|
|
LvglWidgetScaleNeedle(lua_State *L) { getParams(L, -1); }
|
|
|
|
bool callRefs(lua_State *L) override
|
|
{
|
|
if (!pcallUpdate1Int(L, getPosFunction, [=](int val) {
|
|
lv_meter_set_indicator_value(meter, indic, val);
|
|
}))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void clearRefs(lua_State *L) override { clearRef(L, getPosFunction); }
|
|
|
|
void buildIndicator(lv_obj_t *parent, lv_meter_scale_t *scale) override
|
|
{
|
|
meter = parent;
|
|
|
|
indic = lv_meter_add_needle_line(meter, scale, w,
|
|
makeLvColor(flagsRGB(color)), rmod);
|
|
}
|
|
|
|
protected:
|
|
uint8_t w = 0;
|
|
int8_t rmod = 0;
|
|
LcdFlags color = COLOR_THEME_PRIMARY1;
|
|
|
|
int getPosFunction = 0;
|
|
|
|
void parseParam(lua_State *L, const char *key) override
|
|
{
|
|
if (!strcmp(key, "w")) {
|
|
w = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "rmod")) {
|
|
rmod = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "color")) {
|
|
color = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "pos")) {
|
|
getPosFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
}
|
|
}
|
|
};
|
|
|
|
class LvglWidgetMeterScale : public LvglWidgetObjectBase
|
|
{
|
|
public:
|
|
LvglWidgetMeterScale(lua_State *L) { getParams(L, -1); }
|
|
|
|
bool callRefs(lua_State *L) override
|
|
{
|
|
for (auto it = indicators.cbegin(); it != indicators.cend(); ++it) {
|
|
if (!(*it)->callRefs(L)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void clearRefs(lua_State *L) override
|
|
{
|
|
for (auto it = indicators.cbegin(); it != indicators.cend(); ++it) {
|
|
(*it)->clearRefs(L);
|
|
}
|
|
}
|
|
|
|
void build(lv_obj_t *parent)
|
|
{
|
|
meter = parent;
|
|
lv_meter_scale_t *scale = lv_meter_add_scale(meter);
|
|
|
|
if (ticks) {
|
|
lv_meter_set_scale_ticks(meter, scale, ticks, tickWidth, tickLen,
|
|
makeLvColor(flagsRGB(tickColor)));
|
|
if (majorNth)
|
|
lv_meter_set_scale_major_ticks(
|
|
meter, scale, majorNth, majorWidth, majorLen,
|
|
makeLvColor(flagsRGB(majorColor)), labelGap);
|
|
}
|
|
|
|
lv_meter_set_scale_range(meter, scale, scaleMin, scaleMax, scaleAngle,
|
|
scaleRotate);
|
|
|
|
if (centerDotSize > 0) {
|
|
lv_obj_set_style_size(meter, centerDotSize, LV_PART_INDICATOR);
|
|
lv_obj_set_style_bg_color(meter, makeLvColor(flagsRGB(centerDotColor)),
|
|
LV_PART_INDICATOR);
|
|
lv_obj_set_style_bg_opa(meter, LV_OPA_COVER, LV_PART_INDICATOR);
|
|
lv_obj_set_style_radius(meter, LV_RADIUS_CIRCLE, LV_PART_INDICATOR);
|
|
}
|
|
|
|
for (auto it = indicators.cbegin(); it != indicators.cend(); ++it) {
|
|
(*it)->buildIndicator(meter, scale);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
lv_obj_t *meter;
|
|
std::vector<LvglWidgetScaleIndicator *> indicators;
|
|
|
|
int16_t scaleMin = 0, scaleMax = 100, scaleAngle = 360, scaleRotate = 0;
|
|
uint8_t ticks = 0, majorNth = 0;
|
|
uint8_t tickWidth = 0, majorWidth = 0;
|
|
uint8_t tickLen = 0, majorLen = 0;
|
|
LcdFlags tickColor = COLOR_THEME_PRIMARY1, majorColor = COLOR_THEME_PRIMARY1;
|
|
uint8_t labelGap = 0, centerDotSize = 0;
|
|
LcdFlags centerDotColor = COLOR_THEME_PRIMARY1;
|
|
|
|
void parseParam(lua_State *L, const char *key) override
|
|
{
|
|
if (!strcmp(key, "ticks")) {
|
|
ticks = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "tickWidth")) {
|
|
tickWidth = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "tickLen")) {
|
|
tickLen = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "tickColor")) {
|
|
tickColor = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "majorNth")) {
|
|
majorNth = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "majorWidth")) {
|
|
majorWidth = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "majorLen")) {
|
|
majorLen = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "majorColor")) {
|
|
majorColor = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "labelGap")) {
|
|
labelGap = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "min")) {
|
|
scaleMin = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "max")) {
|
|
scaleMax = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "angle")) {
|
|
scaleAngle = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "rotate")) {
|
|
scaleRotate = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "dotSize")) {
|
|
centerDotSize = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "dotColor")) {
|
|
centerDotColor = luaL_checkunsigned(L, -1);
|
|
} else if (!strcmp(key, "indicators")) {
|
|
luaL_checktype(L, -1, LUA_TTABLE);
|
|
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
|
lua_getfield(L, -1, "type");
|
|
const char *key = lua_tostring(L, -1);
|
|
lua_pop(L, 1);
|
|
if (!strcmp(key, "arc")) {
|
|
indicators.push_back(new LvglWidgetScaleArc(L));
|
|
} else if (!strcmp(key, "lines")) {
|
|
indicators.push_back(new LvglWidgetScaleLines(L));
|
|
} else if (!strcmp(key, "needle")) {
|
|
indicators.push_back(new LvglWidgetScaleNeedle(L));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
void LvglWidgetMeter::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "scales")) {
|
|
luaL_checktype(L, -1, LUA_TTABLE);
|
|
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
|
scales.push_back(new LvglWidgetMeterScale(L));
|
|
}
|
|
} else {
|
|
LvglWidgetRoundObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
bool LvglWidgetMeter::callRefs(lua_State *L)
|
|
{
|
|
for (auto it = scales.cbegin(); it != scales.cend(); ++it) {
|
|
if (!(*it)->callRefs(L)) return false;
|
|
}
|
|
return LvglWidgetRoundObject::callRefs(L);
|
|
}
|
|
|
|
void LvglWidgetMeter::clearRefs(lua_State *L)
|
|
{
|
|
for (auto it = scales.cbegin(); it != scales.cend(); ++it) {
|
|
(*it)->clearRefs(L);
|
|
}
|
|
LvglWidgetRoundObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetMeter::build(lua_State *L)
|
|
{
|
|
window = new Window(lvglManager->getCurrentParent(),
|
|
{x - radius, y - radius, radius * 2, radius * 2},
|
|
lv_meter_create);
|
|
|
|
lv_obj_t *meter = window->getLvObj();
|
|
|
|
lv_obj_add_flag(meter, LV_OBJ_FLAG_EVENT_BUBBLE);
|
|
lv_obj_clear_flag(meter, LV_OBJ_FLAG_CLICKABLE);
|
|
|
|
for (auto it = scales.cbegin(); it != scales.cend(); ++it) {
|
|
(*it)->build(meter);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetTextButton::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "text")) {
|
|
txt = luaL_checkstring(L, -1);
|
|
} else if (!strcmp(key, "press")) {
|
|
pressFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetTextButton::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, pressFunction);
|
|
LvglWidgetObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetTextButton::setText(const char *s)
|
|
{
|
|
uint32_t h = hash(s, strlen(s));
|
|
if (h != textHash) {
|
|
txt = s;
|
|
textHash = h;
|
|
((TextButton *)window)->setText(s);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetTextButton::build(lua_State *L)
|
|
{
|
|
window =
|
|
new TextButton(lvglManager->getCurrentParent(), {x, y, w, h}, txt, [=]() {
|
|
pcallSimpleFunc(L, pressFunction);
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetToggleSwitch::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "get")) {
|
|
getStateFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else if (!strcmp(key, "set")) {
|
|
setStateFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetToggleSwitch::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, getStateFunction);
|
|
clearRef(L, setStateFunction);
|
|
LvglWidgetObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetToggleSwitch::build(lua_State *L)
|
|
{
|
|
window = new ToggleSwitch(
|
|
lvglManager->getCurrentParent(), {x, y, 0, 0},
|
|
[=]() { return pcallGetIntVal(L, getStateFunction); },
|
|
[=](uint8_t val) { pcallSetIntVal(L, setStateFunction, val); });
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetConfirmDialog::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "title")) {
|
|
title = luaL_checkstring(L, -1);
|
|
} else if (!strcmp(key, "message")) {
|
|
message = luaL_checkstring(L, -1);
|
|
} else if (!strcmp(key, "confirm")) {
|
|
confirmFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else if (!strcmp(key, "cancel")) {
|
|
cancelFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetConfirmDialog::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, confirmFunction);
|
|
clearRef(L, cancelFunction);
|
|
LvglWidgetObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetConfirmDialog::build(lua_State *L)
|
|
{
|
|
window = new ConfirmDialog(
|
|
MainWindow::instance(), title, message,
|
|
[=]() { pcallSimpleFunc(L, confirmFunction); },
|
|
[=]() { pcallSimpleFunc(L, cancelFunction); });
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetTextEdit::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "value")) {
|
|
txt = luaL_checkstring(L, -1);
|
|
} else if (!strcmp(key, "length")) {
|
|
maxLen = luaL_checkinteger(L, -1);
|
|
if (maxLen > 128) maxLen = 128;
|
|
if (maxLen <= 0) maxLen = 32;
|
|
} else if (!strcmp(key, "set")) {
|
|
setFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetTextEdit::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, setFunction);
|
|
LvglWidgetObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetTextEdit::build(lua_State *L)
|
|
{
|
|
strcpy(value, txt);
|
|
if (h == LV_SIZE_CONTENT) h = 0;
|
|
window = new TextEdit(lvglManager->getCurrentParent(), {x, y, w, h}, value,
|
|
maxLen, [=]() {
|
|
if (setFunction) {
|
|
int t = lua_gettop(L);
|
|
PROTECT_LUA()
|
|
{
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, setFunction);
|
|
lua_pushstring(L, value);
|
|
bool rv = lua_pcall(L, 1, 0, 0) == 0;
|
|
if (!rv) {
|
|
lvglManager->luaShowError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lvglManager->luaShowError();
|
|
}
|
|
UNPROTECT_LUA();
|
|
lua_settop(L, t);
|
|
}
|
|
});
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetNumberEdit::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "min")) {
|
|
min = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "max")) {
|
|
max = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "get")) {
|
|
getFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else if (!strcmp(key, "set")) {
|
|
setFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else if (!strcmp(key, "display")) {
|
|
dispFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetNumberEdit::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, getFunction);
|
|
clearRef(L, setFunction);
|
|
clearRef(L, dispFunction);
|
|
LvglWidgetObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetNumberEdit::build(lua_State *L)
|
|
{
|
|
if (h == LV_SIZE_CONTENT) h = 0;
|
|
window = new NumberEdit(
|
|
lvglManager->getCurrentParent(), {x, y, w, h}, min, max,
|
|
[=]() { return pcallGetIntVal(L, getFunction); },
|
|
[=](int val) { pcallSetIntVal(L, setFunction, val); });
|
|
if (dispFunction) {
|
|
((NumberEdit *)window)->setDisplayHandler([=](int val) {
|
|
const char *s = "???";
|
|
int t = lua_gettop(L);
|
|
PROTECT_LUA()
|
|
{
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, dispFunction);
|
|
lua_pushinteger(L, val);
|
|
bool rv = lua_pcall(L, 1, 1, 0) == 0;
|
|
if (rv) {
|
|
s = luaL_checkstring(L, -1);
|
|
} else {
|
|
lvglManager->luaShowError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lvglManager->luaShowError();
|
|
}
|
|
UNPROTECT_LUA();
|
|
lua_settop(L, t);
|
|
return s;
|
|
});
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetChoice::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "title")) {
|
|
title = luaL_checkstring(L, -1);
|
|
} else if (!strcmp(key, "values")) {
|
|
luaL_checktype(L, -1, LUA_TTABLE);
|
|
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
|
values.push_back(lua_tostring(L, -1));
|
|
}
|
|
} else if (!strcmp(key, "get")) {
|
|
getFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else if (!strcmp(key, "set")) {
|
|
setFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetChoice::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, getFunction);
|
|
clearRef(L, setFunction);
|
|
LvglWidgetObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetChoice::build(lua_State *L)
|
|
{
|
|
window = new Choice(
|
|
lvglManager->getCurrentParent(), {x, y, w, h}, values, 0,
|
|
values.size() - 1, [=]() { return pcallGetIntVal(L, getFunction) - 1; },
|
|
[=](int val) { pcallSetIntVal(L, setFunction, val + 1); }, title.c_str());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LvglWidgetSlider::parseParam(lua_State *L, const char *key)
|
|
{
|
|
if (!strcmp(key, "get")) {
|
|
getValueFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else if (!strcmp(key, "set")) {
|
|
setValueFunction = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
} else if (!strcmp(key, "min")) {
|
|
vmin = luaL_checkinteger(L, -1);
|
|
} else if (!strcmp(key, "max")) {
|
|
vmax = luaL_checkinteger(L, -1);
|
|
} else {
|
|
LvglWidgetObject::parseParam(L, key);
|
|
}
|
|
}
|
|
|
|
void LvglWidgetSlider::clearRefs(lua_State *L)
|
|
{
|
|
clearRef(L, getValueFunction);
|
|
clearRef(L, setValueFunction);
|
|
LvglWidgetObject::clearRefs(L);
|
|
}
|
|
|
|
void LvglWidgetSlider::build(lua_State *L)
|
|
{
|
|
window = new Slider(
|
|
lvglManager->getCurrentParent(), w, vmin, vmax,
|
|
[=]() { return pcallGetIntVal(L, getValueFunction); },
|
|
[=](uint8_t val) { pcallSetIntVal(L, setValueFunction, val); });
|
|
window->setPos(x, y);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|