Quick Start Guide
This guide will help you get started with ESP Emote GFX in just a few steps.
Installation
Add ESP Emote GFX to your ESP-IDF project by including it as a component. The component is available through the ESP Component Registry.
Basic Setup
Include the main header:
#include "gfx.h"
Initialize the graphics core (no display yet):
gfx_core_config_t gfx_cfg = {
.fps = 30,
.task = GFX_EMOTE_INIT_CONFIG()
};
gfx_handle_t handle = gfx_emote_init(&gfx_cfg);
if (handle == NULL) {
ESP_LOGE(TAG, "Failed to initialize GFX");
return;
}
Add a display with a flush callback:
void disp_flush_callback(gfx_disp_t *disp, int x1, int y1, int x2, int y2, const void *data)
{
void *panel = gfx_disp_get_user_data(disp);
// Send RGB565 data (x1,y1)-(x2,y2) to your panel, e.g. esp_lcd_panel_draw_bitmap(panel, x1, y1, x2, y2, data);
}
gfx_disp_config_t disp_cfg = {
.h_res = 320,
.v_res = 240,
.flush_cb = disp_flush_callback,
.update_cb = NULL,
.user_data = your_panel_handle, // e.g. esp_lcd_panel_handle_t
.flags = { .swap = true },
.buffers = { .buf1 = NULL, .buf2 = NULL, .buf_pixels = 320 * 16 },
};
gfx_disp_t *disp = gfx_disp_add(handle, &disp_cfg);
if (disp == NULL) {
ESP_LOGE(TAG, "Failed to add display");
gfx_emote_deinit(handle);
return;
}
(Optional) Register panel IO callback so the framework knows when flush is done:
static bool flush_io_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
{
gfx_disp_t *disp = (gfx_disp_t *)user_ctx;
if (disp) {
gfx_disp_flush_ready(disp, true);
}
return true;
}
const esp_lcd_panel_io_callbacks_t cbs = { .on_color_trans_done = flush_io_ready };
esp_lcd_panel_io_register_event_callbacks(io_handle, &cbs, disp);
(Optional) Add touch input:
void touch_event_cb(gfx_touch_t *touch, const gfx_touch_event_t *event, void *user_data)
{
// Handle PRESS / MOVE / RELEASE; event->x, event->y, event->hit_obj
}
gfx_touch_config_t touch_cfg = {
.handle = esp_lcd_touch_handle, // from your BSP or esp_lcd_touch_new
.event_cb = touch_event_cb,
.disp = disp,
.poll_ms = 50,
.user_data = NULL,
};
gfx_touch_t *touch = gfx_touch_add(handle, &touch_cfg);
Creating Your First Widget
Widgets are created on a display (gfx_disp_t *), not on the handle.
Creating a Label
gfx_obj_t *label = gfx_label_create(disp);
gfx_label_set_text(label, "Hello, World!");
gfx_obj_set_pos(label, 50, 50);
gfx_label_set_color(label, GFX_COLOR_HEX(0xFF0000)); // Red
Creating an Image
gfx_obj_t *img = gfx_img_create(disp);
extern const gfx_image_dsc_t my_image;
gfx_img_set_src(img, (void *)&my_image);
gfx_obj_set_pos(img, 100, 100);
Creating an Animation
gfx_obj_t *anim = gfx_anim_create(disp);
gfx_anim_set_src(anim, anim_data, anim_size);
gfx_obj_align(anim, GFX_ALIGN_CENTER, 0, 0);
gfx_anim_set_segment(anim, 0, 0xFFFF, 15, true);
gfx_anim_start(anim);
Creating a Rig Scene
Rig scenes are created from a generated gfx_motion_asset_t and managed by gfx_motion_player_t.
#include "gfx.h"
#include "rig_active.inc"
static gfx_motion_player_t motion_player;
void setup_motion_scene(gfx_disp_t *disp)
{
gfx_motion_player_init(&motion_player, disp, &s_motion_scene_asset);
gfx_motion_player_set_canvas(&motion_player, 0, 0, 320, 240);
gfx_motion_player_set_color(&motion_player, GFX_COLOR_HEX(0xFF7A00));
gfx_motion_player_set_action(&motion_player, 0, true);
}
Use gfx_motion_player_deinit() when the scene is no longer needed.
Object touch callback (e.g. drag)
void my_touch_cb(gfx_obj_t *obj, const gfx_touch_event_t *event, void *user_data)
{
if (event->type == GFX_TOUCH_EVENT_PRESS) { /* ... */ }
if (event->type == GFX_TOUCH_EVENT_MOVE) { gfx_obj_set_pos(obj, event->x, event->y); }
}
gfx_obj_set_touch_cb(label, my_touch_cb, NULL);
Thread Safety
When modifying objects from outside the graphics task, use the graphics lock:
gfx_emote_lock(handle);
gfx_label_set_text(label, "Updated text");
gfx_obj_set_pos(img, new_x, new_y);
gfx_emote_unlock(handle);
Complete Example
#include "gfx.h"
#include "esp_log.h"
static const char *TAG = "gfx_example";
static gfx_handle_t gfx_handle = NULL;
static gfx_disp_t *gfx_disp = NULL;
static void disp_flush_callback(gfx_disp_t *disp, int x1, int y1, int x2, int y2, const void *data)
{
esp_lcd_panel_handle_t panel = (esp_lcd_panel_handle_t)gfx_disp_get_user_data(disp);
esp_lcd_panel_draw_bitmap(panel, x1, y1, x2, y2, data);
}
void app_main(void)
{
gfx_core_config_t gfx_cfg = {
.fps = 30,
.task = GFX_EMOTE_INIT_CONFIG(),
};
gfx_handle = gfx_emote_init(&gfx_cfg);
if (gfx_handle == NULL) {
ESP_LOGE(TAG, "Failed to initialize GFX");
return;
}
gfx_disp_config_t disp_cfg = {
.h_res = 320,
.v_res = 240,
.flush_cb = disp_flush_callback,
.update_cb = NULL,
.user_data = panel_handle, // your esp_lcd_panel_handle_t
.flags = { .swap = true },
.buffers = { .buf1 = NULL, .buf2 = NULL, .buf_pixels = 320 * 16 },
};
gfx_disp = gfx_disp_add(gfx_handle, &disp_cfg);
if (gfx_disp == NULL) {
ESP_LOGE(TAG, "Failed to add display");
gfx_emote_deinit(gfx_handle);
return;
}
gfx_obj_t *label = gfx_label_create(gfx_disp);
gfx_label_set_text(label, "Hello, ESP Emote GFX!");
gfx_obj_set_pos(label, 50, 50);
gfx_label_set_color(label, GFX_COLOR_HEX(0x00FF00));
gfx_disp_refresh_all(gfx_disp);
ESP_LOGI(TAG, "GFX application started");
}
Next Steps
Read the Core API Reference for detailed API documentation
Read the Rig Widget Guide for the scene asset model and playback flow
Check out the Widget API Reference for widget-specific functions
See Examples for more complex usage patterns