static int tool_set_plane_iter(goxel_t *goxel, const inputs_t *inputs, int state, const vec2_t *view_size, bool inside) { bool snaped; vec3_t pos, normal; mesh_t *mesh = goxel->layers_mesh; const bool pressed = inputs->mouse_down[0]; goxel_set_help_text(goxel, "Click on the mesh to set plane."); snaped = inside && goxel_unproject_on_mesh(goxel, view_size, &inputs->mouse_pos, mesh, &pos, &normal); if (snaped && pressed) { vec3_iadd(&pos, normal); goxel->plane = plane_from_normal(pos, normal); } return 0; }
box_t block_get_box(const block_t *block, bool exact) { box_t ret; int x, y, z; int xmin = N, xmax = 0, ymin = N, ymax = 0, zmin = N, zmax = 0; if (!exact) return bbox_from_extents(block->pos, N / 2, N / 2, N / 2); BLOCK_ITER(x, y, z) { if (BLOCK_AT(block, x, y, z).a) { xmin = min(xmin, x); ymin = min(ymin, y); zmin = min(zmin, z); xmax = max(xmax, x); ymax = max(ymax, y); zmax = max(zmax, z); } } if (xmin > xmax) return box_null(); ret = bbox_from_points(vec3(xmin - 0.5, ymin - 0.5, zmin - 0.5), vec3(xmax + 0.5, ymax + 0.5, zmax + 0.5)); vec3_iadd(&ret.p, block->pos); vec3_isub(&ret.p, vec3(N / 2 - 0.5, N / 2 - 0.5, N / 2 - 0.5)); return ret; }
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; }
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; }