Exemplo n.º 1
0
void *action_exec(const action_t *action, const arg_t *args)
{
    void *ret = NULL;
    int i, nb_args;
    long vals[4];
    // So that we do not add undo snapshot when an action calls an other one.
    static int reentry = 0;
    // XXX: not sure this is actually legal in C.  func will be called with
    // a variable number or arguments, that might be of any registered types!
    void *(*func)() = action->func;
    bool is_void;

    assert(action);
    nb_args = action->sig.nb_args;
    assert(nb_args <= ARRAY_SIZE(vals));
    is_void = action->sig.ret == TYPE_VOID;

    // For the moment all action cancel the current tool, for simplicity.
    tool_cancel(goxel(), goxel()->tool, goxel()->tool_state);

    if (reentry == 0 && !(action->flags & ACTION_NO_CHANGE)) {
        image_history_push(goxel()->image);
    }

    reentry++;

    for (i = 0; i < nb_args; i++)
        vals[i] = get_arg_value(action->sig.args[i], args);

    if (is_void && nb_args == 0)
        func();
    else if (is_void && nb_args == 1)
        func(vals[0]);
    else if (is_void && nb_args == 2)
        func(vals[0], vals[1]);
    else if (is_void && nb_args == 3)
        func(vals[0], vals[1], vals[2]);
    else if (is_void && nb_args == 4)
        func(vals[0], vals[1], vals[2], vals[3]);
    else if (!is_void && nb_args == 0)
        ret = func();
    else if (!is_void && nb_args == 1)
        ret = func(vals[0]);
    else if (!is_void && nb_args == 2)
        ret = func(vals[0], vals[1]);
    else if (!is_void && nb_args == 3)
        ret = func(vals[0], vals[1], vals[2]);
    else if (!is_void && nb_args == 4)
        ret = func(vals[0], vals[1], vals[2], vals[3]);
    else
        LOG_E("Cannot handle signature for action %s", action->id);

    reentry--;
    if (reentry == 0 && !(action->flags & ACTION_NO_CHANGE)) {
        goxel_update_meshes(goxel(), -1);
    }
    return ret;
}
Exemplo n.º 2
0
static int tool_laser_iter(goxel_t *goxel, const inputs_t *inputs, int state,
                           const vec2_t *view_size, bool inside)
{
    vec3_t pos, normal;
    box_t box;
    painter_t painter = goxel->painter;
    mesh_t *mesh = goxel->image->active_layer->mesh;
    const bool down = inputs->mouse_down[0];
    // XXX: would be nice if we got the vec4_t view instead of view_size,
    // and why input->pos is not already in win pos?
    vec4_t view = vec4(0, 0, view_size->x, view_size->y);
    vec2_t win = inputs->mouse_pos;
    win.y = view_size->y - win.y;

    painter.op = OP_SUB;
    painter.shape = &shape_cylinder;
    // Create the tool box from the camera along the visible ray.
    camera_get_ray(&goxel->camera, &win, &view, &pos, &normal);
    box.mat = mat4_identity;
    box.w = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat),
                     vec4(1, 0, 0, 0)).xyz;
    box.h = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat),
                     vec4(0, 1, 0, 0)).xyz;
    box.d = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat),
                     vec4(0, 0, 1, 0)).xyz;
    box.d = vec3_neg(normal);
    box.p = pos;
    // Just a large value for the size of the laser box.
    mat4_itranslate(&box.mat, 0, 0, -1024);
    mat4_iscale(&box.mat, goxel->tool_radius, goxel->tool_radius, 1024);
    render_box(&goxel->rend, &box, false, NULL, false);
    if (state == STATE_IDLE) {
        if (down) {
            state = STATE_PAINT;
            image_history_push(goxel->image);
        }
    }
    if (state == STATE_PAINT) {
        if (!down) {
            return STATE_IDLE;
        }
        mesh_op(mesh, &painter, &box);
        goxel_update_meshes(goxel, -1);
    }
    return state;
}
Exemplo n.º 3
0
static int tool_laser_iter(goxel_t *goxel, const inputs_t *inputs, int state,
                           const vec2_t *view_size, bool inside)
{
    vec3_t pos, normal;
    box_t box;
    painter_t painter = goxel->painter;
    mesh_t *mesh = goxel->image->active_layer->mesh;
    const bool down = inputs->mouse_down[0];

    painter.op = OP_SUB;
    painter.shape = &shape_cylinder;
    // Create the laser box with an inifinity width.
    goxel_unproject_on_screen(goxel, view_size, &inputs->mouse_pos,
                              &pos, &normal);
    box.mat = mat4_identity;
    box.w = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat),
                     vec4(1, 0, 0, 0)).xyz;
    box.h = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat),
                     vec4(0, 1, 0, 0)).xyz;
    box.d = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat),
                     vec4(0, 0, 1, 0)).xyz;
    box.p = pos;
    mat4_itranslate(&box.mat, 0, 0, -128);
    mat4_iscale(&box.mat, goxel->tool_radius, goxel->tool_radius, 128);
    render_box(&goxel->rend, &box, false, NULL, false);
    if (state == STATE_IDLE) {
        if (down) state = STATE_PAINT;
    }
    if (state == STATE_PAINT) {
        if (!down) {
            image_history_push(goxel->image);
            return STATE_IDLE;
        }
        mesh_op(mesh, &painter, &box);
        goxel_update_meshes(goxel, false);
    }
    return state;
}
Exemplo n.º 4
0
static void do_move(layer_t *layer, const float mat[4][4])
{
    float m[4][4];

    mat4_set_identity(m);
    // Change referential to the mesh origin.
    // XXX: maybe this should be done in mesh_move directy??
    mat4_itranslate(m, -0.5, -0.5, -0.5);
    mat4_imul(m, mat);
    mat4_itranslate(m, +0.5, +0.5, +0.5);

    if (layer->base_id || layer->image) {
        mat4_mul(mat, layer->mat, layer->mat);
        layer->base_mesh_key = 0;
    } else {
        mesh_move(layer->mesh, m);
        if (!box_is_null(layer->box)) {
            mat4_mul(mat, layer->box, layer->box);
            box_get_bbox(layer->box, layer->box);
        }
    }
    goxel_update_meshes(goxel, -1);
}
Exemplo n.º 5
0
static int tool_cube_iter(goxel_t *goxel, const inputs_t *inputs, int state,
                          const vec2_t *view_size, bool inside)
{
    const bool down = inputs->mouse_down[0];
    const bool up = !down;
    int snaped = 0;
    vec3_t pos, normal;
    box_t box;
    uvec4b_t box_color = HEXCOLOR(0xffff00ff);
    mesh_t *mesh = goxel->image->active_layer->mesh;

    if (inside)
        snaped = goxel_unproject(goxel, view_size, &inputs->mouse_pos,
                                 &pos, &normal);
    if (snaped) {
        if (    snaped == SNAP_MESH && goxel->painter.op == OP_ADD &&
                !goxel->snap_offset)
            vec3_iadd(&pos, normal);
        pos.x = round(pos.x - 0.5) + 0.5;
        pos.y = round(pos.y - 0.5) + 0.5;
        pos.z = round(pos.z - 0.5) + 0.5;
    }
    if (state == STATE_IDLE) {
        goxel->tool_t = 0;
        if (snaped) state = STATE_SNAPED;
    }
    if (state == STATE_SNAPED) {
        if (goxel->tool_t == 0) {
            goxel->tool_t = 1;
            mesh_set(&goxel->tool_origin_mesh, mesh);
        }
        if (!snaped) return STATE_CANCEL;
        goxel_set_help_text(goxel, "Click and drag to draw.");
        goxel->tool_start_pos = pos;
        box = get_box(&goxel->tool_start_pos, &pos, &normal, 0,
                      &goxel->plane);
        mesh_set(&mesh, goxel->tool_origin_mesh);
        mesh_op(mesh, &goxel->painter, &box);
        render_box(&goxel->rend, &box, false, &box_color, false);
        if (down) {
            state = STATE_PAINT;
            goxel->painting = true;
        }
    }
    if (state == STATE_PAINT) {
        goxel_set_help_text(goxel, "Drag.");
        box = get_box(&goxel->tool_start_pos, &pos, &normal, 0, &goxel->plane);
        render_box(&goxel->rend, &box, false, &box_color, false);
        mesh_set(&mesh, goxel->tool_origin_mesh);
        mesh_op(mesh, &goxel->painter, &box);
        goxel_update_meshes(goxel, false);
        if (up) {
            state = STATE_PAINT2;
            goxel->tool_plane = plane_from_normal(pos, goxel->plane.u);
        }
    }
    if (state == STATE_PAINT2) {
        goxel_set_help_text(goxel, "Adjust height.");
        render_plane(&goxel->rend, &goxel->tool_plane, &goxel->grid_color);
        pos = vec3_add(goxel->tool_plane.p,
                    vec3_project(vec3_sub(pos, goxel->tool_plane.p),
                                 goxel->plane.n));
        box = get_box(&goxel->tool_start_pos, &pos, &normal, 0,
                      &goxel->plane);
        render_box(&goxel->rend, &box, false, &box_color, false);
        mesh_set(&mesh, goxel->tool_origin_mesh);
        mesh_op(mesh, &goxel->painter, &box);
        goxel_update_meshes(goxel, false);
        if (down) {
            mesh_set(&mesh, goxel->tool_origin_mesh);
            mesh_op(mesh, &goxel->painter, &box);
            goxel_update_meshes(goxel, true);
            goxel->painting = false;
            image_history_push(goxel->image);
            return STATE_WAIT_UP;
        }
    }
    if (state == STATE_WAIT_UP) {
        goxel->tool_plane = plane_null;
        if (up) state = STATE_IDLE;
    }
    return state;
}
Exemplo n.º 6
0
static int tool_brush_iter(goxel_t *goxel, const inputs_t *inputs, int state,
                           const vec2_t *view_size, bool inside)
{
    const bool down = inputs->mouse_down[0];
    const bool pressed = down && !goxel->painting;
    const bool released = !down && goxel->painting;
    int snaped = 0;
    vec3_t pos, normal;
    box_t box;
    painter_t painter2;
    mesh_t *mesh = goxel->image->active_layer->mesh;

    if (inside)
        snaped = goxel_unproject(goxel, view_size, &inputs->mouse_pos,
                                 &pos, &normal);
    goxel_set_help_text(goxel, "Brush: use shift to draw lines, "
                               "ctrl to pick color");
    if (snaped) {
        if (    snaped == SNAP_MESH && goxel->painter.op == OP_ADD &&
                !goxel->snap_offset)
            vec3_iadd(&pos, normal);
        if (goxel->tool == TOOL_BRUSH && goxel->snap_offset)
            vec3_iaddk(&pos, normal, goxel->snap_offset * goxel->tool_radius);
        pos.x = round(pos.x - 0.5) + 0.5;
        pos.y = round(pos.y - 0.5) + 0.5;
        pos.z = round(pos.z - 0.5) + 0.5;
    }
    if (state == STATE_IDLE) {
        goxel->tool_t = 0;
        if (snaped) state = STATE_SNAPED;
    }
    if (state == STATE_SNAPED) {
        if (goxel->tool_t == 0) {
            goxel->tool_t = 1;
            mesh_set(&goxel->tool_origin_mesh, mesh);
            if (!inputs->keys[KEY_SHIFT])
                mesh_set(&goxel->pick_mesh, goxel->layers_mesh);
            goxel->tool_last_op.op = 0; // Discard last op.
        }
        if (!snaped) return STATE_CANCEL;
        if (inputs->keys[KEY_SHIFT])
            render_line(&goxel->rend, &goxel->tool_start_pos, &pos, NULL);
        if (check_can_skip(goxel, pos, down, goxel->painter.op))
            return state;
        box = get_box(&pos, NULL, &normal, goxel->tool_radius, NULL);

        mesh_set(&mesh, goxel->tool_origin_mesh);
        mesh_op(mesh, &goxel->painter, &box);
        goxel_update_meshes(goxel, false);

        if (inputs->keys[KEY_SHIFT]) {
            render_line(&goxel->rend, &goxel->tool_start_pos, &pos, NULL);
            if (pressed) {
                painter2 = goxel->painter;
                painter2.shape = &shape_cylinder;
                box = get_box(&goxel->tool_start_pos, &pos, &normal,
                              goxel->tool_radius, NULL);
                mesh_op(mesh, &painter2, &box);
                goxel_update_meshes(goxel, false);
                goxel->tool_start_pos = pos;
                mesh_set(&goxel->tool_origin_mesh, mesh);
            }
        }
        if (pressed) {
            mesh_set(&mesh, goxel->tool_origin_mesh);
            state = STATE_PAINT;
            goxel->tool_last_op.op = 0;
            goxel->painting = true;
        }
    }
    if (state == STATE_PAINT) {
        if (check_can_skip(goxel, pos, down, goxel->painter.op))
            return state;
        if (released) {
            image_history_push(goxel->image);
            goxel->painting = false;
            goxel->last_pos = pos;
            if (inputs->keys[KEY_SHIFT])
                return STATE_WAIT_KEY_UP;
            mesh_set(&goxel->pick_mesh, goxel->layers_mesh);
            return STATE_IDLE;
        }
        box = get_box(&pos, NULL, &normal, goxel->tool_radius, NULL);
        mesh_op(mesh, &goxel->painter, &box);
        goxel_update_meshes(goxel, false);
        goxel->tool_start_pos = pos;
    }
    if (state == STATE_WAIT_KEY_UP) {
        goxel->tool_t = 0;
        if (!inputs->keys[KEY_SHIFT]) state = STATE_IDLE;
        if (snaped) state = STATE_SNAPED;
    }
    return state;
}