Repository: godotengine/godot
File: editor/plugins/node_3d_editor_plugin.cpp (C++)

Code before:
}

void Node3DEditorViewport::_update_freelook(real_t delta) {
	if (!is_freelook_active()) {
		return;
	}

	const FreelookNavigationScheme navigation_scheme = (FreelookNavigationScheme)EDITOR_GET("editors/3d/freelook/freelook_navigation_scheme").operator int();

	Vector3 forward;
	if (navigation_scheme == FREELOOK_FULLY_AXIS_LOCKED) {
		// Forward/backward keys will always go straight forward/backward, never moving on the Y axis.
		forward = Vector3(0, 0, -1).rotated(Vector3(0, 1, 0), camera->get_rotation().y);
	} else {
		// Forward/backward keys will be relative to the camera pitch.
		forward = camera->get_transform().basis.xform(Vector3(0, 0, -1));
	}

	const Vector3 right = camera->get_transform().basis.xform(Vector3(1, 0, 0));

	Vector3 up;
	if (navigation_scheme == FREELOOK_PARTIALLY_AXIS_LOCKED || navigation_scheme == FREELOOK_FULLY_AXIS_LOCKED) {
		// Up/down keys will always go up/down regardless of camera pitch.
		up = Vector3(0, 1, 0);
	} else {
		// Up/down keys will be relative to the camera pitch.
		up = camera->get_transform().basis.xform(Vector3(0, 1, 0));
	}

	Vector3 direction;

	// Use actions from the inputmap, as this is the only way to reliably detect input in this method.
	// See #54469 for more discussion and explanation.
	Input *inp = Input::get_singleton();
	if (inp->is_action_pressed("spatial_editor/freelook_left")) {
		direction -= right;
	}
	if (inp->is_action_pressed("spatial_editor/freelook_right")) {
		direction += right;
	}
	if (inp->is_action_pressed("spatial_editor/freelook_forward")) {
		direction += forward;
	}
	if (inp->is_action_pressed("spatial_editor/freelook_backwards")) {
		direction -= forward;
	}
	if (inp->is_action_pressed("spatial_editor/freelook_up")) {
		direction += up;
	}
	if (inp->is_action_pressed("spatial_editor/freelook_down")) {
		direction -= up;

Review comment (bug):
```suggestion
	if (check_shortcut.is_null()) {
		return true;
	}
	return check_shortcut->get_events().is_empty();
```
Since you said it could error, otherwise if it does error it will crash

Code after:
	surface->queue_redraw();
}

void Node3DEditorViewport::scale_freelook_speed(real_t scale) {
	real_t min_speed = MAX(camera->get_near() * 4, ZOOM_FREELOOK_MIN);
	real_t max_speed = MIN(camera->get_far() / 4, ZOOM_FREELOOK_MAX);
	if (unlikely(min_speed > max_speed)) {
		freelook_speed = (min_speed + max_speed) / 2;
	} else {
		freelook_speed = CLAMP(freelook_speed * scale, min_speed, max_speed);
	}

	zoom_indicator_delay = ZOOM_FREELOOK_INDICATOR_DELAY_S;
	surface->queue_redraw();
}

bool Node3DEditorViewport::_is_nav_modifier_pressed(const String &p_name) {
	return _is_shortcut_empty(p_name) || Input::get_singleton()->is_action_pressed(p_name);
}

bool Node3DEditorViewport::_is_shortcut_empty(const String &p_name) {
	Ref<Shortcut> check_shortcut = ED_GET_SHORTCUT(p_name);

	ERR_FAIL_COND_V_MSG(check_shortcut.is_null(), true, "The Shortcut was null, possible name mismatch.");

	return check_shortcut->get_events().is_empty();
}

Point2 Node3DEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const {
	Point2 relative;
	if (bool(EDITOR_GET("editors/3d/navigation/warped_mouse_panning"))) {
		relative = Input::get_singleton()->warp_mouse_motion(p_ev_mouse_motion, surface->get_global_rect());
	} else {
		relative = p_ev_mouse_motion->get_relative();
	}
	return relative;
}

void Node3DEditorViewport::_update_freelook(real_t delta) {
	if (!is_freelook_active()) {
		return;
	}

	const FreelookNavigationScheme navigation_scheme = (FreelookNavigationScheme)EDITOR_GET("editors/3d/freelook/freelook_navigation_scheme").operator int();

	Vector3 forward;
	if (navigation_scheme == FREELOOK_FULLY_AXIS_LOCKED) {
		// Forward/backward keys will always go straight forward/backward, never moving on the Y axis.
		forward = Vector3(0, 0, -1).rotated(Vector3(0, 1, 0), camera->get_rotation().y);
	} else {
		// Forward/backward keys will be relative to the camera pitch.