// mouse button handler static void event_button(struct FTR *f, int k, int m, int x, int y) { struct viewer_state *e = f->userdata; // begin dragging a control point in the WINDOW DOMAIN if (k == FTR_BUTTON_LEFT) { int p = hit_point(e, x, y); if (p >= 0) { e->dragging_point = true; e->dragged_point = p; } } // end dragging a control point in the WINDOW DOMAIN if (e->dragging_point && k == -FTR_BUTTON_LEFT) { int p = e->dragged_point; e->dragging_point = false; double X[2] = {x, y}; map_window_to_view(e, e->c[p], X); } // begin dragging a control point in the IMAGE DOMAIN if (k == FTR_BUTTON_RIGHT) { int p = hit_point(e, x, y); if (p >= 0) { e->dragging_ipoint = true; e->dragged_point = p; } } // end dragging a control point in the IMAGE DOMAIN if (e->dragging_ipoint && k == -FTR_BUTTON_RIGHT) { int p = e->dragged_point; e->dragging_ipoint = false; double P[2], Q[2] = {x, y}; map_window_to_image(e, P, Q); e->p[p][0] = P[0]; e->p[p][1] = P[1]; map_window_to_view(e, e->c[p], Q); } // zoom in/out if (k == FTR_BUTTON_DOWN) change_view_scale(e, x, y, ZOOM_FACTOR); if (k == FTR_BUTTON_UP) change_view_scale(e, x, y, 1.0/ZOOM_FACTOR); paint_state(f); }
CL_SpanLayout::HitTestResult CL_SpanLayout_Impl::hit_test(CL_GraphicContext &gc, const CL_Point &pos) { CL_SpanLayout::HitTestResult result; if(lines.empty()) { result.type = CL_SpanLayout::HitTestResult::no_objects_available; return result; } int x = position.x; int y = position.y; // Check if we are outside to the top if(pos.y < y) { result.type = CL_SpanLayout::HitTestResult::outside_top; result.object_id = lines[0].segments[0].id; result.offset = 0; return result; } for (std::vector<Line>::size_type line_index = 0; line_index < lines.size(); line_index++) { Line &line = lines[line_index]; // Check if we found current line if(pos.y >= y && pos.y <= y + line.height) { for (std::vector<LineSegment>::size_type segment_index = 0; segment_index < line.segments.size(); segment_index++) { LineSegment &segment = line.segments[segment_index]; // Check if we are outside to the left if(segment_index == 0 && pos.x < x) { result.type = CL_SpanLayout::HitTestResult::outside_left; result.object_id = segment.id; result.offset = segment.start; return result; } // Check if we are inside a segment if(pos.x >= x + segment.x_position && pos.x <= x + segment.x_position + segment.width) { CL_StringRef segment_text = text.substr(segment.start, segment.end-segment.start); CL_Point hit_point(pos.x - x - segment.x_position, 0); int offset = segment.start + segment.font.get_character_index(gc, segment_text, hit_point); result.type = CL_SpanLayout::HitTestResult::inside; result.object_id = segment.id; result.offset = offset; return result; } // Check if we are outside to the right if(segment_index == line.segments.size() - 1 && pos.x > x + segment.x_position + segment.width) { result.type = CL_SpanLayout::HitTestResult::outside_right; result.object_id = segment.id; result.offset = segment.end; return result; } } } y += line.height; } // We are outside to the bottom const Line &last_line = lines[lines.size() - 1]; const LineSegment &last_segment = last_line.segments[last_line.segments.size() - 1]; result.type = CL_SpanLayout::HitTestResult::outside_bottom; result.object_id = last_segment.id; result.offset = last_segment.end; return result; }
void determine_hilight() { float min_dist = 1024; hl_wrect = NULL; hl_fpoly = NULL; hl_thing = NULL; // List of sectors the camera view ray passes through vector<int> sectors; // Check Things if (render_things > 0) { for (int t = 0; t < map.n_things; t++) { int f_height = 0; int height = things_3d[t]->sprite->height; if (things_3d[t]->parent_sector == -1) continue; if (sector_info[things_3d[t]->parent_sector].visible) { if (map.things[t]->ttype->hanging) f_height = map.sectors[things_3d[t]->parent_sector]->c_height - height; else f_height = map.sectors[things_3d[t]->parent_sector]->f_height; } if (map.things[t]->z != 0 && map.hexen) f_height += map.things[t]->z; int r = things_3d[t]->sprite->width / 2; if (map.things[t]->ttype->radius == -1) { r = 4; height = 8; f_height -= 4; } float x1 = (map.things[t]->x - camera.strafe.x * r) * SCALE_3D; float y1 = (map.things[t]->y - camera.strafe.y * r) * SCALE_3D; float x2 = (map.things[t]->x + camera.strafe.x * r) * SCALE_3D; float y2 = (map.things[t]->y + camera.strafe.y * r) * SCALE_3D; float dist = line_intersect(camera.position, camera.view, x1, y1, x2, y2); if (dist != -1 && dist < min_dist) { point3_t direction = camera.view - camera.position; point3_t hit_point(camera.position.x + (direction.x * dist), camera.position.y + (direction.y * dist), camera.position.z + (direction.z * dist)); if (hit_point.z >= f_height * SCALE_3D && hit_point.z <= (f_height + height) * SCALE_3D) { min_dist = dist; hl_thing = things_3d[t]; } } } } // Check Lines for (int a = 0; a < map.n_lines; a++) { if (!lines_3d[a].visible) continue; rect_t lrect = map.l_getrect(a); float dist = line_intersect(camera.position, camera.view, (float)lrect.x1() * SCALE_3D, (float)lrect.y1() * SCALE_3D, (float)lrect.x2() * SCALE_3D, (float)lrect.y2() * SCALE_3D); if (dist != -1 && dist < min_dist) { point3_t direction = camera.view - camera.position; point3_t hit_point(camera.position.x + (direction.x * dist), camera.position.y + (direction.y * dist), camera.position.z + (direction.z * dist)); sectors.push_back(map.l_getsector1(a)); sectors.push_back(map.l_getsector2(a)); // For all wallrects on the line for (int r = 0; r < lines_3d[a].rects.size(); r++) { if (!determine_line_side(lines_3d[a].rects[r]->verts[0].x, lines_3d[a].rects[r]->verts[0].y, lines_3d[a].rects[r]->verts[1].x, lines_3d[a].rects[r]->verts[1].y, camera.position.x, camera.position.y)) continue; float up = get_slope_height_point(lines_3d[a].rects[r]->verts[0], lines_3d[a].rects[r]->verts[1], hit_point); float lo = get_slope_height_point(lines_3d[a].rects[r]->verts[3], lines_3d[a].rects[r]->verts[2], hit_point); if (up >= hit_point.z && lo <= hit_point.z) { hl_thing = NULL; hl_wrect = lines_3d[a].rects[r]; min_dist = dist; break; } } } } // Check sectors for (int a = 0; a < ssects_3d.size(); a++) { if (!ssects_3d[a].visible) continue; point3_t direction = camera.view - camera.position; for (int b = 0; b < ssects_3d[a].flats.size(); b++) { // Get flat plane flatpoly_t *poly = ssects_3d[a].flats[b]; if (!(vector_exists(sectors, poly->parent_sector))) continue; plane_t plane; if (poly->part == PART_CEIL) plane = sector_info[poly->parent_sector].c_plane; else plane = sector_info[poly->parent_sector].f_plane; // Check side of plane float h = plane_height(plane, camera.position.x, camera.position.y); if (poly->part == PART_CEIL) { if (camera.position.z > h) continue; } if (poly->part == PART_FLOOR) { if (camera.position.z < h) continue; } float dist = dist_ray_plane(camera.position, direction, plane); if (dist <= min_dist && dist > 0.0f) { point3_t intersection(camera.position.x + (direction.x * dist), camera.position.y + (direction.y * dist), camera.position.z + (direction.z * dist)); bool in = true; DWORD start = gl_ssects[a].startseg; DWORD end = start + gl_ssects[a].n_segs; for (DWORD seg = start; seg < end; seg++) { if (!determine_seg_side(seg, intersection.x, intersection.y)) { in = false; break; } } if (in) { hl_wrect = NULL; hl_thing = NULL; hl_fpoly = poly; min_dist = dist; } } } } }