add elapsed time to tick handler params, add generic scrollable menu
This commit is contained in:
@@ -8,6 +8,8 @@ set(COMPONENT_SRCS
|
||||
"scenes/scene_car.c"
|
||||
"scenes/scene_demo.c"
|
||||
"scenes/scene_bootanim.c"
|
||||
"scenes/scene_menu.c"
|
||||
"scenes/scene_test_menu.c"
|
||||
"graphics/nokia.c"
|
||||
"graphics/utf8.c"
|
||||
"graphics/font.c"
|
||||
|
||||
+4
-2
@@ -52,14 +52,17 @@ static void __attribute__((noreturn)) gui_thread(void *arg) {
|
||||
|
||||
uint32_t last_wheel_time = 0;
|
||||
|
||||
uint32_t last_time = xTaskGetTickCount();
|
||||
while (1) {
|
||||
bool want_repaint = false;
|
||||
uint32_t value = 0;
|
||||
xTaskNotifyWait(0, ULONG_MAX, &value, pdMS_TO_TICKS(10));
|
||||
uint32_t time = xTaskGetTickCount();
|
||||
|
||||
if (value & 0b10000) {
|
||||
// TICK
|
||||
want_repaint |= Liquid_handleTick(liquid);
|
||||
want_repaint |= Liquid_handleTick(liquid, time - last_time);
|
||||
last_time = time;
|
||||
}
|
||||
|
||||
if (value & 0b1000) {
|
||||
@@ -69,7 +72,6 @@ static void __attribute__((noreturn)) gui_thread(void *arg) {
|
||||
}
|
||||
|
||||
if (value & 0b11) {
|
||||
uint32_t time = xTaskGetTickCount();
|
||||
uint32_t increment = 1;
|
||||
// wheel delta changes with speed
|
||||
if (last_wheel_time != 0) {
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#ifndef LIQUID_INPUT_EVENT_H
|
||||
#define LIQUID_INPUT_EVENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum InputEvent_Kind {
|
||||
InputEventKind_Wheel,
|
||||
InputEventKind_Button,
|
||||
@@ -18,6 +20,7 @@ struct InputEvent {
|
||||
struct {
|
||||
// Wheel delta
|
||||
int32_t delta;
|
||||
int8_t direction;
|
||||
} wheel;
|
||||
struct {
|
||||
// Button state
|
||||
@@ -30,7 +33,10 @@ static inline struct InputEvent InputEvent_Wheel(int32_t delta)
|
||||
{
|
||||
return (struct InputEvent) {
|
||||
.kind = InputEventKind_Wheel,
|
||||
.wheel = {.delta = delta}
|
||||
.wheel = {
|
||||
.delta = delta,
|
||||
.direction = delta > 0 ? 1 : -1,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -119,12 +119,12 @@ bool Liquid_handleInput(struct Liquid *container, struct InputEvent event) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Liquid_handleTick(struct Liquid *container) {
|
||||
bool Liquid_handleTick(struct Liquid *container, uint32_t elapsed_millis) {
|
||||
struct RunningScene *topmost = SLIST_FIRST(&container->stack);
|
||||
assert(topmost != NULL);
|
||||
assert(topmost->scene != NULL);
|
||||
if (topmost->scene->onTick) {
|
||||
struct SceneEvent result = topmost->scene->onTick(topmost->scene);
|
||||
struct SceneEvent result = topmost->scene->onTick(topmost->scene, elapsed_millis);
|
||||
return processReturnValue(container, result);
|
||||
} else {
|
||||
return false;
|
||||
|
||||
@@ -19,7 +19,7 @@ struct Liquid;
|
||||
bool Liquid_handleInput(struct Liquid *container, struct InputEvent event);
|
||||
|
||||
/** return 1 if repaint requested */
|
||||
bool Liquid_handleTick(struct Liquid *container);
|
||||
bool Liquid_handleTick(struct Liquid *container, uint32_t elapsed_millis);
|
||||
|
||||
/** render the active scene */
|
||||
void Liquid_paint(struct Liquid *container);
|
||||
|
||||
@@ -38,7 +38,7 @@ typedef struct SceneEvent (*Scene_onChildReturn_t)(struct Scene *scene, uint32_t
|
||||
* @param scene - self
|
||||
* @return follow-up scene event, can be SceneEvent_None() if not used.
|
||||
*/
|
||||
typedef struct SceneEvent (*Scene_onTick_t)(struct Scene *scene);
|
||||
typedef struct SceneEvent (*Scene_onTick_t)(struct Scene *scene, uint32_t millis);
|
||||
|
||||
/**
|
||||
* Scene::init fp type
|
||||
|
||||
@@ -2,27 +2,26 @@
|
||||
#include <stdio.h>
|
||||
#include <graphics/bitmaps.h>
|
||||
|
||||
#include "scenes.h"
|
||||
#include "liquid.h"
|
||||
#include "analog.h"
|
||||
#include "graphics/nokia.h"
|
||||
#include "graphics/drawing.h"
|
||||
|
||||
#define BOOTANIM_TIME_MS 100
|
||||
|
||||
struct BootScene {
|
||||
struct Scene base;
|
||||
uint32_t cnt;
|
||||
};
|
||||
|
||||
static struct SceneEvent Boot_onTick(struct BootScene *self) {
|
||||
self->cnt += 10; // ms
|
||||
if (self->cnt == 2000) {
|
||||
static struct SceneEvent onTick(struct BootScene *self, uint32_t millis) {
|
||||
self->cnt += millis; // ms
|
||||
if (self->cnt >= BOOTANIM_TIME_MS) {
|
||||
return SceneEvent_Close(0, NULL);
|
||||
}
|
||||
|
||||
return SceneEvent_None();
|
||||
}
|
||||
|
||||
static void Boot_paint(struct BootScene *self)
|
||||
static void paint(struct BootScene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
LCD_setBitmap(Bitmap_Get("boot_logo")->bytes);
|
||||
@@ -30,7 +29,7 @@ static void Boot_paint(struct BootScene *self)
|
||||
|
||||
struct Scene *NewScene_Boot(void) {
|
||||
struct BootScene *scene = calloc(1, sizeof(struct BootScene));
|
||||
scene->base.paint = (Scene_paint_t) Boot_paint;
|
||||
scene->base.onTick = (Scene_onTick_t) Boot_onTick;
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
scene->base.onTick = (Scene_onTick_t) onTick;
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ struct CarScene {
|
||||
int32_t pos;
|
||||
};
|
||||
|
||||
static struct SceneEvent Car_onInput(struct CarScene *self, struct InputEvent event) {
|
||||
static struct SceneEvent onInput(struct CarScene *self, struct InputEvent event) {
|
||||
switch (event.kind) {
|
||||
case InputEventKind_Wheel:
|
||||
self->pos += event.wheel.delta;
|
||||
@@ -27,7 +27,7 @@ static struct SceneEvent Car_onInput(struct CarScene *self, struct InputEvent ev
|
||||
}
|
||||
}
|
||||
|
||||
static void Car_paint(struct CarScene *self)
|
||||
static void paint(struct CarScene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
LCD_setRect(self->pos, LCD_HEIGHT/2-10, self->pos+20,LCD_HEIGHT/2+10,0,1);
|
||||
@@ -38,7 +38,7 @@ struct Scene *NewScene_Car(void) {
|
||||
struct CarScene *scene = calloc(1, sizeof(struct CarScene));
|
||||
if (!scene) return NULL;
|
||||
|
||||
scene->base.onInput = (Scene_onInput_t) Car_onInput;
|
||||
scene->base.paint = (Scene_paint_t) Car_paint;
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ struct DemoScene {
|
||||
uint32_t timer_prescale;
|
||||
};
|
||||
|
||||
static struct SceneEvent Demo_onInput(struct DemoScene *self, struct InputEvent event) {
|
||||
static struct SceneEvent onInput(struct DemoScene *self, struct InputEvent event) {
|
||||
switch (event.kind) {
|
||||
case InputEventKind_Wheel:
|
||||
self->pos += event.wheel.delta;
|
||||
@@ -35,11 +35,11 @@ static struct SceneEvent Demo_onInput(struct DemoScene *self, struct InputEvent
|
||||
return SceneEvent_Repaint();
|
||||
}
|
||||
|
||||
static struct SceneEvent Demo_onTick(struct DemoScene *self) {
|
||||
static struct SceneEvent onTick(struct DemoScene *self, uint32_t millis) {
|
||||
// top text anim
|
||||
self->timer_prescale += 1;
|
||||
self->timer_prescale += millis;
|
||||
|
||||
if (self->timer_prescale == 100) {
|
||||
if (self->timer_prescale == 1000) {
|
||||
self->timer_prescale = 0;
|
||||
self->timer_phase += 1;
|
||||
self->timer_phase = self->timer_phase & 0b11; // 0..3
|
||||
@@ -50,7 +50,7 @@ static struct SceneEvent Demo_onTick(struct DemoScene *self) {
|
||||
return SceneEvent_None();
|
||||
}
|
||||
|
||||
static void Demo_paint(struct DemoScene *self)
|
||||
static void paint(struct DemoScene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
|
||||
@@ -85,8 +85,9 @@ static void Demo_paint(struct DemoScene *self)
|
||||
struct Scene *NewScene_Demo(void) {
|
||||
struct DemoScene *scene = calloc(1, sizeof(struct DemoScene));
|
||||
|
||||
scene->base.onInput = (Scene_onInput_t) Demo_onInput;
|
||||
scene->base.paint = (Scene_paint_t) Demo_paint;
|
||||
scene->base.onTick = (Scene_onTick_t) Demo_onTick;
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
scene->base.onTick = (Scene_onTick_t) onTick;
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <malloc.h>
|
||||
#include <graphics/bitmaps.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdbool.h>
|
||||
#include <liquid/input_event.h>
|
||||
|
||||
#include "liquid.h"
|
||||
#include "graphics/drawing.h"
|
||||
|
||||
#include "scene_menu.h"
|
||||
|
||||
static void paint(struct MenuScene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
|
||||
int row = 0;
|
||||
for (int i = self->scroll_up; i < MIN(self->items_len, self->scroll_up + 6); i++, row++) {
|
||||
bool selected = self->selected==i;
|
||||
LCD_setStrEx(self->items[i].label, 0, row * 8, selected?WHITE:BLACK,FONT_NORMAL|(selected?FONT_BG:0));
|
||||
}
|
||||
}
|
||||
|
||||
static struct SceneEvent onInput(struct MenuScene *self, struct InputEvent event) {
|
||||
switch (event.kind) {
|
||||
case InputEventKind_Wheel:;
|
||||
self->selected += event.wheel.direction;
|
||||
if (self->selected < 0) {
|
||||
self->selected = 0;
|
||||
}
|
||||
else if (self->selected >= self->items_len) {
|
||||
self->selected = self->items_len - 1;
|
||||
}
|
||||
|
||||
// hacky scroll adjust
|
||||
while (self->selected - self->scroll_up < 1 && self->scroll_up > 0) {
|
||||
self->scroll_up--;
|
||||
}
|
||||
|
||||
while (self->selected - self->scroll_up >= 5 && self->scroll_up < self->items_len - 6) {
|
||||
self->scroll_up++;
|
||||
}
|
||||
|
||||
return SceneEvent_Repaint();
|
||||
|
||||
case InputEventKind_Button:
|
||||
if (event.button.state) {
|
||||
if (self->onSelect) {
|
||||
return self->onSelect(self);
|
||||
}
|
||||
return SceneEvent_Close(0, NULL);
|
||||
}
|
||||
// fall through
|
||||
default:
|
||||
return SceneEvent_None();
|
||||
}
|
||||
}
|
||||
|
||||
struct MenuScene *NewScene_Menu(struct MenuItem *items, size_t items_len) {
|
||||
struct MenuScene *scene = calloc(1, sizeof(struct MenuScene));
|
||||
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
|
||||
scene->items = items;
|
||||
scene->items_len = items_len;
|
||||
|
||||
return scene;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* TODO file description
|
||||
*
|
||||
* Created on 2020/01/05.
|
||||
*/
|
||||
|
||||
#ifndef REFLOWER_SCENE_MENU_H
|
||||
#define REFLOWER_SCENE_MENU_H
|
||||
|
||||
#define MENUITEM_LABEL_LEN 30
|
||||
|
||||
struct MenuItem {
|
||||
char label[MENUITEM_LABEL_LEN];
|
||||
uint32_t tag;
|
||||
};
|
||||
|
||||
struct MenuScene;
|
||||
|
||||
typedef struct SceneEvent (*MenuScene_onSelect_t)(struct MenuScene *scene);
|
||||
|
||||
struct MenuScene {
|
||||
struct Scene base;
|
||||
// items array
|
||||
struct MenuItem *items;
|
||||
// items count
|
||||
size_t items_len;
|
||||
// Vertical scroll offset (how many steps is the topmost item moved above the screen)
|
||||
int32_t scroll_up;
|
||||
// Selected item number
|
||||
int32_t selected;
|
||||
// selection handler
|
||||
MenuScene_onSelect_t onSelect;
|
||||
};
|
||||
|
||||
struct MenuScene *NewScene_Menu(struct MenuItem *items, size_t items_len);
|
||||
|
||||
#endif //REFLOWER_SCENE_MENU_H
|
||||
@@ -16,29 +16,34 @@ struct RootScene {
|
||||
struct Scene base;
|
||||
};
|
||||
|
||||
static struct SceneEvent Root_init(struct RootScene *self)
|
||||
static struct SceneEvent init(struct RootScene *self)
|
||||
{
|
||||
return SceneEvent_OpenChild(NewScene_Boot(), 1);
|
||||
}
|
||||
|
||||
struct SceneEvent Root_onChildReturn(
|
||||
struct RootScene *self,
|
||||
uint32_t tag,
|
||||
int32_t status,
|
||||
void *data)
|
||||
struct SceneEvent onChildReturn(struct RootScene *self, uint32_t tag, int32_t status, void *data)
|
||||
{
|
||||
if (tag == 1) {
|
||||
return SceneEvent_OpenChild(NewScene_Demo(), 0);
|
||||
return SceneEvent_OpenChild(NewScene_MenuTest(), 0);
|
||||
}
|
||||
|
||||
// this should be unreachable
|
||||
return SceneEvent_None();
|
||||
}
|
||||
|
||||
static void paint(struct Scene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
|
||||
LCD_setStrEx("Press DEL to enter setup", 0, 0, 1, 0x3);
|
||||
}
|
||||
|
||||
struct Scene *NewScene_Root(void) {
|
||||
struct RootScene *scene = calloc(1, sizeof(struct RootScene));
|
||||
|
||||
scene->base.init = (Scene_init_t) Root_init;
|
||||
scene->base.onChildReturn = (Scene_onChildReturn_t) Root_onChildReturn;
|
||||
scene->base.init = (Scene_init_t) init;
|
||||
scene->base.onChildReturn = (Scene_onChildReturn_t) onChildReturn;
|
||||
scene->base.paint = paint;
|
||||
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#include <malloc.h>
|
||||
#include <graphics/bitmaps.h>
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "liquid.h"
|
||||
#include "graphics/drawing.h"
|
||||
|
||||
#include "scenes.h"
|
||||
#include "scene_menu.h"
|
||||
|
||||
|
||||
static struct SceneEvent onSelect(struct MenuScene *self) {
|
||||
if (self->selected == 0) {
|
||||
return SceneEvent_Close(0, NULL);
|
||||
}
|
||||
|
||||
if (self->selected == 8) {
|
||||
return SceneEvent_OpenChild(NewScene_Car(), 0);
|
||||
}
|
||||
if (self->selected == 9) {
|
||||
return SceneEvent_OpenChild(NewScene_Demo(), 0);
|
||||
}
|
||||
if (self->selected == 5) {
|
||||
self->items[5].tag++;
|
||||
snprintf(self->items[5].label, MENUITEM_LABEL_LEN, "Count = %d", self->items[5].tag);
|
||||
return SceneEvent_Repaint();
|
||||
}
|
||||
|
||||
return SceneEvent_None();
|
||||
}
|
||||
|
||||
struct Scene *NewScene_MenuTest() {
|
||||
struct MenuItem *items = calloc(10, sizeof(struct MenuItem));
|
||||
|
||||
strncpy(items[0].label, "🔙Back", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[1].label, "▶#1", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[2].label, "▶#2", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[3].label, "▶#3", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[4].label, "▶#4", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[5].label, "Count = 0", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[6].label, "▶#6", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[7].label, "▶#7", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[8].label, "Car", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[9].label, "Demo Scene", MENUITEM_LABEL_LEN);
|
||||
|
||||
struct MenuScene * scene = NewScene_Menu(items, 10);
|
||||
scene->onSelect = onSelect;
|
||||
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
@@ -12,4 +12,6 @@ struct Scene *NewScene_Boot(void);
|
||||
struct Scene *NewScene_Demo(void);
|
||||
struct Scene *NewScene_Car(void);
|
||||
|
||||
struct Scene *NewScene_MenuTest(void);
|
||||
|
||||
#endif //REFLOWER_SCENES_H
|
||||
|
||||
Reference in New Issue
Block a user