Hi,
I want to know what the problem is and what methods can be optimized.
This effect is shown in the figure
Hi,
I want to know what the problem is and what methods can be optimized.
This effect is shown in the figure
The issue is that when the button is placed above the triangle in the Z-order the button’s corner isn’t drawn properly?
1.Both button object and triangle object setup lv_obj_set_drag(object, true)
2.The triangle object is always on top
3.When I drag the button object move to the triangle object until overlap, the triangle object effect be changed, I expect that the triangle object effect don’t be changed
So I wonder if it’s possible to achieve this or feasible advice.
In the second effect comparison, the button’s corner shouldn’t be visible inside the triangle. It looks like a bug with LittlevGL to me.
When overlapping, this is generated when the triangle object is redrawn.
In fact, the triangle object does not need to be mixed with the button object.
Hi, The code like this
typedef struct {
lv_point_t points[3];
bool auto_size;
} lv_triangle_ext_t;
lv_obj_t* lv_triangle_create(lv_obj_t* par, const lv_obj_t* copy);
void lv_triangle_set_points(lv_obj_t* obj, const lv_point_t* points);
void lv_triangle_set_auto_size(lv_obj_t* obj, bool en);
bool lv_triangle_get_auto_size(const lv_obj_t* obj);
static bool lv_triangle_design(lv_obj_t* obj, const lv_area_t* mask, lv_design_mode_t mode);
lv_obj_t* lv_triangle_create(lv_obj_t* par, const lv_obj_t* copy)
{
lv_obj_t* obj = lv_obj_create(par, copy);
LV_ASSERT_MEM(obj);
if (obj == NULL) return NULL;
lv_triangle_ext_t* ext = (lv_triangle_ext_t*)lv_obj_allocate_ext_attr(obj, sizeof(lv_triangle_ext_t));
LV_ASSERT_MEM(ext);
if (ext == NULL){
lv_obj_del(obj);
return NULL;
}
ext->auto_size = 1;
lv_obj_set_design_cb(obj, lv_triangle_design);
lv_obj_set_click(obj, false);
if (copy == NULL) {
lv_obj_set_size(obj, LV_DPI, LV_DPI); /*Auto size is enables, but set default size until no points are added*/
lv_obj_set_style(obj, NULL); /*Inherit parent's style*/
}
else {
lv_triangle_ext_t* copy_ext = (lv_triangle_ext_t*)lv_obj_get_ext_attr(copy);
lv_triangle_set_points(obj, copy_ext->points);
lv_obj_set_style(obj, lv_obj_get_style(copy));
lv_obj_refresh_style(obj);
}
return obj;
}
void lv_triangle_set_points(lv_obj_t* obj, const lv_point_t* points)
{
lv_triangle_ext_t* ext = (lv_triangle_ext_t*)lv_obj_get_ext_attr(obj);
ext->points[0] = points[0];
ext->points[1] = points[1];
ext->points[2] = points[2];
if (ext->auto_size != 0) {
uint16_t i;
lv_coord_t xmax = LV_COORD_MIN;
lv_coord_t ymax = LV_COORD_MIN;
for (i = 0; i < 3; i++) {
xmax = LV_MATH_MAX(points[i].x, xmax);
ymax = LV_MATH_MAX(points[i].y, ymax);
}
const lv_style_t* style = lv_obj_get_style(obj);
lv_obj_set_size(obj, xmax + style->body.border.width, ymax + style->body.border.width);
}
lv_obj_invalidate(obj);
}
void lv_triangle_set_auto_size(lv_obj_t* obj, bool en)
{
lv_triangle_ext_t* ext = (lv_triangle_ext_t*)lv_obj_get_ext_attr(obj);
if (ext->auto_size == en) return;
ext->auto_size = en == false ? 0 : 1;
if (en) lv_triangle_set_points(obj, ext->points);
}
bool lv_triangle_get_auto_size(const lv_obj_t* obj) {
lv_triangle_ext_t* ext = (lv_triangle_ext_t*)lv_obj_get_ext_attr(obj);
return ext->auto_size;
}
static bool lv_triangle_design(lv_obj_t* obj, const lv_area_t* mask, lv_design_mode_t mode)
{
if (mode == LV_DESIGN_COVER_CHK) {
return false;
}
else if (mode == LV_DESIGN_DRAW_MAIN) {
lv_triangle_ext_t* ext = (lv_triangle_ext_t*)lv_obj_get_ext_attr(obj);
if ((ext->points[0].x == ext->points[1].x && ext->points[0].y == ext->points[1].y) ||
(ext->points[0].x == ext->points[2].x && ext->points[0].y == ext->points[2].y) ||
(ext->points[1].x == ext->points[2].x && ext->points[1].y == ext->points[2].y))
return true;
const lv_style_t* style = lv_obj_get_style(obj);
lv_opa_t opa_scale = lv_obj_get_opa_scale(obj);
lv_area_t offset;
lv_obj_get_coords(obj, &offset);
lv_point_t points[3] = { {ext->points[0].x + offset.x1, ext->points[0].y + offset.y1},
{ext->points[1].x + offset.x1, ext->points[1].y + offset.y1},
{ext->points[2].x + offset.x1, ext->points[2].y + offset.y1} };
if (style->body.opa != 0){
lv_draw_triangle(points, mask, style, opa_scale);
}
if (style->line.width) {
lv_style_t style_line; lv_style_copy(&style_line, style);
style_line.line.width = style->body.border.width;
style_line.line.color = style->body.border.color;
lv_draw_line(&points[0], &points[1], mask, &style_line, opa_scale);
lv_draw_line(&points[1], &points[2], mask, &style_line, opa_scale);
lv_draw_line(&points[2], &points[0], mask, &style_line, opa_scale);
}
}
return true;
}
void ui_test(void)
{
lv_obj_t *btn_obj = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_size(btn_obj, 60, 60);
lv_obj_set_drag(btn_obj, true);
lv_obj_t *triangle_obj = lv_triangle_create(lv_scr_act(), NULL);
static lv_style_t triangle_style;
lv_style_copy(&triangle_style, &lv_style_plain);
triangle_style.body.main_color = LV_COLOR_BLUE;
triangle_style.body.grad_color = LV_COLOR_PURPLE;
triangle_style.body.opa = LV_OPA_COVER;
triangle_style.body.border.color = LV_COLOR_RED;
triangle_style.body.border.width = 2;
triangle_style.body.border.opa = LV_OPA_COVER;
lv_obj_set_style(triangle_obj, &triangle_style);
static lv_point_t triangle_pts[] = {
{ 0, 50 },
{ 30, 0 },
{ 60, 60 },
};
lv_triangle_set_points(triangle_obj, triangle_pts);
lv_obj_set_drag(triangle_obj, true);
}
Thanks. I’ve just fixed it in dev-7.0
.
I’ve also slightly modified you design function:
dev-7.0
it has lv_design_res_t
return valuestatic lv_design_res_t lv_triangle_design(lv_obj_t* obj, const lv_area_t* mask, lv_design_mode_t mode)
{
if (mode == LV_DESIGN_COVER_CHK) {
return LV_DESIGN_RES_NOT_COVER;
}
else if (mode == LV_DESIGN_DRAW_MAIN) {
lv_triangle_ext_t* ext = (lv_triangle_ext_t*)lv_obj_get_ext_attr(obj);
if ((ext->points[0].x == ext->points[1].x && ext->points[0].y == ext->points[1].y) ||
(ext->points[0].x == ext->points[2].x && ext->points[0].y == ext->points[2].y) ||
(ext->points[1].x == ext->points[2].x && ext->points[1].y == ext->points[2].y))
return true;
const lv_style_t* style = lv_obj_get_style(obj);
lv_opa_t opa_scale = lv_obj_get_opa_scale(obj);
lv_area_t offset;
lv_obj_get_coords(obj, &offset);
lv_point_t points[3] = { {ext->points[0].x + offset.x1, ext->points[0].y + offset.y1},
{ext->points[1].x + offset.x1, ext->points[1].y + offset.y1},
{ext->points[2].x + offset.x1, ext->points[2].y + offset.y1} };
if (style->body.opa != 0){
/*Polygons are drawn from rectangles.
* Disable border an shadow because the border would be applied on the masked rectangle not the polygon */
lv_style_t style_tmp;
lv_style_copy(&style_tmp, style);
style_tmp.body.border.width = 0;
style_tmp.body.shadow.width = 0;
lv_draw_triangle(points, mask, &style_tmp, opa_scale);
}
if (style->line.width) {
lv_style_t style_line; lv_style_copy(&style_line, style);
style_line.line.width = style->body.border.width;
style_line.line.color = style->body.border.color;
lv_draw_line(&points[0], &points[1], mask, &style_line, opa_scale);
lv_draw_line(&points[1], &points[2], mask, &style_line, opa_scale);
lv_draw_line(&points[2], &points[0], mask, &style_line, opa_scale);
}
}
return LV_DESIGN_RES_OK;
}
Thank you very much. I’ve just tested it and it works.
Great! Thanks for the feedback!