bool Player::unmount() { if (!mount) { return true; } printf_fvec3(get_world_pos()); printf("\n"); mount->remove_entity(this); // try setting pos to about 2 blocks above current position set_pos(fvec3(pos.x, pos.y + 2.0f, pos.z)); if (get_world()->will_collide_with_anything(this)) { // return false if we can't unmount...because not room for player set_pos(fvec3(pos.x, pos.y - 2.0f, pos.z)); mount->add_entity(this); return false; } velocity = mount->velocity; mount = 0; can_collide = true; printf_fvec3(get_world_pos()); get_world()->add_entity(this); toggle_mount(false); return true; }
void Player::set_mount(SuperObject* m, fvec3 rwc) { if (!m) { unmount(); return; } if (mount) { // unmount first mount->remove_entity(this); } printf_fvec3(get_world_pos()); printf("\n"); mount = m; // no moving around while mounted! velocity = fvec3(0, 0, 0); // TODO this is hack fix this->set_pos(rwc - get_center_offset()); mount->add_entity(this); //m->transform_into_my_coordinates_smooth(&offset_to_mount, pos.x, pos.y, pos.z); //set_pos(pos - this->center_pos); can_collide = false; printf_fvec3(get_world_pos()); toggle_mount(true); }
void CurveEditor::add_point(Vector2 pos) { ERR_FAIL_COND(_curve_ref.is_null()); UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo(); ur.create_action(TTR("Remove Curve Point")); Vector2 point_pos = get_world_pos(pos); if (point_pos.y < 0.0) point_pos.y = 0.0; else if (point_pos.y > 1.0) point_pos.y = 1.0; // Small trick to get the point index to feed the undo method int i = _curve_ref->add_point(point_pos); _curve_ref->remove_point(i); ur.add_do_method(*_curve_ref, "add_point", point_pos); ur.add_undo_method(*_curve_ref, "remove_point", i); ur.commit_action(); }
void Entity::set_parent(SuperObject* parent) { // transform entity rotation/pos into this object's frame // after transformation, the rwc center position should be the same fvec3 global_center = get_world_pos(); Rotation global_rotation = get_world_rotation(); fvec3 oac; if (parent) { parent->transform_into_my_coordinates(&oac, global_center.x, global_center.y, global_center.z); } else { oac = global_center; } this->parent = parent; set_pos(oac - get_center_offset()); Rotation aligned_rot; if (parent) { parent->transform_into_my_rotation(&aligned_rot, global_rotation); } else { aligned_rot = global_rotation; } set_angle(aligned_rot); }
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); } }
void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb_ref = p_event; if (mb_ref.is_valid()) { const InputEventMouseButton &mb = **mb_ref; if (mb.is_pressed() && !_dragging) { Vector2 mpos = mb.get_position(); _selected_tangent = get_tangent_at(mpos); if (_selected_tangent == TANGENT_NONE) set_selected_point(get_point_at(mpos)); switch (mb.get_button_index()) { case BUTTON_RIGHT: _context_click_pos = mpos; open_context_menu(get_global_transform().xform(mpos)); break; case BUTTON_MIDDLE: remove_point(_hover_point); break; case BUTTON_LEFT: _dragging = true; break; } } if (!mb.is_pressed() && _dragging && mb.get_button_index() == BUTTON_LEFT) { _dragging = false; if (_has_undo_data) { UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo(); ur.create_action(_selected_tangent == TANGENT_NONE ? TTR("Modify Curve Point") : TTR("Modify Curve Tangent")); ur.add_do_method(*_curve_ref, "_set_data", _curve_ref->get_data()); ur.add_undo_method(*_curve_ref, "_set_data", _undo_data); // Note: this will trigger one more "changed" signal even if nothing changes, // but it's ok since it would have fired every frame during the drag anyways ur.commit_action(); _has_undo_data = false; } } } Ref<InputEventMouseMotion> mm_ref = p_event; if (mm_ref.is_valid()) { const InputEventMouseMotion &mm = **mm_ref; Vector2 mpos = mm.get_position(); if (_dragging && _curve_ref.is_valid()) { Curve &curve = **_curve_ref; if (_selected_point != -1) { if (!_has_undo_data) { // Save full curve state before dragging points, // because this operation can modify their order _undo_data = curve.get_data(); _has_undo_data = true; } if (_selected_tangent == TANGENT_NONE) { // Drag point Vector2 point_pos = get_world_pos(mpos); int i = curve.set_point_offset(_selected_point, point_pos.x); // The index may change if the point is dragged across another one set_hover_point_index(i); set_selected_point(i); // This is to prevent the user from losing a point out of view. if (point_pos.y < curve.get_min_value()) point_pos.y = curve.get_min_value(); else if (point_pos.y > curve.get_max_value()) point_pos.y = curve.get_max_value(); curve.set_point_value(_selected_point, point_pos.y); } else { // Drag tangent Vector2 point_pos = curve.get_point_position(_selected_point); Vector2 control_pos = get_world_pos(mpos); Vector2 dir = (control_pos - point_pos).normalized(); real_t tangent; if (Math::abs(dir.x) > CMP_EPSILON) tangent = dir.y / dir.x; else tangent = 9999 * (dir.y >= 0 ? 1 : -1); bool link = !Input::get_singleton()->is_key_pressed(KEY_SHIFT); if (_selected_tangent == TANGENT_LEFT) { curve.set_point_left_tangent(_selected_point, tangent); // Note: if a tangent is set to linear, it shouldn't be linked to the other if (link && _selected_point != curve.get_point_count() - 1 && !curve.get_point_right_mode(_selected_point) != Curve::TANGENT_FREE) curve.set_point_right_tangent(_selected_point, tangent); } else { curve.set_point_right_tangent(_selected_point, tangent); if (link && _selected_point != 0 && !curve.get_point_left_mode(_selected_point) != Curve::TANGENT_FREE) curve.set_point_left_tangent(_selected_point, tangent); } } } } else { set_hover_point_index(get_point_at(mpos)); } } Ref<InputEventKey> key_ref = p_event; if (key_ref.is_valid()) { const InputEventKey &key = **key_ref; if (key.is_pressed() && _selected_point != -1) { if (key.get_scancode() == KEY_DELETE) remove_point(_selected_point); } } }