some shake
This commit is contained in:
159
addons/shaker/src/Vector3/ShakerReceiver3D.gd
Normal file
159
addons/shaker/src/Vector3/ShakerReceiver3D.gd
Normal file
@@ -0,0 +1,159 @@
|
||||
@icon("res://addons/shaker/assets/ShakerReceiver3D.svg")
|
||||
@tool
|
||||
class_name ShakerReceiver3D
|
||||
extends Node3D
|
||||
|
||||
## Transmits values from ShakerEmitter3D to ShakerComponent3D
|
||||
|
||||
# Fade-in easing
|
||||
@export_exp_easing var enter_fade_in: float = 0.1:
|
||||
set = set_fade_in,
|
||||
get = get_fade_in
|
||||
|
||||
# Fade-out easing
|
||||
@export_exp_easing("attenuation") var exit_fade_out: float = 3.0:
|
||||
set = set_fade_out,
|
||||
get = get_fade_out
|
||||
|
||||
# Private variables
|
||||
var area3d: Area3D
|
||||
var position_offset: Vector3 = Vector3.ZERO
|
||||
var rotation_offset: Vector3 = Vector3.ZERO
|
||||
var scale_offset: Vector3 = Vector3.ZERO
|
||||
var emitter_list: Array[EmitterData]
|
||||
|
||||
# Called when the node enters the scene tree for the first time
|
||||
func _ready() -> void:
|
||||
_setup_area3d()
|
||||
if !Engine.is_editor_hint():
|
||||
add_to_group("ShakerReceiver")
|
||||
_connect_signals()
|
||||
|
||||
# Sets up the Area3D node
|
||||
func _setup_area3d() -> void:
|
||||
for child in get_children():
|
||||
if child is Area3D:
|
||||
area3d = child
|
||||
return
|
||||
|
||||
area3d = Area3D.new()
|
||||
var collision = CollisionShape3D.new()
|
||||
add_child(area3d)
|
||||
area3d.add_child(collision)
|
||||
area3d.set_owner(get_tree().edited_scene_root)
|
||||
collision.set_owner(get_tree().edited_scene_root)
|
||||
area3d.name = "Area3D"
|
||||
collision.name = "CollisionShape3D"
|
||||
|
||||
area3d.collision_layer = 0
|
||||
area3d.collision_mask = 1 << 9
|
||||
|
||||
# Connects signals
|
||||
func _connect_signals() -> void:
|
||||
area3d.area_entered.connect(on_area_entered)
|
||||
area3d.area_exited.connect(on_area_exited)
|
||||
|
||||
# Called every frame
|
||||
func _process(delta: float) -> void:
|
||||
if !Engine.is_editor_hint():
|
||||
position_offset = Vector3.ZERO
|
||||
rotation_offset = Vector3.ZERO
|
||||
scale_offset = Vector3.ZERO
|
||||
|
||||
if emitter_list.size() > 0:
|
||||
for emitter_data in emitter_list:
|
||||
_process_emitter(emitter_data, delta)
|
||||
|
||||
# Processes each emitter
|
||||
func _process_emitter(emitter_data: EmitterData, delta: float) -> void:
|
||||
if !Engine.is_editor_hint():
|
||||
if is_instance_valid(emitter_data.emitter):
|
||||
var ease_in: float = ease(emitter_data.timer, enter_fade_in)
|
||||
var ease_out: float = ease(1.0 - (emitter_data.timer - emitter_data.fade_out_timer), exit_fade_out) if emitter_data.fade_out_timer != 0.0 else 1.0
|
||||
emitter_data.ease_out_intensity = move_toward(emitter_data.ease_out_intensity, ease_out, delta)
|
||||
ease_out = emitter_data.ease_out_intensity
|
||||
var max_distance: float = emitter_data.emitter.max_distance
|
||||
var distance: float = min(emitter_data.emitter.global_position.distance_to(global_position), max_distance) / max(max_distance, 0.001)
|
||||
|
||||
var attenuation: float = ease(1.0 - distance, emitter_data.emitter.distance_attenuation)
|
||||
position_offset += emitter_data.emitter.shake_offset_position * ease_in * ease_out * attenuation
|
||||
rotation_offset += emitter_data.emitter.shake_offset_rotation * ease_in * ease_out * attenuation
|
||||
scale_offset += emitter_data.emitter.shake_offset_scale * ease_in * ease_out * attenuation
|
||||
emitter_data.timer += delta
|
||||
if ease_out <= delta:
|
||||
emitter_list.erase(emitter_data)
|
||||
else:
|
||||
emitter_list.erase(emitter_data)
|
||||
|
||||
|
||||
# Returns the current shake values
|
||||
func get_value() -> Array[Vector3]:
|
||||
return [position_offset, rotation_offset, scale_offset]
|
||||
|
||||
# Returns configuration warnings
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
if not get_parent() is ShakerComponent3D:
|
||||
return ["Parent must be ShakerComponent3D"]
|
||||
var _ex:bool = false
|
||||
for i in get_children():
|
||||
if i is Area3D:
|
||||
_ex = true
|
||||
break
|
||||
if !_ex:
|
||||
return ["ShakerReceiver3D needs Area3D to work"]
|
||||
return []
|
||||
|
||||
# Called when an area enters
|
||||
func on_area_entered(area: Area3D) -> void:
|
||||
var node = area.get_parent()
|
||||
if node is ShakerEmitter3D:
|
||||
var _exists = null
|
||||
for index in emitter_list.size():
|
||||
var data = emitter_list[index]
|
||||
if data.emitter == node: _exists = data
|
||||
if !_exists:
|
||||
var data = EmitterData.new(node)
|
||||
emitter_list.append(data)
|
||||
else:
|
||||
_exists.fade_out_timer = 0.0
|
||||
|
||||
# Called when an area exits
|
||||
func on_area_exited(area: Area3D) -> void:
|
||||
var node = area.get_parent()
|
||||
if node is ShakerEmitter3D:
|
||||
for index in emitter_list.size():
|
||||
var data = emitter_list[index]
|
||||
if data.emitter == node:
|
||||
data.fade_out_timer = data.timer
|
||||
break
|
||||
|
||||
# Setter for enter_fade_in
|
||||
func set_fade_in(value: float) -> void:
|
||||
enter_fade_in = value
|
||||
|
||||
# Getter for enter_fade_in
|
||||
func get_fade_in() -> float:
|
||||
return enter_fade_in
|
||||
|
||||
# Setter for exit_fade_out
|
||||
func set_fade_out(value: float) -> void:
|
||||
exit_fade_out = value
|
||||
|
||||
# Getter for exit_fade_out
|
||||
func get_fade_out() -> float:
|
||||
return exit_fade_out
|
||||
|
||||
# EmitterData inner class
|
||||
class EmitterData:
|
||||
var emitter: ShakerEmitter3D
|
||||
var timer: float = 0.0
|
||||
var fade_out_timer: float = 0.0
|
||||
var ease_out_intensity:float = 1.0
|
||||
|
||||
func _init(_emitter: ShakerEmitter3D) -> void:
|
||||
self.emitter = _emitter
|
||||
|
||||
func is_playing() -> bool:
|
||||
for i:EmitterData in emitter_list:
|
||||
return i.emitter.emitting
|
||||
return false
|
||||
Reference in New Issue
Block a user