Replies: 36 comments 18 replies
-
Please ensure the old API remains supported "as is". I do not have either the time or energy to migrate a complex widget (i.e. the INAV Lua to a new API), and I doubt I'll easily find a new maintainer to do so. I don't mean to discourage you from this endeavour, which I'm sure will be appreciated by many. However, for the reluctant maintainer of a legacy OTX/ETX widget, backwards compatibility is everything. |
Beta Was this translation helpful? Give feedback.
-
The current plan is to slowly add the new API over the next releases and then have at least one release with both APIs. How we will maintain two API remains to be seen. |
Beta Was this translation helpful? Give feedback.
-
@philmoz good job! As others said, keep the Lcd API the same. I guess the idea is to get this closer to to how the /WIDGETS/LuiGui works. Some things not necessary needs to be only color.. if we can get access to similar components in B&W radios, the code will look similar from LUA point of view regardless if it is B&W or color. |
Beta Was this translation helpful? Give feedback.
-
great POC, looks promising, it may give a boost to the color screens apps (happy to see that we are talking only on color screens!) also, the "layout=layout" looks to me very limited |
Beta Was this translation helpful? Give feedback.
-
Currently the layout function serves two purposes - first it lets the firmware code know the widget wants to use the Lvgl UI. This turns off the automatic erase of the underlying screen area. Secondly it is called whenever the widget size changes so you can create or modify the Lvgl objects used to define your widget. How you setup the Lvgl objects to create your actual UI is up to you. If you want multiple layouts that should be possible - the API will allow you to create frames (empty Lvgl containers) that can then contain other UI objects. Individual objects (including frames) can be shown or hidden as needed. I may end up removing the 'layout' function as the existing 'update' function could serve the same purpose. In this case the 'create' function would then need to set some flag to turn on Lvgl mode. I hope to be able to expose the styled objects used in the main UI - buttons, toggle switches, sliders etc. However I need to figure out how the interaction with these elements is handled. I.E. when you tap a button how does this get to the widget script code. |
Beta Was this translation helpful? Give feedback.
-
Pleased to see that someone is thinking about how to get away from raw drawing UI!
|
Beta Was this translation helpful? Give feedback.
-
While this might simplify the Lua script code I suspect it could have performance issues. The data structure do not allow direct binding to radio or model variables (due to bitfields being used). So binding must go though getter/setter functions. This would mean that, instead of a single call from the C code to the Lua refresh function, each object would need to make one or two such calls. |
Beta Was this translation helpful? Give feedback.
-
Indeed I believe as well that it will smarter to getter/setter from the lua to the firmware, as it simply complex implementation and lockups |
Beta Was this translation helpful? Give feedback.
-
can we see a text that the font is growing slowly like the rectangle? |
Beta Was this translation helpful? Give feedback.
-
Oh yeah I for sure know it isn't easy to implement in EdgeTX because the infrastructure isn't there but a thin wrapper around lvgl doesn't change much from the lua developer standpoint. Instead of just drawing text in one line (current lua) you'd just be changing it to become multiple lines (one to create the control and then set attributes, then one to update the text). I know that this draws faster but is that the only goal of this? If someone is going to add an entire new system to the lua, I feel like there's a great opportunity to not have to manage all the same stuff an employ a more verbose syntax to get those values on the screen but perform better. Binding a control to a source eliminates all the code of updating the text, caching the ID to get the value faster, comparing the previous value to see if it needs to be updated, etc. Maybe I'm just a die hard event-driven programmer though haha. I like what you've got so far (although I'm unsure about the 4 numbers in the middle which will likely have me pulling up the documentation every time to remember what order the 4 values are in) but let's blue sky a little before we start discarding ideas just because the current codebase doesn't already support it 😀 It doesn't support this either, but you wrote it in no time at all so now it does! |
Beta Was this translation helpful? Give feedback.
-
Would using a table for the parameters be preferred: lvgl.label({text="CTR", x=0, y=0, w=0, h=0, color=widget.options.Color, font=MIDSIZE}) |
Beta Was this translation helpful? Give feedback.
-
It certainly is clearer and I like the optionality aspect, but after thinking about it for a bit the original form might be better just strictly on its lower memory footprint. Wouldn't passing tables for every control greatly increase the size of the compiled script lua code in RAM compared to just passing numbers? I do love embedded programming where we have to think "well that seems nice but it also takes 1KB extra sooo..." 😅 |
Beta Was this translation helpful? Give feedback.
-
Is there a artifact (build) or branch with code for what you do @philmoz? |
Beta Was this translation helpful? Give feedback.
-
API summary moved to PR #4887 |
Beta Was this translation helpful? Give feedback.
-
A couple of other notes:
|
Beta Was this translation helpful? Give feedback.
-
Assuming the CPU usage logic I added is correct then: Direct draw BattAnalog widget - total CPU usage (mixer, widgets, scripts, etc) = 100% |
Beta Was this translation helpful? Give feedback.
-
Adding the FPS into the mix makes the performance improvement even more dramatic. The Lvgl widget runs at 20 FPS (the max rate the gui task runs at) with 64% CPU to spare.. |
Beta Was this translation helpful? Give feedback.
-
awesome! |
Beta Was this translation helpful? Give feedback.
-
There is a small increase in memory usage: Compiled .luac files (from TX16S): Max memory used when running: |
Beta Was this translation helpful? Give feedback.
-
For reference here is the current version of the Lvgl converted BattAnalog script. |
Beta Was this translation helpful? Give feedback.
-
to allow the functions to be more organized, in autocomplete & documentation
it is better to use:
|
Beta Was this translation helpful? Give feedback.
-
What about the FPS? |
Beta Was this translation helpful? Give feedback.
-
Some progress on supporting EdgeTX styled controls in a stand alone script. standalone.script.mp4 |
Beta Was this translation helpful? Give feedback.
-
Very cool! |
Beta Was this translation helpful? Give feedback.
-
Well done 👍 |
Beta Was this translation helpful? Give feedback.
-
Will the lvgl widgets be available to the lua script? |
Beta Was this translation helpful? Give feedback.
-
I've added support for the Lvgl 'meter' widget. lvgl.meters.mp4Widget script used to generate above video: local opts = {
}
local wgt
local function create(zone, opts)
wgt = { zone=zone, opts=opts, counter=0, bg_ctr=0 }
return wgt
end
local function update(wgt, opts)
wgt.opts = opts
lvgl.clear()
local lyt = {
{type="rectangle", x=0, y=0, w=120, h=120, color=WHITE, filled=true, rounded=60,
children={
{type="meter", x=60 , y=60, radius=60,
scales={{
min=-100, max=100, angle=270, rotate=135,
ticks=41, tickWidth=1, tickLen=10, tickColor=COLOR_THEME_PRIMARY1,
majorNth=8, majorWidth=2, majorLen=15, majorColor=COLOR_THEME_PRIMARY1, labelGap=10,
dotSize=6, dotColor=ORANGE,
indicators={
{type="arc", w=2, color=BLUE, rmod=0, startPos=-100, endPos=-60},
{type="arc", w=2, color=RED, rmod=0, startPos=60, endPos=100},
{type="lines", startColor=BLUE, endColor=BLUE, localFade=true, wmod=0, startPos=-100, endPos=-60},
{type="lines", startColor=RED, endColor=RED, localFade=true, wmod=0, startPos=60, endPos=100},
{type="needle", w=1, rmod=-10, color=BLACK, getPos=(function() return -100 + wgt.counter % 200 end)},
{type="needle", w=1, rmod=-10, color=GREEN, getPos=(function() return 100 - wgt.counter % 200 end)},
}},
},
},
}
},
{type="rectangle", x=120, y=0, w=120, h=120, color=WHITE, filled=true, rounded=60,
children={
{type="meter", x=60 , y=60, radius=60,
scales={{
min=0, max=100, angle=270, rotate=90,
ticks=11, tickWidth=1, tickLen=15, tickColor=COLOR_THEME_PRIMARY1,
majorNth=2, majorWidth=1, majorLen=15, majorColor=COLOR_THEME_PRIMARY1, labelGap=15,
indicators={
{type="arc", w=5, color=RED, rmod=0, startPos=0, getEnd=(function() return wgt.counter % 100 end)},
{type="arc", w=5, color=GREEN, rmod=-5, startPos=0, getEnd=(function() return wgt.counter % 200 / 2 end)},
{type="arc", w=5, color=BLUE, rmod=-10, startPos=0, getEnd=(function() return wgt.counter % 300 / 3 end)},
}}
},
},
}
},
{type="rectangle", x=240, y=0, w=120, h=120, color=WHITE, filled=true, rounded=60,
children={
{type="meter", x=60 , y=60, radius=60,
scales={
{
min=0, max=60, angle=360, rotate=270,
ticks=61, tickWidth=1, tickLen=10, tickColor=COLOR_THEME_PRIMARY1,
indicators={
{type="needle", w=1, rmod=0, color=BLACK, getPos=(function() return wgt.counter % 60 end)},
}
},
{
min=1, max=12, angle=330, rotate=300,
ticks=12, tickWidth=0, tickLen=0,
majorNth=1, majorWidth=1, majorLen=15, majorColor=COLOR_THEME_PRIMARY1, labelGap=10,
dotSize=6, dotColor=BLACK,
indicators={
{type="needle", w=1, rmod=-20, color=BLACK, getPos=(function() return wgt.counter % 720 / 60 + 1 end)},
}
},
},
},
}
},
}
local refs = lvgl.build(lyt)
end
local function background(wgt)
wgt.bg_ctr = wgt.bg_ctr + 1
end
local function refresh(wgt)
wgt.counter = wgt.counter + 1
end
return { name="Lvgl Meters", options=opts, create=create, update=update, refresh=refresh, background=background, useLvgl=true } |
Beta Was this translation helpful? Give feedback.
-
All I have done is expose the properties of the Lvgl 'meter' widget which you asked for. You can create any 'meter' layout you want using all these properties as described in the Lvgl documentation for the widget. The Lvgl 'meter' widget is a complex object and can only be built using the properties it provides. Things like the 'needle' type come from Lvgl not the EdgeTx firmware. |
Beta Was this translation helpful? Give feedback.
-
I have made a start on being able to use Lvgl for the UI in widgets (obviously color radios only).
This requires a new API to define the UI layout, and is incompatible with the existing direct drawing API - a widget can use one or the other; but not both.
For example, this script:
Produces this output:
Instead of redrawing the widget every time refresh is called, the layout is done once (or when the size changes), then the refresh function only needs to update the attributes of the Lvgl objects.
I would like to get feedback on what the new API should look like - so any thoughts here would be appreciated.
At the moment interactive elements are not supported (i.e. buttons, text boxes, etc); but should be possible in the future.
Beta Was this translation helpful? Give feedback.
All reactions