static int draw_child(struct sprite *s, struct srt *srt, struct sprite_trans * ts) { struct sprite_trans temp; struct matrix temp_matrix; struct sprite_trans *t = trans_mul(&s->t, ts, &temp, &temp_matrix); switch (s->type) { case TYPE_PICTURE: switch_program(t, PROGRAM_PICTURE); sprite_drawquad(s->s.pic, srt, t); return 0; case TYPE_POLYGON: switch_program(t, PROGRAM_PICTURE); sprite_drawpolygon(s->s.poly, srt, t); return 0; case TYPE_LABEL: if (s->data.text) { switch_program(t, s->s.label->edge ? PROGRAM_TEXT_EDGE : PROGRAM_TEXT); label_draw(s->data.text, s->s.label,srt,t); } return 0; case TYPE_ANCHOR: anchor_update(s, srt, t); return 0; case TYPE_ANIMATION: break; case TYPE_PANNEL: if (s->data.scissor) { // enable scissor set_scissor(s->s.pannel, srt, t); return 1; } else { return 0; } default: // todo : invalid type return 0; } // draw animation struct pack_animation *ani = s->s.ani; int frame = real_frame(s) + s->start_frame; struct pack_frame * pf = &ani->frame[frame]; int i; int scissor = 0; for (i=0;i<pf->n;i++) { struct pack_part *pp = &pf->part[i]; int index = pp->component_id; struct sprite * child = s->data.children[index]; if (child == NULL || child->visible == false) { continue; } struct sprite_trans temp2; struct matrix temp_matrix2; struct sprite_trans *ct = trans_mul(&pp->t, t, &temp2, &temp_matrix2); scissor += draw_child(child, srt, ct); } for (i=0;i<scissor;i++) { scissor_pop(); } return 0; }
static int child_pos(struct sprite *s, struct srt *srt, struct sprite_trans *ts, struct sprite *t, int pos[2]) { struct sprite_trans temp; struct matrix temp_matrix; struct sprite_trans *st = trans_mul(&s->t, ts, &temp, &temp_matrix); if (s == t) { struct matrix tmp; if (st->mat == NULL) { matrix_identity(&tmp); } else { tmp = *st->mat; } matrix_srt(&tmp, srt); switch (s->type) { case TYPE_PICTURE: picture_pos(tmp.m, s->s.pic, srt, st, pos); return 0; case TYPE_LABEL: label_pos(tmp.m, s->s.label, srt, st, pos); return 0; case TYPE_ANIMATION: case TYPE_PANNEL: pos[0] = tmp.m[4] / SCREEN_SCALE; pos[1] = tmp.m[5] / SCREEN_SCALE; return 0; default: return 1; } } if (s->type != TYPE_ANIMATION){ return 1; } struct pack_animation *ani = s->s.ani; int frame = real_frame(s) + s->start_frame; struct pack_frame * pf = &ani->frame[frame]; int i; for (i=0;i<pf->n;i++) { struct pack_part *pp = &pf->part[i]; int index = pp->component_id; struct sprite * child = s->data.children[index]; if (child == NULL) { continue; } struct sprite_trans temp2; struct matrix temp_matrix2; struct sprite_trans *ct = trans_mul(&pp->t, st, &temp2, &temp_matrix2); if (child_pos(child, srt, ct, t, pos) == 0) { return 0; } } return 1; }
bool sprite_child_visible(struct sprite *s, const char * childname) { struct pack_animation *ani = s->s.ani; int frame = real_frame(s) + s->start_frame; struct pack_frame * pf = &ani->frame[frame]; int i; for (i=0;i<pf->n;i++) { struct pack_part *pp = &pf->part[i]; int index = pp->component_id; struct sprite * child = s->data.children[index]; if (child->name && strcmp(childname, child->name) == 0) { return true; } } return false; }
/* return 1 : test succ 0 : test failed, but *touch capture the message */ static int test_animation(struct sprite *s, struct srt *srt, struct matrix * t, int x, int y, struct sprite ** touch) { struct pack_animation *ani = s->s.ani; int frame = real_frame(s) + s->start_frame; struct pack_frame * pf = &ani->frame[frame]; int start = pf->n-1; do { int scissor = -1; int i; // find scissor and check it first for (i=start;i>=0;i--) { struct pack_part *pp = &pf->part[i]; int index = pp->component_id; struct sprite * c = s->data.children[index]; if (c == NULL || !c->visible) { continue; } if (c->type == TYPE_PANNEL && c->data.scissor) { scissor = i; break; } } if (scissor >=0) { struct sprite *tmp = NULL; check_child(s, srt, t, pf, scissor, x, y, &tmp); if (tmp == NULL) { start = scissor - 1; continue; } } else { scissor = 0; } for (i=start;i>=scissor;i--) { int hit = check_child(s, srt, t, pf, i, x, y, touch); if (hit) return 1; } start = scissor - 1; } while(start>=0); return 0; }
static int child_aabb(struct sprite *s, struct srt *srt, struct matrix * mat, int aabb[4]) { struct matrix temp; struct matrix *t = mat_mul(s->t.mat, mat, &temp); switch (s->type) { case TYPE_PICTURE: quad_aabb(s->s.pic, srt, t, aabb); return 0; case TYPE_POLYGON: polygon_aabb(s->s.poly, srt, t, aabb); return 0; case TYPE_LABEL: label_aabb(s->s.label, srt, t, aabb); return 0; case TYPE_ANIMATION: break; case TYPE_PANNEL: panel_aabb(s->s.pannel, srt, t, aabb); return s->data.scissor; default: // todo : invalid type return 0; } // draw animation struct pack_animation *ani = s->s.ani; int frame = real_frame(s) + s->start_frame; struct pack_frame * pf = &ani->frame[frame]; int i; for (i=0;i<pf->n;i++) { struct pack_part *pp = &pf->part[i]; int index = pp->component_id; struct sprite * child = s->data.children[index]; if (child == NULL || child->visible == false) { continue; } struct matrix temp2; struct matrix *ct = mat_mul(pp->t.mat, t, &temp2); if (child_aabb(child, srt, ct, aabb)) break; } return 0; }
void sprite_matrix(struct sprite * self, struct matrix *mat) { struct sprite * parent = self->parent; if (parent) { assert(parent->type == TYPE_ANIMATION); sprite_matrix(parent, mat); struct matrix tmp; struct matrix * parent_mat = parent->t.mat; struct matrix * child_mat = NULL; struct pack_animation *ani = parent->s.ani; int frame = real_frame(parent) + parent->start_frame; struct pack_frame * pf = &ani->frame[frame]; int i; for (i=0;i<pf->n;i++) { struct pack_part *pp = &pf->part[i]; int index = pp->component_id; struct sprite * child = parent->data.children[index]; if (child == self) { child_mat = pp->t.mat; break; } } if (parent_mat == NULL && child_mat == NULL) return; if (parent_mat) { matrix_mul(&tmp, parent_mat, mat); } else { tmp = *mat; } if (child_mat) { matrix_mul(mat, child_mat, &tmp); } else { *mat = tmp; } } else { matrix_identity(mat); } }