// LINEAR BEZIER CURVES // =================================================== // B(t) = (1-t)P_0 + tP_1 void bezier2d_generate_linear ( vec2** pts, unsigned int count, unsigned int destct, vec2*** dest ) { *dest = malloc(sizeof(vec2*)*destct); double t = 0.0; double inc = (double)count/(double)destct; vec2 a, b, c; for(int i = 0, j=0; i < count-1; t += inc, j++) { if (t > 1.0) { t = t - 1.0; i++; } vec2_scale(&a, pts[i], 1.0-t); vec2_scale(&b, pts[i+1], t); vec2_add(&c, &a, &b); *dest[i] = vec2_copy(&c); } }
void obs_sceneitem_getscale(obs_sceneitem_t item, struct vec2 *scale) { vec2_copy(scale, &item->scale); }
static void update_item_transform(struct obs_scene_item *item) { uint32_t width = obs_source_get_width(item->source); uint32_t height = obs_source_get_height(item->source); uint32_t cx = calc_cx(item, width); uint32_t cy = calc_cy(item, height); struct vec2 base_origin; struct vec2 origin; struct vec2 scale = item->scale; struct calldata params; uint8_t stack[128]; if (os_atomic_load_long(&item->defer_update) > 0) return; width = cx; height = cy; vec2_zero(&base_origin); vec2_zero(&origin); /* ----------------------- */ if (item->bounds_type != OBS_BOUNDS_NONE) { calculate_bounds_data(item, &origin, &scale, &cx, &cy); } else { cx = (uint32_t)((float)cx * scale.x); cy = (uint32_t)((float)cy * scale.y); } add_alignment(&origin, item->align, (int)cx, (int)cy); matrix4_identity(&item->draw_transform); matrix4_scale3f(&item->draw_transform, &item->draw_transform, scale.x, scale.y, 1.0f); matrix4_translate3f(&item->draw_transform, &item->draw_transform, -origin.x, -origin.y, 0.0f); matrix4_rotate_aa4f(&item->draw_transform, &item->draw_transform, 0.0f, 0.0f, 1.0f, RAD(item->rot)); matrix4_translate3f(&item->draw_transform, &item->draw_transform, item->pos.x, item->pos.y, 0.0f); item->output_scale = scale; /* ----------------------- */ if (item->bounds_type != OBS_BOUNDS_NONE) { vec2_copy(&scale, &item->bounds); } else { scale.x = (float)width * item->scale.x; scale.y = (float)height * item->scale.y; } add_alignment(&base_origin, item->align, (int)scale.x, (int)scale.y); matrix4_identity(&item->box_transform); matrix4_scale3f(&item->box_transform, &item->box_transform, scale.x, scale.y, 1.0f); matrix4_translate3f(&item->box_transform, &item->box_transform, -base_origin.x, -base_origin.y, 0.0f); matrix4_rotate_aa4f(&item->box_transform, &item->box_transform, 0.0f, 0.0f, 1.0f, RAD(item->rot)); matrix4_translate3f(&item->box_transform, &item->box_transform, item->pos.x, item->pos.y, 0.0f); /* ----------------------- */ item->last_width = width; item->last_height = height; calldata_init_fixed(¶ms, stack, sizeof(stack)); calldata_set_ptr(¶ms, "scene", item->parent); calldata_set_ptr(¶ms, "item", item); signal_handler_signal(item->parent->source->context.signals, "item_transform", ¶ms); }
void obs_sceneitem_getpos(obs_sceneitem_t item, struct vec2 *pos) { vec2_copy(pos, &item->pos); }
void obs_sceneitem_getorigin(obs_sceneitem_t item, struct vec2 *origin) { vec2_copy(origin, &item->origin); }
void obs_sceneitem_setscale(obs_sceneitem_t item, const struct vec2 *scale) { vec2_copy(&item->scale, scale); }
void obs_sceneitem_setorigin(obs_sceneitem_t item, const struct vec2 *origin) { vec2_copy(&item->origin, origin); }
void obs_sceneitem_setpos(obs_sceneitem_t item, const struct vec2 *pos) { vec2_copy(&item->pos, pos); }
int main(void) { VEC2 vec1, vec2; long n = 4; size_t siz = sizeof(long); static long items1[100], items2[100]; /* NOTE: You cannot use vec2_init(). Use vec2_construct() instead. */ vec2_construct(&vec1, siz, 100, items1, 0); vec2_construct(&vec2, siz, 100, items2, 0); n = 1; vec2_push_back(&vec1, &n); assert(vec2_size(&vec1) == 1); printf("vec1: "); vec2_foreach(&vec1, print_foreach); printf("\n"); n = 2; vec2_push_back(&vec1, &n); assert(vec2_size(&vec1) == 2); printf("vec1: "); vec2_foreach(&vec1, print_foreach); printf("\n"); n = 3; vec2_push_back(&vec1, &n); assert(vec2_size(&vec1) == 3); printf("vec1: "); vec2_foreach(&vec1, print_foreach); printf("\n"); n = 1; assert(memcmp(vec2_item(&vec1, 0), &n, siz) == 0); n = 2; assert(memcmp(vec2_item(&vec1, 1), &n, siz) == 0); n = 3; assert(memcmp(vec2_item(&vec1, 2), &n, siz) == 0); assert(vec2_size(&vec2) == 0); n = -1; vec2_push_back(&vec2, &n); assert(vec2_size(&vec2) == 1); vec2_insert_sub(&vec1, 1, &vec2); printf("vec1: "); vec2_foreach(&vec1, print_foreach); printf("\n"); n = 1; assert(memcmp(vec2_item(&vec1, 0), &n, siz) == 0); n = -1; assert(memcmp(vec2_item(&vec1, 1), &n, siz) == 0); n = 2; assert(memcmp(vec2_item(&vec1, 2), &n, siz) == 0); n = 3; assert(memcmp(vec2_item(&vec1, 3), &n, siz) == 0); vec2_sort(&vec1, long_compare); printf("vec1: "); vec2_foreach(&vec1, print_foreach); printf("\n"); vec2_erase(&vec1, 0); n = 1; assert(memcmp(vec2_item(&vec1, 0), &n, siz) == 0); n = 2; assert(memcmp(vec2_item(&vec1, 1), &n, siz) == 0); n = 3; assert(memcmp(vec2_item(&vec1, 2), &n, siz) == 0); n = 4; vec2_insert(&vec1, 1, 1, &n); printf("vec1: "); vec2_foreach(&vec1, print_foreach); printf("\n"); n = 1; assert(memcmp(vec2_item(&vec1, 0), &n, siz) == 0); n = 4; assert(memcmp(vec2_item(&vec1, 1), &n, siz) == 0); n = 2; assert(memcmp(vec2_item(&vec1, 2), &n, siz) == 0); n = 3; assert(memcmp(vec2_item(&vec1, 3), &n, siz) == 0); vec2_erase_range(&vec1, 1, 2); vec2_shrink_to_fit(&vec1); printf("vec1: "); vec2_foreach(&vec1, print_foreach); printf("\n"); n = 1; assert(memcmp(vec2_item(&vec1, 0), &n, siz) == 0); n = 3; assert(memcmp(vec2_item(&vec1, 1), &n, siz) == 0); vec2_copy(&vec2, &vec1); printf("vec2: "); vec2_foreach(&vec2, print_foreach); printf("\n"); vec2_destroy(&vec1); vec2_destroy(&vec2); return 0; } /* main */
static int update(gesture_t *gest, const inputs_t *inputs, int mask) { const touch_t *ts = inputs->touches; int nb_ts = 0; int i, j; for (i = 0; i < ARRAY_SIZE(inputs->touches); i++) { for (j = 0; j < ARRAY_SIZE(inputs->touches[i].down); j++) { if (ts[i].down[j]) { nb_ts++; break; } } } if (gest->type == GESTURE_DRAG) { switch (gest->state) { case GESTURE_POSSIBLE: if (nb_ts == 1 && ts[0].down[gest->button]) { vec2_copy(ts[0].pos, gest->start_pos[0]); vec2_copy(gest->start_pos[0], gest->pos); if (!rect_contains(gest->viewport, gest->pos)) { gest->state = GESTURE_FAILED; break; } gest->state = (mask & (GESTURE_CLICK | GESTURE_PINCH)) ? GESTURE_RECOGNISED : GESTURE_BEGIN; } break; case GESTURE_RECOGNISED: if (vec2_dist(gest->start_pos[0], ts[0].pos) >= g_start_dist) gest->state = GESTURE_BEGIN; if (nb_ts == 0) { gest->state = (!(mask & GESTURE_CLICK)) ? GESTURE_BEGIN : GESTURE_FAILED; } if (nb_ts > 1) gest->state = GESTURE_FAILED; break; case GESTURE_BEGIN: case GESTURE_UPDATE: vec2_copy(ts[0].pos, gest->pos); gest->state = GESTURE_UPDATE; if (!ts[0].down[gest->button]) gest->state = GESTURE_END; break; } } if (gest->type == GESTURE_CLICK) { vec2_copy(ts[0].pos, gest->pos); switch (gest->state) { case GESTURE_POSSIBLE: if (ts[0].down[gest->button]) { vec2_copy(ts[0].pos, gest->start_pos[0]); gest->state = GESTURE_RECOGNISED; } break; case GESTURE_RECOGNISED: if (!ts[0].down[gest->button]) gest->state = GESTURE_TRIGGERED; break; } } if (gest->type == GESTURE_PINCH) { switch (gest->state) { case GESTURE_POSSIBLE: if (ts[0].down[0] && ts[1].down[0]) { gest->state = GESTURE_BEGIN; vec2_copy(ts[0].pos, gest->start_pos[0]); vec2_copy(ts[1].pos, gest->start_pos[1]); gest->pinch = 1; gest->rotation = 0; vec2_mix(ts[0].pos, ts[1].pos, 0.5, gest->pos); } break; case GESTURE_BEGIN: case GESTURE_UPDATE: gest->state = GESTURE_UPDATE; gest->pinch = vec2_dist(ts[0].pos, ts[1].pos) / vec2_dist(gest->start_pos[0], gest->start_pos[1]); gest->rotation = get_angle(gest->start_pos[0], gest->start_pos[1], ts[0].pos, ts[1].pos); vec2_mix(ts[0].pos, ts[1].pos, 0.5, gest->pos); if (!ts[0].down[0] || !ts[1].down[0]) gest->state = GESTURE_END; break; } } if (gest->type == GESTURE_HOVER) { switch (gest->state) { case GESTURE_POSSIBLE: if (DEFINED(GOXEL_MOBILE)) break; //Workaround. if (nb_ts == 0) { vec2_copy(ts[0].pos, gest->pos); if (rect_contains(gest->viewport, gest->pos)) { gest->state = GESTURE_BEGIN; } } break; case GESTURE_BEGIN: case GESTURE_UPDATE: vec2_copy(ts[0].pos, gest->pos); gest->state = rect_contains(gest->viewport, gest->pos) ? GESTURE_UPDATE : GESTURE_END; break; } } return 0; }