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); }
// XXX: this is very close to tool_cube_iter. static int tool_selection_iter(goxel_t *goxel, const inputs_t *inputs, int state, const vec2_t *view_size, bool inside) { extern const mat4_t FACES_MATS[6]; const bool down = inputs->mouse_down[0]; const bool up = !down; int snaped = 0; int face = -1; vec3_t pos, normal; plane_t face_plane; box_t box; uvec4b_t box_color = HEXCOLOR(0xffff00ff); // See if we can snap on a selection face. if (inside && !box_is_null(goxel->selection) && IS_IN(state, STATE_IDLE, STATE_SNAPED, STATE_SNAPED_FACE)) { goxel->tool_snape_face = -1; if (goxel_unproject_on_box(goxel, view_size, &inputs->mouse_pos, &goxel->selection, &pos, &normal, &face)) { goxel->tool_snape_face = face; state = STATE_SNAPED_FACE; } } if (!box_is_null(goxel->selection) && goxel->tool_snape_face != -1) face_plane.mat = mat4_mul(goxel->selection.mat, FACES_MATS[goxel->tool_snape_face]); if (inside && face == -1) snaped = goxel_unproject(goxel, view_size, &inputs->mouse_pos, &pos, &normal); if (snaped) { 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; goxel->tool_snape_face = -1; if (snaped) state = STATE_SNAPED; } if (state == STATE_SNAPED) { if (!snaped) return STATE_CANCEL; goxel_set_help_text(goxel, "Click and drag to set selection."); goxel->tool_start_pos = pos; box = get_box(&goxel->tool_start_pos, &pos, &normal, 0, &goxel->plane); 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."); goxel->selection = get_box(&goxel->tool_start_pos, &pos, &normal, 0, &goxel->plane); 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)); goxel->selection = get_box(&goxel->tool_start_pos, &pos, &normal, 0, &goxel->plane); if (down) { goxel->painting = false; return STATE_WAIT_UP; } } if (state == STATE_WAIT_UP) { goxel->tool_plane = plane_null; goxel->selection = box_get_bbox(goxel->selection); return up ? STATE_IDLE : STATE_WAIT_UP; } if (IS_IN(state, STATE_SNAPED_FACE, STATE_MOVE_FACE)) goxel_set_help_text(goxel, "Drag to move face"); if (state == STATE_SNAPED_FACE) { if (face == -1) return STATE_IDLE; render_img(&goxel->rend, NULL, &face_plane.mat); if (down) { state = STATE_MOVE_FACE; goxel->tool_plane = plane(pos, normal, vec3_normalized(face_plane.u)); } } if (state == STATE_MOVE_FACE) { if (up) return STATE_IDLE; goxel_unproject_on_plane(goxel, view_size, &inputs->mouse_pos, &goxel->tool_plane, &pos, &normal); pos = vec3_add(goxel->tool_plane.p, vec3_project(vec3_sub(pos, goxel->tool_plane.p), vec3_normalized(face_plane.n))); pos.x = round(pos.x); pos.y = round(pos.y); pos.z = round(pos.z); goxel->selection = box_move_face(goxel->selection, goxel->tool_snape_face, pos); } return state; }