static void a3d_sprite_draw(a3d_widget_t* widget) { assert(widget); LOGD("debug"); a3d_sprite_t* self = (a3d_sprite_t*) widget; a3d_screen_t* screen = widget->screen; a3d_mat4f_t mvp; // draw sprite a3d_vec4f_t* c = &self->color; float alpha = widget->fade*c->a; if(alpha > 0.0f) { float w = 0.0f; float h = 0.0f; float x = widget->rect_draw.l; float y = widget->rect_draw.t; float ww = widget->rect_draw.w; float hh = widget->rect_draw.h; a3d_screen_sizef(screen, &w, &h); a3d_mat4f_ortho(&mvp, 1, 0.0f, w, h, 0.0f, 0.0f, 2.0f); a3d_mat4f_translate(&mvp, 0, x + ww/2.0f, y + hh/2.0f, -1.0f); a3d_mat4f_scale(&mvp, 0, ww, hh, 1.0f); a3d_mat4f_rotate(&mvp, 0, self->theta, 0.0f, 0.0f, 1.0f); a3d_spriteShader_t* shader = a3d_screen_spriteShader(screen); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glUseProgram(shader->prog); glEnableVertexAttribArray(shader->attr_vertex); glEnableVertexAttribArray(shader->attr_coords); glBindTexture(GL_TEXTURE_2D, self->id_tex[self->index]); glBindBuffer(GL_ARRAY_BUFFER, self->id_vertex); glVertexAttribPointer(shader->attr_vertex, 4, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, self->id_coords); glVertexAttribPointer(shader->attr_coords, 2, GL_FLOAT, GL_FALSE, 0, 0); glUniform4f(shader->unif_color, c->r, c->g, c->b, alpha); glUniformMatrix4fv(shader->unif_mvp, 1, GL_FALSE, (GLfloat*) &mvp); glUniform1i(shader->unif_sampler, 0); glDrawArrays(GL_TRIANGLES, 0, 6); glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableVertexAttribArray(shader->attr_coords); glDisableVertexAttribArray(shader->attr_vertex); glUseProgram(0); glDisable(GL_BLEND); } }
void a3d_widget_layoutSize(a3d_widget_t* self, float* w, float* h) { assert(self); assert(w); assert(h); LOGD("debug w=%f, h=%f", *w, *h); float sw; float sh; a3d_screen_sizef(self->screen, &sw, &sh); a3d_font_t* font = a3d_screen_font(self->screen, A3D_SCREEN_FONT_REGULAR); float ar = a3d_font_aspectRatioAvg(font); float th = 0.0f; if((self->wrapy >= A3D_WIDGET_WRAP_STRETCH_TEXT_SMALL) && (self->wrapy <= A3D_WIDGET_WRAP_STRETCH_TEXT_LARGE)) { int style = self->wrapy - A3D_WIDGET_WRAP_STRETCH_TEXT_SMALL; th = a3d_screen_layoutText(self->screen, style); } float tw = ar*th; // screen/text/parent square float ssq = (sw > sh) ? sh : sw; float tsq = th; // always use the height for square float psq = (*w > *h) ? *h : *w; int sq = (self->stretch_mode == A3D_WIDGET_STRETCH_SQUARE); // initialize size float h_bo = 0.0f; float v_bo = 0.0f; a3d_screen_layoutBorder(self->screen, self->style_border, &h_bo, &v_bo); if(self->wrapx == A3D_WIDGET_WRAP_SHRINK) { self->rect_draw.w = *w - 2.0f*h_bo; self->rect_border.w = *w; } else { float rw = 0.0f; if(self->wrapx == A3D_WIDGET_WRAP_STRETCH_SCREEN) { rw = sq ? ssq : sw; rw *= self->stretch_factor; self->rect_draw.w = rw - 2.0f*h_bo; self->rect_border.w = rw; } else if((self->wrapx >= A3D_WIDGET_WRAP_STRETCH_TEXT_SMALL) && (self->wrapx <= A3D_WIDGET_WRAP_STRETCH_TEXT_LARGE)) { rw = sq ? tsq : tw; rw *= self->stretch_factor; self->rect_draw.w = rw; self->rect_border.w = rw + 2.0f*h_bo; } else { rw = sq ? psq : *w; rw *= self->stretch_factor; self->rect_draw.w = rw - 2.0f*h_bo; self->rect_border.w = rw; } } // intersect draw with border interior if(self->rect_draw.w < 0.0f) { self->rect_draw.w = 0.0f; } if(self->wrapy == A3D_WIDGET_WRAP_SHRINK) { self->rect_draw.h = *h - 2.0f*v_bo; self->rect_border.h = *h; } else { float rh = 0.0f; if(self->wrapy == A3D_WIDGET_WRAP_STRETCH_SCREEN) { rh = sq ? ssq : sh; rh *= self->stretch_factor; self->rect_draw.h = rh - 2.0f*v_bo; self->rect_border.h = rh; } else if((self->wrapy >= A3D_WIDGET_WRAP_STRETCH_TEXT_SMALL) && (self->wrapy <= A3D_WIDGET_WRAP_STRETCH_TEXT_LARGE)) { rh = sq ? tsq : th; rh *= self->stretch_factor; self->rect_draw.h = rh; self->rect_border.h = rh + 2.0f*v_bo; } else { rh = sq ? psq : *h; rh *= self->stretch_factor; self->rect_draw.h = rh - 2.0f*v_bo; self->rect_border.h = rh; } } // intersect draw with border interior if(self->rect_draw.h < 0.0f) { self->rect_draw.h = 0.0f; } // reflow dynamically sized widgets (e.g. textbox) // this makes the most sense for stretched widgets float draw_w = self->rect_draw.w; float draw_h = self->rect_draw.h; a3d_widget_reflow_fn reflow_fn = self->reflow_fn; if(reflow_fn) { (*reflow_fn)(self, draw_w, draw_h); } // compute draw size for shrink wrapped widgets and // recursively compute size of any children // the draw size of the widget also becomes the border // size of any children a3d_widget_size_fn size_fn = self->size_fn; if(size_fn) { (*size_fn)(self, &draw_w, &draw_h); } // wrap width if(self->wrapx == A3D_WIDGET_WRAP_SHRINK) { self->rect_draw.w = draw_w; self->rect_border.w = draw_w + 2.0f*h_bo; } // wrap height if(self->wrapy == A3D_WIDGET_WRAP_SHRINK) { self->rect_draw.h = draw_h; self->rect_border.h = draw_h + 2.0f*v_bo; } *w = self->rect_border.w; *h = self->rect_border.h; }