86 lines
2.9 KiB
C++
86 lines
2.9 KiB
C++
#include "player_camera.h"
|
|
#include "core/config/engine.h"
|
|
#include "core/math/math_funcs.h"
|
|
#include "scene/main/node.h"
|
|
#include "scene/main/scene_tree.h"
|
|
|
|
PlayerCamera *PlayerCamera::instance{ nullptr };
|
|
|
|
void PlayerCamera::_bind_methods() {
|
|
ClassDB::bind_static_method(get_class_static(), "get_instance", &self_type::get_instance);
|
|
ClassDB::bind_method(D_METHOD("impact_effect", "color", "freeze_time", "zoom", "shake_intensity"), &self_type::impact_effect);
|
|
BIND_PROPERTY(Variant::FLOAT, max_shake);
|
|
}
|
|
|
|
void PlayerCamera::end_effect() {
|
|
--this->active_effects;
|
|
if (this->active_effects > 0) {
|
|
this->active_shake -= this->active_shake / float(this->active_effects);
|
|
this->active_shake = this->active_shake > 0.f ? this->active_shake : 0.f;
|
|
return;
|
|
}
|
|
if (this->active_environment.is_valid()) {
|
|
this->active_environment->set_ambient_light_color(this->ambient_light_color);
|
|
}
|
|
get_tree()->set_pause(false);
|
|
set_process(false);
|
|
set_global_position(get_global_position() - this->shake_offset);
|
|
this->shake_offset = {};
|
|
this->active_environment->set_ambient_light_energy(1.f);
|
|
}
|
|
|
|
void PlayerCamera::process(double delta) {
|
|
this->shake_interval -= delta / Engine::get_singleton()->get_time_scale();
|
|
if (this->shake_interval < 0.0) {
|
|
this->shake_interval = 0.03;
|
|
Vector3 const new_location{ get_position() - this->shake_offset };
|
|
Vector3 const new_offset{ Vector3{ 0, this->active_shake < 0.5f ? this->active_shake : 0.5f, 0 }.rotated({ 0, 0, 1 }, Math::random(0.0, Math::PI)) };
|
|
Basis const basis{ get_basis() };
|
|
set_position(new_location + (this->shake_offset = basis.get_column(0) * new_offset.x + basis.get_column(1) * new_offset.y));
|
|
}
|
|
}
|
|
|
|
void PlayerCamera::_notification(int what) {
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
return;
|
|
}
|
|
switch (what) {
|
|
default:
|
|
return;
|
|
case NOTIFICATION_ENTER_TREE:
|
|
set_process_mode(ProcessMode::PROCESS_MODE_ALWAYS);
|
|
instance = this;
|
|
return;
|
|
case NOTIFICATION_READY:
|
|
this->active_environment = get_world_3d()->get_environment();
|
|
if (this->active_environment.is_valid()) {
|
|
this->ambient_light_color = this->active_environment->get_ambient_light_color();
|
|
}
|
|
return;
|
|
case NOTIFICATION_PROCESS:
|
|
process(get_process_delta_time());
|
|
return;
|
|
case NOTIFICATION_EXIT_TREE:
|
|
if (instance == this) {
|
|
instance = nullptr;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
PlayerCamera *PlayerCamera::get_instance() {
|
|
return instance;
|
|
}
|
|
|
|
Ref<SceneTreeTimer> PlayerCamera::impact_effect(Color color, float freeze_time, float zoom, float shake_intensity) {
|
|
this->active_environment->set_ambient_light_color(color);
|
|
this->active_environment->set_ambient_light_energy(1.f);
|
|
Ref<SceneTreeTimer> timer{ get_tree()->create_timer(freeze_time, true, false, true) };
|
|
timer->set_process_always(true);
|
|
timer->connect("timeout", callable_mp(this, &self_type::end_effect));
|
|
this->active_shake += shake_intensity;
|
|
++this->active_effects;
|
|
get_tree()->set_pause(true);
|
|
set_process(true);
|
|
return timer;
|
|
}
|