add elapsed time to tick handler params, add generic scrollable menu

master
Ondřej Hruška 4 years ago
parent d7cd0e9cfa
commit 2b92a6832d
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      main/CMakeLists.txt
  2. 6
      main/liquid/gui.c
  3. 8
      main/liquid/input_event.h
  4. 4
      main/liquid/liquid.c
  5. 2
      main/liquid/liquid.h
  6. 2
      main/liquid/scene_type.h
  7. 17
      main/scenes/scene_bootanim.c
  8. 8
      main/scenes/scene_car.c
  9. 17
      main/scenes/scene_demo.c
  10. 68
      main/scenes/scene_menu.c
  11. 37
      main/scenes/scene_menu.h
  12. 23
      main/scenes/scene_root.c
  13. 52
      main/scenes/scene_test_menu.c
  14. 2
      main/scenes/scenes.h

@ -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"

@ -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

Loading…
Cancel
Save