- First complete version of firmware. Currently being tested in the rehearsal room

- Added bunch of screens, fonts and images
 - Added script to read out frame buffer (function currently disabled in Firmware)
This commit is contained in:
2025-10-26 20:57:58 +01:00
parent 90bca063e6
commit 89c875e38f
62 changed files with 4668 additions and 489 deletions

View File

@@ -27,17 +27,20 @@ static const int _LEFT = -1;
static const int _UP = -1;
static const int _DOWN = +1;
static int16_t _Menu_Hierarchical_Current_Y = 0; // Current animated Y position of menu
static int16_t _Menu_Hierarchical_Scroll_Y = 0; // Current animated scroll offset
static float _Menu_Hierarchical_Transition_Progress = 0.0f; // Selection transition progress (0.0-1.0)
static int32_t _Menu_Hierarchical_Last_Selected = -1; // Previous selected item for transition detection
static int16_t _Menu_Hierarchical_Current_Y = 0; // Current animated Y position of menu
static int16_t _Menu_Hierarchical_Scroll_Y = 0; // Current animated scroll offset
static float _Menu_Hierarchical_Transition_Progress = 0.0f; // Selection transition progress (0.0-1.0)
static int32_t _Menu_Hierarchical_Last_Selected = -1; // Previous selected item for transition detection
static int16_t _Menu_Select_Current_Y = 0;
static int16_t _Menu_Icon_Row_Current_X = 0;
static int16_t _Select_YesNo_Current_X = 0;
static int16_t _Select_List_Current_Y = 0;
static float _Entry_Indicator_Current_Angle = 0.0f;
static int16_t _Entry_Indicator_Current_X = 0;
static int16_t _Menu_Select_Current_Y = 0;
static int16_t _Menu_Icon_Row_Current_X = 0;
static int16_t _Select_YesNo_Current_X = 0;
static int32_t _Select_List_Target_Scroll_Y = 0;
static int32_t _Select_List_Current_Scroll_Y = 0;
static float _Entry_Indicator_Current_Angle = 0.0f;
static int16_t _Entry_Indicator_Current_X = 0;
// ============================================================================================
@@ -49,17 +52,18 @@ static Menu_Transition_Direction Display_Render_Complex_Menu_Hierarchical_Detect
static void Display_Render_Complex_Menu_Hierarchical_Auto_Detect_Changes(Object_Menu_Hierarchical* menu_hierarchical);
static void Display_Render_Complex_Menu_Hierarchical_Update_Transition_Animation(Object_Menu_Hierarchical* menu_hierarchical);
static void Display_Render_Complex_Menu_Hierarchical_Update_All_Animations(Object_Menu_Hierarchical* menu_hierarchical);
static void Display_Render_Complex_Menu_Hierarchical_Update_Animation(const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Single_Menu(Coordinates* coordinates, const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, Configuration_Menu_Hierarchical* config, int16_t x_offset);
static void Display_Render_Complex_Menu_Hierarchical_Title(Coordinates* coordinates, const char* title, Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Items(Coordinates* coordinates, const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Single_Item(Coordinates* coordinates, const Menu_Item* item, int32_t item_index, int32_t selected_item, int16_t item_y, Display_Color item_color, float scale_factor, Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Selection_Box(Coordinates* coordinates, int32_t selected_item, int32_t scroll_offset, Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Scroll_Indicators(Coordinates* coordinates, const Menu_List* current_list, int32_t scroll_offset, Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Update_Animation(const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Single_Menu(Coordinates* coordinates, const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config, int16_t x_offset);
static void Display_Render_Complex_Menu_Hierarchical_Title(Coordinates* coordinates, const char* title, const Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Items(Coordinates* coordinates, const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Single_Item(Coordinates* coordinates, const Menu_Item* item, int32_t item_index, int32_t selected_item, int16_t item_y, Display_Color item_color, float scale_factor, const Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Selection_Box(Coordinates* coordinates, int32_t selected_item, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config);
static void Display_Render_Complex_Menu_Hierarchical_Scroll_Indicators(Coordinates* coordinates, const Menu_List* current_list, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config);
static int32_t Display_Render_Complex_Select_List_Calculate_Scroll_Offset(uint32_t selected_entry, uint32_t total_entries, uint16_t visible_items);
static float Display_Render_Complex_Select_RGB_Calculate_Progress_Ring_Angle(uint8_t value, uint8_t min_value, uint8_t max_value);
static void Display_Render_Complex_Entry_Indicator_Arc(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, Configuration_Entry_Indicator* config);
static void Display_Render_Complex_Entry_Indicator_Dot(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, Configuration_Entry_Indicator* config);
static void Display_Render_Complex_Entry_Indicator_Arc(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, const Configuration_Entry_Indicator* config);
static void Display_Render_Complex_Entry_Indicator_Dot(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, const Configuration_Entry_Indicator* config);
/*******************************************************************
@@ -115,13 +119,13 @@ void Display_Render_Complex_Value_Bar_Arc(Coordinates* coordinates, Object_Value
{
Object_Value_Bar_Arc* V = value_bar;
if(*V->Value != V->Current)
if(*(V->Value )!= V->Current)
{
// Need to drcrease
if(*V->Value < V->Current)
// Need to decrease
if(*(V->Value) < V->Current)
{
if(abs(*V->Value - V->Current) <= V->Delta_Dec) {
V->Current = *V->Value;
if((V->Current - *(V->Value)) <= V->Delta_Dec) {
V->Current = *(V->Value);
}
else {
V->Current -= V->Delta_Dec;
@@ -130,8 +134,8 @@ void Display_Render_Complex_Value_Bar_Arc(Coordinates* coordinates, Object_Value
// Need to increase
else
{
if(abs(*V->Value - V->Current) <= V->Delta_Inc) {
V->Current = *V->Value;
if((*(V->Value) - V->Current) <= V->Delta_Inc) {
V->Current = *(V->Value);
}
else {
V->Current += V->Delta_Inc;
@@ -335,7 +339,7 @@ void Display_Render_Complex_Menu_Icon_Row_Set(uint32_t initially_selected_item,
_Menu_Icon_Row_Current_X = (DISPLAY_WIDTH >> 1) - initially_selected_item * icon_space_width;
}
void Display_Render_Complex_Menu_Icon_Row(Coordinates* coordinates, Icon_Row_Item* items, uint32_t item_count, uint32_t selected_item, Configuration_Menu_Icon_Row* config)
void Display_Render_Complex_Menu_Icon_Row(Coordinates* coordinates, Icon_Row_Item* items, uint32_t item_count, uint32_t selected_item, const Configuration_Menu_Icon_Row* config)
{
int16_t X_Target = coordinates->X + DISPLAY_X_CENTER - selected_item * config->Icon_Space_Width;
@@ -545,7 +549,7 @@ void Display_Render_Complex_Menu_Ring(Coordinates* coordinates, Object_Menu_Ring
void Display_Render_Complex_Menu_Hierarchical(Coordinates* coordinates, Object_Menu_Hierarchical* menu_hierarchical)
{
Configuration_Menu_Hierarchical* Config = menu_hierarchical->Config;
const Configuration_Menu_Hierarchical* Config = menu_hierarchical->Config;
if (menu_hierarchical->Current_List == NULL || Config == NULL) {
return;
@@ -587,9 +591,31 @@ void Display_Render_Complex_Menu_Hierarchical(Coordinates* coordinates, Object_M
}
}
void Display_Render_Complex_Select_YesNo(Coordinates* coordinates, char* title, uint32_t title_length, bool value, Configuration_Select_YesNo* config)
void Display_Render_Complex_Select_YesNo_Set(bool value, const Configuration_Select_YesNo* config)
{
if(config == NULL) {
if(config == NULL || config->Value_Font == NULL) {
return;
}
Display_Font_Set_Font(config->Value_Font);
int16_t Width_Yes = Display_Font_Width_String("Yes", 3, DISPLAY_DEFAULT_CHAR_SPACING);
int16_t Width_No = Display_Font_Width_String("No", 2, DISPLAY_DEFAULT_CHAR_SPACING);
int16_t Width_Diff = Width_Yes - Width_No;
int16_t X_Yes = DISPLAY_X_CENTER - Width_Yes - config->Value_Center_X_Offset;
int16_t X_No = DISPLAY_X_CENTER + config->Value_Center_X_Offset;
int16_t Center_Yes = X_Yes + (Width_Yes >> 1);
int16_t Center_No = X_No + (Width_No >> 1);
_Select_YesNo_Current_X = value ? Center_Yes : Center_No;
}
void Display_Render_Complex_Select_YesNo(Coordinates* coordinates, char* title, uint32_t title_length, bool value, const Configuration_Select_YesNo* config)
{
if(config == NULL || config->Value_Font == NULL) {
return;
}
@@ -603,10 +629,6 @@ void Display_Render_Complex_Select_YesNo(Coordinates* coordinates, char* title,
Display_Font_Print_String(Title_X, Title_Y, title, title_length, DISPLAY_DEFAULT_CHAR_SPACING, config->Title_Color);
}
if(config->Value_Font == NULL) {
return;
}
Display_Font_Set_Font(config->Value_Font);
int16_t YesNo_Y = coordinates->Y + config->Value_Y_Center - (Display_Font_Get_Font_Height() >> 1);
@@ -669,64 +691,108 @@ void Display_Render_Complex_Select_YesNo(Coordinates* coordinates, char* title,
}
}
void Display_Render_Complex_Select_List(Coordinates* coordinates, char* list_titles, uint32_t list_entry_count, uint32_t list_char_length, uint32_t selected_entry, Configuration_Select_List* config)
void Display_Render_Complex_Select_List(Coordinates* coordinates, char* list_titles, uint32_t list_entry_count, uint32_t list_char_length, uint32_t selected_entry, uint32_t initial_entry, const Configuration_Select_List* config)
{
if(config == NULL) {
return;
}
if(config->Font == NULL) {
return;
}
if (config == NULL || config->Font == NULL || list_titles == NULL) {
return;
}
Display_Font_Set_Font(config->Font);
int16_t Entry_Height = Display_Font_Get_Font_Height();
int16_t Total_Height = Entry_Height * list_entry_count + config->List_Entry_Y_Gap * (list_entry_count-1);
int16_t Entry_Width = Display_Font_Width_String(&list_titles[0], list_char_length, DISPLAY_DEFAULT_CHAR_SPACING);
int16_t Entry_Height = Display_Font_Get_Font_Height();
int16_t Item_Full_Height = Entry_Height + config->List_Entry_Y_Gap;
int16_t Entry_Width = Display_Font_Width_String(&list_titles[0], list_char_length, DISPLAY_DEFAULT_CHAR_SPACING);
int16_t X_Entires = coordinates->X + DISPLAY_X_CENTER - (Entry_Width >> 1);
int16_t Y = coordinates->Y + DISPLAY_Y_CENTER - (Total_Height >> 1);
// Calculate scroll offset for current selection
int32_t Offset_Items = Display_Render_Complex_Select_List_Calculate_Scroll_Offset(selected_entry, list_entry_count, config->Visible_Items);
_Select_List_Target_Scroll_Y = -Offset_Items * Item_Full_Height;
int16_t Y_Target = Y + selected_entry * (Entry_Height + config->List_Entry_Y_Gap);
for(int16_t i=0;i<list_entry_count;i++)
{
Display_Color Color = config->Color_Not_Selected;
if(i==selected_entry) {
if(_Select_List_Current_Y == Y_Target) {
Color = config->Color_Selected;
}
else {
Color = Display_Color_Interpolate_Float(config->Color_Selected, config->Color_Not_Selected, (float)abs(_Select_List_Current_Y - Y_Target) / (float)Entry_Height);
}
}
Display_Font_Print_String(X_Entires, Y, &list_titles[i*list_char_length], list_char_length, DISPLAY_DEFAULT_CHAR_SPACING, Color);
Y += (Entry_Height + config->List_Entry_Y_Gap);
}
if(coordinates->X > 0 || coordinates->Y > 0) {
return;
}
Display_Shapes_Draw_Round_Rect_Frame(X_Entires-4, _Select_List_Current_Y-4, Entry_Width+8, Entry_Height+8, 5, 1, config->Color_Selected);
// Display_Shapes_Draw_Rect_Frame(X_Entires-6, _Select_List_Current_Y-2, Entry_Width+8, Entry_Height+8, 1, config->Color_Selected);
int Move_Direction = _NONE;
if(_Select_List_Current_Y < Y_Target) {
int Move_Direction = _NONE;
if(_Select_List_Target_Scroll_Y > _Select_List_Current_Scroll_Y) {
Move_Direction = _DOWN;
} else if(_Select_List_Current_Y > Y_Target) {
} else if(_Select_List_Target_Scroll_Y < _Select_List_Current_Scroll_Y) {
Move_Direction = _UP;
}
int16_t Distance = abs(Y_Target - _Select_List_Current_Y);
_Select_List_Current_Y += (((Distance >> 1) + 1) * Move_Direction);
int16_t Distance = abs(_Select_List_Target_Scroll_Y - _Select_List_Current_Scroll_Y);
_Select_List_Current_Scroll_Y += (((Distance >> 1) + 1) * Move_Direction);
int16_t X_Entries = coordinates->X + DISPLAY_X_CENTER - (Entry_Width >> 1);
int16_t Base_Y = coordinates->Y + config->Y_Top + _Select_List_Current_Scroll_Y;
int16_t List_Y_Top = config->Y_Top;
int16_t List_Y_Bottom = config->Y_Top + config->Visible_Items * Item_Full_Height;
for (int32_t i = -1; i <= config->Visible_Items; i++)
{
int32_t Item_Index = Offset_Items + i;
if (Item_Index < 0 || Item_Index >= (int32_t)list_entry_count) {
continue;
}
// Calculate item position relative to visible area
int32_t Item_Offset_From_Base = Item_Index - Offset_Items;
int16_t Text_Y = Base_Y + Item_Index * Item_Full_Height;
bool Item_In_Visible_Range = (Text_Y >= List_Y_Top) && (Text_Y + Item_Full_Height <= List_Y_Bottom);
float Alpha = 1.0f;
if(Item_In_Visible_Range == false)
{
if(Text_Y < List_Y_Top && (List_Y_Top - Text_Y) < Item_Full_Height) {
Alpha = 1.0 - (float)(List_Y_Top - Text_Y) / (float)Item_Full_Height;
}
else if(Text_Y < List_Y_Bottom && (List_Y_Bottom - Text_Y) < Item_Full_Height) {
Alpha = (float)(List_Y_Bottom - Text_Y) / (float)Item_Full_Height;
}
else {
continue;
}
}
if (Alpha <= 0.01f) {
continue;
}
Display_Color Base_Color = (Item_Index == (int32_t)selected_entry) ? config->Color_Selected : config->Color_Not_Selected;
Display_Color Item_Color = Base_Color;
if (Alpha < 1.0f) {
uint16_t Alpha_Fixed = (uint16_t)(Alpha * 256.0f);
Item_Color = Display_Color_Interpolate_Fixpoint(DISPLAY_COLOR_BLACK, Base_Color, Alpha_Fixed);
}
// Selection box with fade
if (config->Show_Selection_Box && Item_Index == (int32_t)selected_entry)
{
Display_Color Box_Color = config->Selection_Box_Color;
if (Alpha < 1.0f) {
uint16_t Alpha_Fixed = (uint16_t)(Alpha * 256.0f);
Box_Color = Display_Color_Interpolate_Fixpoint(DISPLAY_COLOR_BLACK, Box_Color, Alpha_Fixed);
}
int16_t Selection_Y = Text_Y - config->Selection_Box_Padding - 1;
int16_t Selection_Width = MAX(Entry_Width + (config->Selection_Box_Padding * 2), config->Selection_Box_Min_Width);
int16_t Selection_Height = Entry_Height + (config->Selection_Box_Padding * 2);
Display_Color Fill_Color = Display_Color_Interpolate_Float(Box_Color, config->Color_Not_Selected, 0.9f);
Display_Shapes_Draw_Round_Rect_Filled(DISPLAY_X_CENTER - Selection_Width/2 + 1, Selection_Y + 1, Selection_Width - 2, Selection_Height - 2, 3, Fill_Color);
Display_Shapes_Draw_Round_Rect_Frame(DISPLAY_X_CENTER - Selection_Width/2, Selection_Y, Selection_Width, Selection_Height, 4, 2, Box_Color);
}
if(config->Mark_Initial_Entry && Item_Index == (int32_t)initial_entry) {
Display_Shapes_Draw_Circle_Filled(X_Entries - 15, Text_Y + Display_Font_Get_Font_Height()/2 - 1, 3, DISPLAY_COLOR_DARKGREEN);
}
// Render text
char* Item_Text = &list_titles[Item_Index * list_char_length];
Display_Font_Print_String(X_Entries, Text_Y, Item_Text, list_char_length, DISPLAY_DEFAULT_CHAR_SPACING, Item_Color);
}
}
void Display_Render_Complex_Select_Value(Coordinates* coordinates, char* title, uint32_t title_length, int32_t value, int32_t max, int32_t min, char* format, Configuration_Select_Value* config)
void Display_Render_Complex_Select_Value(Coordinates* coordinates, char* title, uint32_t title_length, int32_t value, int32_t max, int32_t min, char* format, const Configuration_Select_Value* config)
{
if(config == NULL) {
return;
@@ -770,7 +836,7 @@ void Display_Render_Complex_Select_RGB(Coordinates* coordinates, Object_Select_R
return;
}
Configuration_Select_RGB* Config = rgb_selector->Config;
const Configuration_Select_RGB* Config = rgb_selector->Config;
// Calculate center position
int16_t Center_X = coordinates->X + DISPLAY_X_CENTER;
@@ -834,15 +900,15 @@ void Display_Render_Complex_Select_RGB(Coordinates* coordinates, Object_Select_R
// Component label (e.g., "RED")
if (Config->Component_Label_Font != NULL)
if (Config->Component_Font != NULL)
{
// Get component label
char* Component_Label = (char*)rgb_selector->Component_Labels[*rgb_selector->Current_Component];
Display_Font_Set_Font(Config->Component_Label_Font);
Display_Font_Set_Font(Config->Component_Font);
uint16_t Label_Width = Display_Font_Width_String(Component_Label, strlen(Component_Label), DISPLAY_DEFAULT_CHAR_SPACING);
int16_t Label_X = Center_X - (Label_Width / 2);
int16_t Label_Y = coordinates->Y + Config->Text_Y_Offset - 3;
int16_t Label_Y = coordinates->Y + Config->Component_Text_Y_Offset - Display_Font_Get_Font_Height() / 2;
Display_Font_Print_String(Label_X, Label_Y, Component_Label, strlen(Component_Label), DISPLAY_DEFAULT_CHAR_SPACING, Config->Text_Color);
}
@@ -860,13 +926,13 @@ void Display_Render_Complex_Select_RGB(Coordinates* coordinates, Object_Select_R
// Center both value and range as a group
int16_t Value_X = Center_X - (Value_Width / 2);
int16_t Value_Y = coordinates->Y + Config->Text_Y_Offset + 3 + Display_Font_Get_Font_Height();
int16_t Value_Y = coordinates->Y + Config->Value_Text_Y_Offset - Display_Font_Get_Font_Height() / 2;
Display_Font_Print_String(Value_X, Value_Y, Value_String, strlen(Value_String), DISPLAY_DEFAULT_CHAR_SPACING, Config->Text_Color);
}
}
void Display_Render_Complex_Entry_Indicator(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, Configuration_Entry_Indicator* config)
void Display_Render_Complex_Entry_Indicator(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, const Configuration_Entry_Indicator* config)
{
if(config->Type == INDICATOR_ARC) {
Display_Render_Complex_Entry_Indicator_Arc(coordinates, entry_count, entry_value, config);
@@ -1232,7 +1298,7 @@ void Display_Render_Complex_Menu_Hierarchical_Update_All_Animations(Object_Menu_
}
}
void Display_Render_Complex_Menu_Hierarchical_Update_Animation(const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, Configuration_Menu_Hierarchical* config)
void Display_Render_Complex_Menu_Hierarchical_Update_Animation(const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config)
{
// Calculate target positions
int16_t Target_Y = config->Menu_Start_Y;
@@ -1277,7 +1343,7 @@ void Display_Render_Complex_Menu_Hierarchical_Update_Animation(const Menu_List*
_Menu_Hierarchical_Scroll_Y += (((Distance_Scroll >> 2) + 1) * Move_Direction_Scroll);
}
void Display_Render_Complex_Menu_Hierarchical_Single_Menu(Coordinates* coordinates, const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, Configuration_Menu_Hierarchical* config, int16_t x_offset)
void Display_Render_Complex_Menu_Hierarchical_Single_Menu(Coordinates* coordinates, const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config, int16_t x_offset)
{
// Create offset coordinates
Coordinates Offset_Coordinates = *coordinates;
@@ -1308,7 +1374,7 @@ void Display_Render_Complex_Menu_Hierarchical_Single_Menu(Coordinates* coordinat
}
}
void Display_Render_Complex_Menu_Hierarchical_Title(Coordinates* coordinates, const char* title, Configuration_Menu_Hierarchical* config)
void Display_Render_Complex_Menu_Hierarchical_Title(Coordinates* coordinates, const char* title, const Configuration_Menu_Hierarchical* config)
{
if (title == NULL || config->Title_Font == NULL) {
return;
@@ -1331,7 +1397,7 @@ void Display_Render_Complex_Menu_Hierarchical_Title(Coordinates* coordinates, co
Display_Shapes_Draw_Line_XY(Separator_X, Separator_Y, Separator_X + Separator_Width, Separator_Y, 1, config->Border_Color);
}
void Display_Render_Complex_Menu_Hierarchical_Items(Coordinates* coordinates, const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, Configuration_Menu_Hierarchical* config)
void Display_Render_Complex_Menu_Hierarchical_Items(Coordinates* coordinates, const Menu_List* current_list, int32_t selected_item, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config)
{
if (current_list->Items == NULL) {
return;
@@ -1394,7 +1460,7 @@ void Display_Render_Complex_Menu_Hierarchical_Items(Coordinates* coordinates, co
}
}
void Display_Render_Complex_Menu_Hierarchical_Single_Item(Coordinates* coordinates, const Menu_Item* item, int32_t item_index, int32_t selected_item, int16_t item_y, Display_Color item_color, float scale_factor, Configuration_Menu_Hierarchical* config)
void Display_Render_Complex_Menu_Hierarchical_Single_Item(Coordinates* coordinates, const Menu_Item* item, int32_t item_index, int32_t selected_item, int16_t item_y, Display_Color item_color, float scale_factor, const Configuration_Menu_Hierarchical* config)
{
char Display_Text[64];
@@ -1456,7 +1522,7 @@ void Display_Render_Complex_Menu_Hierarchical_Single_Item(Coordinates* coordinat
}
}
void Display_Render_Complex_Menu_Hierarchical_Selection_Box(Coordinates* coordinates, int32_t selected_item, int32_t scroll_offset, Configuration_Menu_Hierarchical* config)
void Display_Render_Complex_Menu_Hierarchical_Selection_Box(Coordinates* coordinates, int32_t selected_item, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config)
{
if (selected_item < 0) {
return;
@@ -1485,7 +1551,7 @@ void Display_Render_Complex_Menu_Hierarchical_Selection_Box(Coordinates* coordin
Display_Shapes_Draw_Round_Rect_Filled(Box_X + 1, Box_Y + 1, Box_Width - 2, Box_Height - 2, 4, Fill_Color);
}
void Display_Render_Complex_Menu_Hierarchical_Scroll_Indicators(Coordinates* coordinates, const Menu_List* current_list, int32_t scroll_offset, Configuration_Menu_Hierarchical* config)
void Display_Render_Complex_Menu_Hierarchical_Scroll_Indicators(Coordinates* coordinates, const Menu_List* current_list, int32_t scroll_offset, const Configuration_Menu_Hierarchical* config)
{
if (current_list->Item_Count <= config->Visible_Items) {
return; // No scrolling needed
@@ -1525,6 +1591,30 @@ void Display_Render_Complex_Menu_Hierarchical_Scroll_Indicators(Coordinates* coo
}
}
int32_t Display_Render_Complex_Select_List_Calculate_Scroll_Offset(uint32_t selected_entry, uint32_t total_entries, uint16_t visible_items)
{
if (total_entries <= visible_items) {
return 0; // No scrolling needed
}
int32_t Scroll_Offset = 0;
// Keep selected item in center of visible area when possible
int32_t Center_Position = visible_items / 2;
if (selected_entry >= Center_Position) {
Scroll_Offset = selected_entry - Center_Position;
}
// Ensure we don't scroll past the end
int32_t Max_Scroll = total_entries - visible_items;
if (Scroll_Offset > Max_Scroll) {
Scroll_Offset = Max_Scroll;
}
return Scroll_Offset;
}
float Display_Render_Complex_Select_RGB_Calculate_Progress_Ring_Angle(uint8_t value, uint8_t min_value, uint8_t max_value)
{
// Convert value (0-255) to angle (0-360 degrees)
@@ -1559,7 +1649,7 @@ float Display_Render_Complex_Select_RGB_Calculate_Progress_Ring_Angle(uint8_t va
return Angle_Degrees;
}
void Display_Render_Complex_Entry_Indicator_Arc(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, Configuration_Entry_Indicator* config)
void Display_Render_Complex_Entry_Indicator_Arc(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, const Configuration_Entry_Indicator* config)
{
if(config->Type != INDICATOR_ARC) {
return;
@@ -1617,7 +1707,7 @@ void Display_Render_Complex_Entry_Indicator_Arc(Coordinates* coordinates, uint32
Display_Shapes_Draw_Arc_Frame(DISPLAY_X_CENTER, DISPLAY_Y_CENTER, config->Options.Arc.Radius, config->Options.Arc.Thickness, _Entry_Indicator_Current_Angle, _Entry_Indicator_Current_Angle+Angle_Step_Per_Entry, 10, config->Color_Selected);
}
void Display_Render_Complex_Entry_Indicator_Dot(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, Configuration_Entry_Indicator* config)
void Display_Render_Complex_Entry_Indicator_Dot(Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, const Configuration_Entry_Indicator* config)
{
if(config->Type != INDICATOR_DOT) {
return;