Vector2 CurveEditor::get_tangent_view_pos(int i, TangentIndex tangent) const { Vector2 dir; if (tangent == TANGENT_LEFT) dir = -Vector2(1, _curve_ref->get_point_left_tangent(i)); else dir = Vector2(1, _curve_ref->get_point_right_tangent(i)); Vector2 point_pos = get_view_pos(_curve_ref->get_point_position(i)); Vector2 control_pos = get_view_pos(_curve_ref->get_point_position(i) + dir); return point_pos + _tangents_length * (control_pos - point_pos).normalized(); }
// ------------------------------------------------------------------------ // window to display an adventure map // ------------------------------------------------------------------------ bool t_adventure_map_window::is_visible( t_screen_point const& point ) const { t_screen_point view_size = get_view_size(); t_screen_point view_pos = get_view_pos(); t_screen_rect rect( view_pos, view_size ); rect.top += 64 * 4; rect.left += 64 * 4; rect.right -= 64 * 4; rect.bottom -= 64 * 4; if (rect.height() < 64) { int center = (rect.top + rect.bottom) / 2; rect.top = center - 32; rect.bottom = center + 32; } if (rect.width() < 64) { int center = (rect.left + rect.right) / 2; rect.left = center - 32; rect.right = center + 32; } return is_point_in_rect( point, rect ); }
// ------------------------------------------------------------------------ // window to display an adventure map // ------------------------------------------------------------------------ void t_adventure_map_window::drag( t_screen_point point ) { t_screen_point delta = m_drag_start - point; t_screen_point new_point = get_view_pos() + delta; m_drag_start = point; move_view( new_point ); }
// ------------------------------------------------------------------------ // window to display an adventure map // ------------------------------------------------------------------------ void t_adventure_map_window::on_size_change( t_screen_rect const& rect ) { bool size_changed = (m_back_buffer == 0); if (get_screen_rect().height() != rect.height() || get_screen_rect().width() != rect.width()) size_changed = true; if (size_changed) { t_screen_point view_pos = get_view_pos(); t_map_renderer::move_view( view_pos, t_screen_point( rect.width(), rect.height() ) ); get_frame()->resize_view(rect); } }
int CurveEditor::get_point_at(Vector2 pos) const { if (_curve_ref.is_null()) return -1; const Curve &curve = **_curve_ref; const float r = _hover_radius * _hover_radius; for (int i = 0; i < curve.get_point_count(); ++i) { Vector2 p = get_view_pos(curve.get_point_position(i)); if (p.distance_squared_to(pos) <= r) { return i; } } return -1; }
// ------------------------------------------------------------------------ // window to display an adventure map // determine if a click is appropriate for the top tile of a bridge span // ------------------------------------------------------------------------ bool t_adventure_map_window::get_bridge_point( t_screen_point const& screen_point, t_adv_map_point& map_point ) const { t_adventure_map_object_id id = adv_object_hit_test( screen_point ); if (id == t_adventure_map::k_invalid_object_id ) return false; t_adventure_object* bridge; bridge = &m_map->get_adv_object( id ); t_adv_map_point point = bridge->get_position(); if (!bridge->is_bridge() && !point.on_bridge ) return false; t_footprint const& footprint = bridge->get_footprint(); t_map_point_2d footprint_size = footprint.get_size(); map_point = point; map_point.on_bridge = true; // handle bridge pieces that are 2x1 if (footprint_size.column > 1 || footprint_size.row > 1) { t_adv_map_point division_point; int division_screen_point; division_point = map_point; if (footprint_size.column > 1) ++division_point.column; else ++division_point.row; division_screen_point = m_map->get_screen_point( division_point ).x; division_screen_point -= get_view_pos().x; if (footprint_size.column > 1) { if (screen_point.x >= division_screen_point) map_point = division_point; } else if (screen_point.x < division_screen_point) { map_point = division_point; } } return true; }
void CurveEditor::_draw() { if (_curve_ref.is_null()) return; Curve &curve = **_curve_ref; update_view_transform(); // Background Vector2 view_size = get_rect().size; draw_style_box(get_stylebox("bg", "Tree"), Rect2(Point2(), view_size)); // Grid draw_set_transform_matrix(_world_to_view); Vector2 min_edge = get_world_pos(Vector2(0, view_size.y)); Vector2 max_edge = get_world_pos(Vector2(view_size.x, 0)); const Color grid_color0 = get_color("grid_major_color", "Editor"); const Color grid_color1 = get_color("grid_minor_color", "Editor"); draw_line(Vector2(min_edge.x, curve.get_min_value()), Vector2(max_edge.x, curve.get_min_value()), grid_color0); draw_line(Vector2(max_edge.x, curve.get_max_value()), Vector2(min_edge.x, curve.get_max_value()), grid_color0); draw_line(Vector2(0, min_edge.y), Vector2(0, max_edge.y), grid_color0); draw_line(Vector2(1, max_edge.y), Vector2(1, min_edge.y), grid_color0); float curve_height = (curve.get_max_value() - curve.get_min_value()); const Vector2 grid_step(0.25, 0.5 * curve_height); for (real_t x = 0; x < 1.0; x += grid_step.x) { draw_line(Vector2(x, min_edge.y), Vector2(x, max_edge.y), grid_color1); } for (real_t y = curve.get_min_value(); y < curve.get_max_value(); y += grid_step.y) { draw_line(Vector2(min_edge.x, y), Vector2(max_edge.x, y), grid_color1); } // Markings draw_set_transform_matrix(Transform2D()); Ref<Font> font = get_font("font", "Label"); float font_height = font->get_height(); Color text_color = get_color("font_color", "Editor"); { // X axis float y = curve.get_min_value(); Vector2 off(0, font_height - 1); draw_string(font, get_view_pos(Vector2(0, y)) + off, "0.0", text_color); draw_string(font, get_view_pos(Vector2(0.25, y)) + off, "0.25", text_color); draw_string(font, get_view_pos(Vector2(0.5, y)) + off, "0.5", text_color); draw_string(font, get_view_pos(Vector2(0.75, y)) + off, "0.75", text_color); draw_string(font, get_view_pos(Vector2(1, y)) + off, "1.0", text_color); } { // Y axis float m0 = curve.get_min_value(); float m1 = 0.5 * (curve.get_min_value() + curve.get_max_value()); float m2 = curve.get_max_value(); Vector2 off(1, -1); draw_string(font, get_view_pos(Vector2(0, m0)) + off, String::num(m0, 2), text_color); draw_string(font, get_view_pos(Vector2(0, m1)) + off, String::num(m1, 2), text_color); draw_string(font, get_view_pos(Vector2(0, m2)) + off, String::num(m2, 3), text_color); } // Draw tangents for current point if (_selected_point >= 0) { const Color tangent_color = get_color("accent_color", "Editor"); int i = _selected_point; Vector2 pos = curve.get_point_position(i); if (i != 0) { Vector2 control_pos = get_tangent_view_pos(i, TANGENT_LEFT); draw_line(get_view_pos(pos), control_pos, tangent_color); draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(2), tangent_color); } if (i != curve.get_point_count() - 1) { Vector2 control_pos = get_tangent_view_pos(i, TANGENT_RIGHT); draw_line(get_view_pos(pos), control_pos, tangent_color); draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(2), tangent_color); } } // Draw lines draw_set_transform_matrix(_world_to_view); const Color line_color = get_color("highlight_color", "Editor"); const Color edge_line_color = get_color("font_color", "Editor"); CanvasItemPlotCurve plot_func(*this, line_color, edge_line_color); plot_curve_accurate(curve, 4.f / view_size.x, plot_func); // Draw points draw_set_transform_matrix(Transform2D()); const Color point_color = get_color("font_color", "Editor"); const Color selected_point_color = get_color("accent_color", "Editor"); for (int i = 0; i < curve.get_point_count(); ++i) { Vector2 pos = curve.get_point_position(i); draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(3), i == _selected_point ? selected_point_color : point_color); // TODO Circles are prettier. Needs a fix! Or a texture //draw_circle(pos, 2, point_color); } // Hover if (_hover_point != -1) { const Color hover_color = line_color; Vector2 pos = curve.get_point_position(_hover_point); stroke_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(_hover_radius), hover_color); } // Help text if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) { text_color.a *= 0.4; draw_string(font, Vector2(50, font_height), TTR("Hold Shift to edit tangents individually"), text_color); } }