#include "player_camera.h" #include "macros.h" #include "player_body.h" #include "player_input.h" void PlayerCamera::_bind_methods() { } void PlayerCamera::on_look_input(Vector2 input) { // PI / 2.1 to avoid change to the flattened forward vector static const double LOOK_LIM{ Math::PI / 2.1 }; GETSET(rotation, { rotation.x = CLAMP(rotation.x + input.y, -LOOK_LIM, LOOK_LIM); }); global_rotate(Vector3{ 0.f, 1.f, 0.f }, input.x); lead_weapon(input * this->weapon_lead_speed); } void PlayerCamera::lead_weapon(Vector2 movement) { this->weapon_lead_rotation.x += movement.y; this->weapon_lead_rotation.y += movement.x; this->weapon_lead_rotation = this->weapon_lead_rotation.normalized() * CLAMP(this->weapon_lead_rotation.length(), -this->weapon_lead_limit, this->weapon_lead_limit); for (Variant child : get_children()) { if (Node3D * child3d{ cast_to(child) }) { child3d->set_rotation(this->weapon_lead_rotation); } } } void PlayerCamera::update_fov() { if (!Engine::get_singleton()->is_editor_hint() && is_ready()) { set_fov(CLAMP(this->base_fov * this->fov_factor, 1, 179)); } } void PlayerCamera::update_offset() { bool const is_running{ this->body->get_is_running() && this->body->is_on_floor() }; if (is_running != this->was_running) { this->was_running = is_running; this->run_bob_time = 0.0; } double wave{ Math::sin(this->run_bob_time) }; Vector3 offset{ Vector3{ float(wave), float(Math::abs(wave)), 0 } * this->run_bob_amplitude }; if (!is_running) { this->run_bob_time = MIN(this->run_bob_time, this->run_bob_blend_out); offset = offset.lerp(Vector3(), this->run_bob_time / this->run_bob_blend_out); } GETSET(position, { Basis const basis{ get_basis() }; position = this->home + basis.get_column(0) * offset.x + basis.get_column(1) * offset.y * 5.0; }); for (Variant child : get_children()) { Node3D *child_3d{ cast_to(child) }; GETSETM(child_3d, position, { position = -offset; }); } } void PlayerCamera::ready() { PlayerInput *input{ cast_to(get_node(NodePath("%PlayerInput"))) }; input->connect(PlayerInput::sig_look_input, callable_mp(this, &self_type::on_look_input)); this->base_fov = get_fov(); this->home = get_position(); this->body = cast_to(get_parent()); } void PlayerCamera::process(double delta) { this->run_bob_time += delta * this->run_bob_frequency; update_offset(); this->fov_factor = 1.0; update_fov(); } void PlayerCamera::_notification(int what) { if (Engine::get_singleton()->is_editor_hint()) { return; } switch (what) { default: return; case NOTIFICATION_READY: set_process(true); set_process_priority(-1); ready(); return; case NOTIFICATION_PROCESS: process(get_process_delta_time()); return; } } void PlayerCamera::set_fov_factor(float value) { this->fov_factor *= value; update_fov(); } float PlayerCamera::get_fov_factor() const { return this->fov_factor; } void PlayerCamera::recoil(float r) { GETSET(rotation, { rotation.x = CLAMP(rotation.x + r, -Math::PI / 2.0, Math::PI / 2.0); }); lead_weapon({ 0, 0.02f }); }