SDK 冲刺批①+②+⑤: meow_box 线性布局 + meow_anim 动画基座 + meow_scroll 滚动物理
- meow_box(include/meow_ui_box.h + meow_ui_box.c):竖直/水平容器;子项=固定|weight|wrap; margin/padding/gap;主轴对齐 start/center/end/space-between/around/evenly;交叉轴 start/center/end/stretch; 嵌套(深度≤16 静态栈,单遍求解,无递归爆炸)。可作 meow_view 布局提供者 (meow_view_set_layout/relayout,opt-in;未设布局的 view 保持现有绝对坐标行为)。 新增 meow_widget_set_rect(只写字段不标脏)作为 box 写坐标的通道。 - meow_anim(include/meow_ui_anim.h + meow_ui_anim.c):时间驱动 tween(from/to/duration/easing: linear/ease-out/ease-in-out/overshoot)+ update/done 回调;静态池≤16、取消、并行多动画; meow_anim_set_region 让每帧只 flush 动画影响区(不整屏)。meow_anim_tick 挂主循环 on_tick, 无动画零开销(只查计数即返回)。 - meow_scroll(include/meow_ui_scroll.h + meow_ui_scroll.c):速度跟踪(最近 N 采样加权)+ 松手 fling (减速度曲线,用 anim 基座驱动)+ 边界过冲 clamp + 简单回弹(不做 spring)+ 可选 snap; 跟手拖动行为不变(track 内部调既有 set_scroll);每帧只 redraw 列表视口区;不引 libm。 - 追加式:既有 meow_row/column/box 与全部 meow_*_create/hit/scroll 签名一行未改;旧绝对坐标永远有效; 既有 App 免改源码。 - 验证:宿主新测试 box(42)/anim(32)/scroll(17) 全 PASS;既存 9 回归(widgets/sdk_input_keys/ime_fix/ pinyin/overlay_suppress/notif_gesture/sdk_fixes/sb_collapse/p1p2p3_repro)全 PASS; 离屏 demo(demo_box_scroll.c)渲染 box 布局 + 列表 fling 正常;zig-mipsel -Wall -Wextra 全 TU 0 warning; meow_ui.a md5 83dd6a2d0d24cc748a8659c29f1de2b5(未重链/部署 hello/files/ncm/reader,由主会话统一处理)。
This commit is contained in:
1 parent
553a7d5d9e
commit
5a5e995ebd
19 files changed
+1839
-2
No files matched your search
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* meow_ui_anim.h — SDK 动画基座 + UI 节拍器(§12.2:meow_anim / meow_anim_tick)。
|
||||
*
|
||||
* 定位:给应用提供**时间驱动 tween**(from/to/duration/easing)+ 完成/取消回调,并行多动画
|
||||
* (静态池≤MEOW_ANIM_MAX)+ 与脏区集成(动画帧只标动画影响区,不做整屏重绘)。
|
||||
*
|
||||
* 节拍:**挂既有 on_tick 机制**(meow_ui_run 主循环 / meow_ui_feed_tick 阻塞 IME 循环),
|
||||
* 无常驻高频轮询;无动画时 meow_anim_tick() 只做一个计数检查即返回(零开销)。
|
||||
*
|
||||
* 内存纪律:静态池(≤MEOW_ANIM_MAX),start/cancel/tick 全程零 malloc。
|
||||
*
|
||||
* 与 §7 的关系:§7(B1 最小可用)是「应用自己在 on_tick 里用 meow_ui_time_ms 做时间轴」;
|
||||
* 本模块把这件事收敛成声明式 tween 对象 + 结束回调,是 §7 的**正式基座**(应用可任选其一或混用)。
|
||||
*/
|
||||
#ifndef MEOW_UI_ANIM_H
|
||||
#define MEOW_UI_ANIM_H
|
||||
|
||||
#include "meow_ui_types.h" /* 基础类型(子头不引伞头,避免相对路径依赖) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ---- 缓动曲线(t∈[0,1] → 曲线化的进度;OVERSHOOT 在中后段可略>1、末点恰=1)---- */
|
||||
typedef enum {
|
||||
MEOW_EASE_LINEAR = 0,
|
||||
MEOW_EASE_OUT = 1, /* 快进慢停(decelerate) */
|
||||
MEOW_EASE_IN_OUT = 2, /* 慢入慢出 */
|
||||
MEOW_EASE_OVERSHOOT = 3, /* 越过目标再回稳(小回弹) */
|
||||
} meow_ease;
|
||||
|
||||
float meow_ease_apply(meow_ease e, float t);
|
||||
|
||||
/* ---- 动画对象(不透明句柄;静态池)---- */
|
||||
#define MEOW_ANIM_MAX 16
|
||||
|
||||
typedef struct meow_anim meow_anim;
|
||||
|
||||
/* 每帧回调:v = 当前插值值(from + (to-from)*ease(t))。app 在此更新状态并绘制。 */
|
||||
typedef void (*meow_anim_update_fn)(meow_anim *a, float v, void *ctx);
|
||||
/* 完成/取消回调:canceled=1=被取消,0=自然完成。 */
|
||||
typedef void (*meow_anim_done_fn)(meow_anim *a, int canceled, void *ctx);
|
||||
|
||||
typedef struct meow_anim_desc {
|
||||
float from;
|
||||
float to;
|
||||
uint32_t duration_ms; /* 时长(ms);0 视为瞬发(下一 tick 完成) */
|
||||
meow_ease ease;
|
||||
meow_anim_update_fn update; /* 可 NULL */
|
||||
meow_anim_done_fn done; /* 可 NULL */
|
||||
void *ctx;
|
||||
} meow_anim_desc;
|
||||
|
||||
/* 启动一个动画(空闲槽;池满返回 NULL)。start 即置 value=from 并回调一次 update(0)。 */
|
||||
meow_anim *meow_anim_start(const meow_anim_desc *d);
|
||||
/* 取消(触发 done(canceled=1),不再 update)。 */
|
||||
void meow_anim_cancel(meow_anim *a);
|
||||
/* 查询:仍在运行(value 未达终点)。 */
|
||||
int meow_anim_active(meow_anim *a);
|
||||
/* 查询:当前插值值。 */
|
||||
float meow_anim_value(meow_anim *a);
|
||||
|
||||
/* 与脏区集成:动画每 tick 只 flush 影响区(x,y,w,h;x<0 表示不自动 flush)。
|
||||
* app 的 update 回调通常也会用 meow_ui_flush_region 自刷;设了这个则 tick 自动刷一次,
|
||||
* 保证「动画帧只标脏动画影响区,不整屏」。 */
|
||||
void meow_anim_set_region(meow_anim *a, int x, int y, int w, int h);
|
||||
|
||||
/* ---- 节拍器(挂在 on_tick / meow_ui_feed_tick;无动画零开销)---- */
|
||||
void meow_anim_tick(void); /* 推进所有活动动画(完成/取消在内部处理) */
|
||||
unsigned meow_anim_count(void); /* 活动动画数(0=空闲) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* MEOW_UI_ANIM_H */
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* meow_ui_box.h — SDK 线性布局引擎(§12.1:meow_box)。
|
||||
*
|
||||
* 定位:既有的 meow_row/column/box(§5.8.5,W_LAYOUT)只支持「固定尺寸子项 + 居中」,
|
||||
* 本模块是其**独立增强**:竖直/水平容器,子项 = 固定尺寸 | weight 权重 | wrap(内容测量),
|
||||
* 支持 margin/padding / 主轴对齐(start/center/end/space-between/around/evenly)/ 交叉轴对齐
|
||||
* (start/center/end/stretch)/ 嵌套。
|
||||
*
|
||||
* 与绝对定位完全兼容:meow_box 是**纯布局计算器**,不是控件,不参与 z 序注册表/命中/绘制;
|
||||
* arrange 把每个子控件的 x/y/w/h 写进现有 meow_widget(用新增 meow_widget_set_rect),
|
||||
* 此后照常 draw/hit/flush_region/owner 闸门——与既有控件绝对定位零冲突。
|
||||
*
|
||||
* 与视图框架集成(opt-in):meow_box 可作 meow_view 的布局提供者(meow_view_set_layout);
|
||||
* view 不设就保持现有绝对坐标行为(§12.1.4)。
|
||||
*
|
||||
* 内存纪律:静态池 + 定长 items 数组(≥MEOW_BOX_MAX_CHILD),热路径(arrange)零 malloc;
|
||||
* 嵌套用深度≤MEOW_BOX_MAX_DEPTH 的静态栈单遍求解,无递归爆炸。
|
||||
*/
|
||||
#ifndef MEOW_UI_BOX_H
|
||||
#define MEOW_UI_BOX_H
|
||||
|
||||
#include "meow_ui_types.h" /* meow_widget 前向 + 基础类型(子头不引伞头,避免相对路径依赖) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct meow_box meow_box;
|
||||
|
||||
/* 主轴方向 */
|
||||
typedef enum {
|
||||
MEOW_BOX_H = 0, /* 横向(row) */
|
||||
MEOW_BOX_V = 1, /* 纵向(column) */
|
||||
} meow_box_dir;
|
||||
|
||||
/* 子项主轴尺寸策略 */
|
||||
typedef enum {
|
||||
MEOW_BOX_FIXED = 0, /* 固定尺寸:内容主轴向取控件当前 w/h */
|
||||
MEOW_BOX_WEIGHT = 1, /* 权重:均分剩余主轴空间(weight>0) */
|
||||
MEOW_BOX_WRAP = 2, /* wrap:按内容测量(min/preferred 或 measure 回调) */
|
||||
} meow_box_size;
|
||||
|
||||
/* 主轴对齐 */
|
||||
typedef enum {
|
||||
MEOW_BOX_ALIGN_START = 0,
|
||||
MEOW_BOX_ALIGN_CENTER = 1,
|
||||
MEOW_BOX_ALIGN_END = 2,
|
||||
MEOW_BOX_ALIGN_SPACE_BETWEEN = 3,
|
||||
MEOW_BOX_ALIGN_SPACE_AROUND = 4,
|
||||
MEOW_BOX_ALIGN_SPACE_EVENLY = 5,
|
||||
} meow_box_align;
|
||||
|
||||
/* 交叉轴对齐 */
|
||||
typedef enum {
|
||||
MEOW_BOX_CROSS_START = 0,
|
||||
MEOW_BOX_CROSS_CENTER = 1,
|
||||
MEOW_BOX_CROSS_END = 2,
|
||||
MEOW_BOX_CROSS_STRETCH = 3,
|
||||
} meow_box_cross;
|
||||
|
||||
/* 内容测量回调(size==MEOW_BOX_WRAP 时用;可 NULL):给出主轴向 min/preferred 尺寸。
|
||||
* ctx = meow_box_add_ex 的 mctx。 */
|
||||
typedef void (*meow_box_measure_fn)(void *ctx, int *min_main, int *pref_main);
|
||||
|
||||
/* 子项描述(add/add_ex/add_sub 提供;app 只读)。w 与 sub 二选一。 */
|
||||
typedef struct meow_box_item {
|
||||
meow_widget *w; /* 子控件(sub==NULL 时用) */
|
||||
meow_box *sub; /* 嵌套 box(w==NULL 时用) */
|
||||
int size; /* MEOW_BOX_* 尺寸策略 */
|
||||
int weight; /* size==WEIGHT 时>0 */
|
||||
int min; /* size==WRAP 的主轴下限 */
|
||||
int preferred;/* size==WRAP 的主轴目标 */
|
||||
meow_box_measure_fn measure; /* size==WRAP 内容测量(可 NULL) */
|
||||
void *mctx;
|
||||
} meow_box_item;
|
||||
|
||||
#define MEOW_BOX_MAX_CHILD 24 /* 每容器子项上限(静态数组) */
|
||||
#define MEOW_BOX_MAX_DEPTH 16 /* 嵌套深度上限(静态求解栈) */
|
||||
|
||||
/* ---- 生命周期(静态池;new 冷路径,arrange 热路径零 malloc)----
|
||||
* 注:命名用 meow_box_new(meow_box_create 已被 §5.8.5 的 W_LAYOUT box 占用)。 */
|
||||
meow_box *meow_box_new(meow_box_dir dir);
|
||||
void meow_box_free(meow_box *b);
|
||||
|
||||
/* ---- 容器配置 ---- */
|
||||
void meow_box_set_rect(meow_box *b, int x, int y, int w, int h); /* 容器矩形(绝对坐标) */
|
||||
void meow_box_set_padding(meow_box *b, int l, int t, int r, int btm);
|
||||
void meow_box_set_gap(meow_box *b, int gap);
|
||||
void meow_box_set_align(meow_box *b, int main_align, int cross_align);
|
||||
|
||||
/* ---- 子项添加(返回 0=成功;越界/无效=负值,不清空既有子项)---- */
|
||||
int meow_box_add(meow_box *b, meow_widget *w, int size, int weight);
|
||||
/* add_ex:WRAP 用 min/preferred(主轴向)+ 可选内容测量回调。 */
|
||||
int meow_box_add_ex(meow_box *b, meow_widget *w, int size, int weight,
|
||||
int min, int preferred, meow_box_measure_fn m, void *mctx);
|
||||
/* 嵌套子 box(parent 布局会为 sub 分配矩形并递归 arrange)。 */
|
||||
int meow_box_add_sub(meow_box *b, meow_box *sub, int size, int weight);
|
||||
|
||||
/* ---- 求解(单遍;深度≤MEOW_BOX_MAX_DEPTH 静态栈,无递归)----
|
||||
* 把每个子控件 x/y/w/h 写进其 meow_widget(meow_widget_set_rect);
|
||||
* 嵌套 sub 的矩形写进 sub 并递归。子控件的 margin(meow_widget_opts.margin_x/y)参与排布。 */
|
||||
void meow_box_arrange(meow_box *b);
|
||||
|
||||
/* ---- 查询 ---- */
|
||||
int meow_box_count(const meow_box *b);
|
||||
meow_widget *meow_box_widget_at(const meow_box *b, int idx); /* 子项控件(无则 NULL) */
|
||||
meow_box *meow_box_sub_at(const meow_box *b, int idx); /* 子项嵌套 box(无则 NULL) */
|
||||
void meow_box_rect(const meow_box *b, int out[4]); /* x,y,w,h */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* MEOW_UI_BOX_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* meow_ui_scroll.h — SDK 滚动物理(§12.3:meow_scroll)。
|
||||
*
|
||||
* 定位:给既有滚动容器(W_LIST / W_LISTVIEW / LazyColumn / LazyRow)加**可惯性滚动**的
|
||||
* **物理层**——速度跟踪(最近 N 个采样加权)、松手 fling(减速度曲线,用 §12.2 动画基座驱动)、
|
||||
* 边界过冲 clamp + 简单回弹(不做复杂 spring)、滚动停止可选 snap。**跟手拖动行为保持现状
|
||||
* 不变**(track 内部调既有 set_scroll,clamp 一致)。
|
||||
*
|
||||
* 设计:meow_scroll 是**滚动会话**,包住一个滚动控件(或任意的 set/max/get/redraw 回调)。
|
||||
* 拖动态:app 在 on_touch_move 里把位移喂给 meow_scroll_track(dy, t)(等价于 app 直接调
|
||||
* meow_list_scroll_by,且额外记录速度采样);松手:app 调 meow_scroll_fling(s),内部用
|
||||
* 加权速度采样得出初速 → 起一条 ease-out 动画推进位移 → 每帧只 redraw(flush 列表视口区)。
|
||||
*
|
||||
* 内存纪律:静态池(应用侧按需创建会话),track/fling/tick 全程零 malloc;无动画时
|
||||
* meow_scroll 不参与节拍(fling 由 meow_anim_tick 驱动,活动计数为 0 则零开销)。
|
||||
*/
|
||||
#ifndef MEOW_UI_SCROLL_H
|
||||
#define MEOW_UI_SCROLL_H
|
||||
|
||||
#include "meow_ui_types.h" /* meow_widget 前向 + 基础类型(子头不引伞头,避免相对路径依赖) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct meow_scroll meow_scroll;
|
||||
|
||||
/* ---- 通用回调(wrap 之外的自定义滚动源用)---- */
|
||||
typedef void (*meow_scroll_set_fn)(void *ctx, int off);
|
||||
typedef int (*meow_scroll_max_fn)(void *ctx);
|
||||
typedef int (*meow_scroll_get_fn)(void *ctx);
|
||||
typedef void (*meow_scroll_redraw_fn)(void *ctx); /* 只刷滚动视口区(不整屏) */
|
||||
|
||||
/* 创建会话:app 提供 set/max/get/redraw。返回 NULL=池满。 */
|
||||
meow_scroll *meow_scroll_create(meow_scroll_set_fn set, meow_scroll_max_fn max,
|
||||
meow_scroll_get_fn get, meow_scroll_redraw_fn redraw,
|
||||
void *ctx);
|
||||
/* 便捷:包一个 meow_widget 列表(is_listview:1=W_LISTVIEW / 0=W_LIST 或 lazycolumn/row)。
|
||||
* redraw 只 flush 该控件矩形(视口区)。 */
|
||||
meow_scroll *meow_scroll_wrap(meow_widget *list, int is_listview);
|
||||
void meow_scroll_free(meow_scroll *s);
|
||||
|
||||
/* 拖动跟手 + 速度采样:dy=本次位移(px);t_ms=采样时刻(单调毫秒)。
|
||||
* 内部 set_scroll(pos+dy)(clamp 到 [0,max],与 app 直接 scroll_by 行为一致)。 */
|
||||
void meow_scroll_track(meow_scroll *s, int dy, uint64_t t_ms);
|
||||
|
||||
/* 松手 fling:内部用「最近 N 个采样加权」算初速,起减速度曲线动画推进位移;
|
||||
* 边界过冲 clamp + 简单回弹;每帧只 redraw 视口区。停止后可选 snap。 */
|
||||
void meow_scroll_fling(meow_scroll *s);
|
||||
/* 立即停止(取消 fling/回弹/snap,停在当前 offset)。 */
|
||||
void meow_scroll_stop(meow_scroll *s);
|
||||
|
||||
/* 当前加权初速(px/s;为 fling 内部所用,供 app 读取/调试)。 */
|
||||
int meow_scroll_velocity(meow_scroll *s);
|
||||
|
||||
/* 查询/配置 */
|
||||
int meow_scroll_active(meow_scroll *s); /* 是否有活动 fling/回弹/snap */
|
||||
int meow_scroll_offset(meow_scroll *s); /* 当前 scroll(get) */
|
||||
void meow_scroll_set_snap(meow_scroll *s, int step); /* >0=fling 停止后吸附到 step 倍数 */
|
||||
void meow_scroll_set_friction(meow_scroll *s, int tau_ms); /* 摩擦时间常数(默认 180ms) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* MEOW_UI_SCROLL_H */
|
||||
@@ -33,6 +33,8 @@ void meow_widget_free(meow_widget *w);
|
||||
|
||||
void meow_widget_draw(meow_widget *w); /* 每次 flush 前调用 */
|
||||
int meow_widget_hit(meow_widget *w, int x, int y); /* 点是否落在控件内 */
|
||||
/* 写控件矩形(§12.1 meow_box 布局引擎用;也可供 app 布局器用)。只设字段不标脏。 */
|
||||
void meow_widget_set_rect(meow_widget *w, int x, int y, int wd, int ht);
|
||||
|
||||
void meow_slider_set(meow_widget *s, int val);
|
||||
int meow_slider_get(meow_widget *s);
|
||||
|
||||
Reference in new issue
Block a user