some shake

This commit is contained in:
2026-01-20 15:27:59 +01:00
parent 8d1e7ebb4f
commit c1ca0bf27b
143 changed files with 5704 additions and 6 deletions

View File

@@ -0,0 +1,48 @@
@icon("res://addons/shaker/assets/ShakerType3D.svg")
@tool
class_name ShakerTypeBase3D
extends ShakerTypeBase
enum GraphAxis {
X,
Y,
Z
}
@export var amplitude: Vector3 = Vector3.ONE:
set = set_amplitude,
get = get_amplitude
@export var offset: Vector3 = Vector3.ZERO:
set = set_offset,
get = get_offset
func set_amplitude(value: Vector3) -> void:
amplitude = value
_on_property_changed("amplitude")
func get_amplitude() -> Vector3:
return amplitude
func set_offset(value: Vector3) -> void:
offset = value
_on_property_changed("offset")
func get_offset() -> Vector3:
return offset
# Get the shake value at a given time
func get_value(t: float) -> Vector3:
var result: Vector3 = Vector3.ZERO
return _calc_value(fmod(t, 1.0), result)
# Calculate the shake value
func _calc_value(t: float, result: Vector3) -> Vector3:
if duration > 0:
t /= duration
if (start_percent != 0 && start_percent > t) || (end_percent != 1 && end_percent < t):
result = Vector3.ZERO
else:
result = result * amplitude + offset
result *= (ease(t, fade_in) if abs(fade_in) > 0.0001 else 1.0) * (ease(1.0 - t, fade_out) if abs(fade_out) > 0.0001 else 1.0)
return result

View File

@@ -0,0 +1 @@
uid://0tu2q57qqu4s

View File

@@ -0,0 +1,103 @@
@tool
@icon("res://addons/shaker/assets/ShakerPreset3D.svg")
class_name ShakerPreset3D
extends ShakerPresetBase
# Shake type arrays for each category
@export var PositionShake: Array[ShakerTypeBase3D]:
set = set_position_shake,
get = get_position_shake
@export var RotationShake: Array[ShakerTypeBase3D]:
set = set_rotation_shake,
get = get_rotation_shake
@export var ScaleShake: Array[ShakerTypeBase3D]:
set = set_scale_shake,
get = get_scale_shake
# Custom setter and getter functions
func set_position_shake(value: Array[ShakerTypeBase3D]) -> void:
for _shake_type in _array_difference(PositionShake, value):
if _shake_type != null:
_shake_type.property_changed.connect(_on_property_changed)
_shake_type.property_changed.connect(_change_graph_category.bind(0))
PositionShake = value
if Graph != null:
Graph.select_category(0)
Graph._on_fit_button_clicked()
_on_property_changed("PositionShake")
func get_position_shake() -> Array[ShakerTypeBase3D]:
return PositionShake
func set_rotation_shake(value: Array[ShakerTypeBase3D]) -> void:
for _shake_type in _array_difference(RotationShake, value):
if _shake_type != null:
_shake_type.property_changed.connect(_on_property_changed)
_shake_type.property_changed.connect(_change_graph_category.bind(1))
RotationShake = value
if Graph != null:
Graph.select_category(1)
Graph._on_fit_button_clicked()
_on_property_changed("RotationShake")
func get_rotation_shake() -> Array[ShakerTypeBase3D]:
return RotationShake
func set_scale_shake(value: Array[ShakerTypeBase3D]) -> void:
for _shake_type in _array_difference(ScaleShake, value):
if _shake_type != null:
_shake_type.property_changed.connect(_on_property_changed)
_shake_type.property_changed.connect(_change_graph_category.bind(2))
ScaleShake = value
if Graph != null:
Graph.select_category(2)
Graph._on_fit_button_clicked()
_on_property_changed("ScaleShake")
func get_scale_shake() -> Array[ShakerTypeBase3D]:
return ScaleShake
# Get the shake value for a given time and category
func get_value(t: float, _category: Categories = Categories.POSITION) -> Vector3:
var result: Vector3 = Vector3.ZERO
var selected_category: Array[ShakerTypeBase3D] = [PositionShake, RotationShake, ScaleShake][_category]
for shake_type in selected_category:
if shake_type != null:
shake_type.duration = component_duration
var _shake_result: Vector3 = shake_type.get_value(t)
match shake_type.BlendingMode:
shake_type.BlendingModes.Add:
result += _shake_result
shake_type.BlendingModes.Multiply:
result *= _shake_result
shake_type.BlendingModes.Subtract:
result -= _shake_result
shake_type.BlendingModes.Max:
result.x = max(result.x, _shake_result.x)
result.y = max(result.y, _shake_result.y)
result.z = max(result.z, _shake_result.z)
shake_type.BlendingModes.Min:
result.x = min(result.x, _shake_result.x)
result.y = min(result.y, _shake_result.y)
result.z = min(result.z, _shake_result.z)
shake_type.BlendingModes.Average:
result = (result + _shake_result) * 0.5
shake_type.BlendingModes.Override:
result = _shake_result
return result
func _change_graph_category(_name:String, _category_index:int) -> void:
if Graph:
Graph.category_button.select(_category_index)
Graph.category_button.item_selected.emit(_category_index)
func get_shakes_by_category(category:Categories) -> Array:
if category == Categories.POSITION:
return PositionShake
elif category == Categories.ROTATION:
return RotationShake
elif category == Categories.SCALE:
return ScaleShake
return [null]

View File

@@ -0,0 +1 @@
uid://mlwdmecg12xd

View File

@@ -0,0 +1,49 @@
@tool
class_name ShakerTypeAudioBus3D
extends ShakerTypeBase3D
@export var bus_name:String = "Master":
set = set_bus_name,
get = get_bus_name
@export var min_frequence:Vector3 = Vector3(20, 20, 20)
@export var max_frequence:Vector3 = Vector3(20000, 20000, 20000)
var bus_index:int = 0
var effect:AudioEffectSpectrumAnalyzerInstance
func _init():
_update_bus_index()
## Calculates the value of the square wave at time t.
func get_value(t: float) -> Vector3:
var result:Vector3 = Vector3.ZERO
if effect:
var mag_x:Vector2 = effect.get_magnitude_for_frequency_range(min_frequence.x, max_frequence.x, AudioEffectSpectrumAnalyzerInstance.MAGNITUDE_MAX)
var mag_y:Vector2 = effect.get_magnitude_for_frequency_range(min_frequence.y, max_frequence.y, AudioEffectSpectrumAnalyzerInstance.MAGNITUDE_MAX)
var mag_z:Vector2 = effect.get_magnitude_for_frequency_range(min_frequence.z, max_frequence.z, AudioEffectSpectrumAnalyzerInstance.MAGNITUDE_MAX)
result.x = mag_x.length()
result.y = mag_y.length()
result.z = mag_y.length()
return _calc_value(t, result)
func set_bus_name(value: String) -> void:
bus_name = value
_update_bus_index()
_on_property_changed("bus_name")
func get_bus_name() -> String:
return bus_name
func _update_bus_index() -> void:
bus_index = AudioServer.get_bus_index(bus_name)
if bus_index > -1:
for e in AudioServer.get_bus_effect_count(bus_index):
var _effect:AudioEffect = AudioServer.get_bus_effect(bus_index, e)
if _effect is AudioEffectSpectrumAnalyzer:
effect = AudioServer.get_bus_effect_instance(bus_index, e, 0)
break;
if effect == null:
AudioServer.add_bus_effect(bus_index, AudioEffectSpectrumAnalyzer.new(), 0)
effect = AudioServer.get_bus_effect_instance(bus_index, 0)
else:
push_error("Error: Bus '" + bus_name + "' not found!")
effect = null

View File

@@ -0,0 +1 @@
uid://cdne0sspxhssj

View File

@@ -0,0 +1,46 @@
@tool
class_name ShakerTypeBrownianShake3D
extends ShakerTypeBase3D
@export var roughness: Vector3 = Vector3.ONE * 1.0:
set = set_roughness,
get = get_roughness
@export var persistence: Vector3 = Vector3.ONE * 0.5:
set = set_persistence,
get = get_persistence
var _generator: RandomNumberGenerator = RandomNumberGenerator.new()
var _last_pos: Vector3 = Vector3.ZERO
func _init() -> void:
property_changed.connect(_property_changed)
func get_value(t: float) -> Vector3:
var result: Vector3 = Vector3.ZERO
result.x = (_last_pos.x + _generator.randf_range(-roughness.x, roughness.x))
result.y = (_last_pos.y + _generator.randf_range(-roughness.y, roughness.y))
result.z = (_last_pos.z + _generator.randf_range(-roughness.z, roughness.z))
result = _calc_value(t, result)
_last_pos.x = lerpf(_last_pos.x, result.x, 1.0 - persistence.x)
_last_pos.y = lerpf(_last_pos.y, result.y, 1.0 - persistence.y)
_last_pos.z = lerpf(_last_pos.z, result.z, 1.0 - persistence.z)
return _last_pos
func _property_changed(name: StringName) -> void:
_last_pos = Vector3.ZERO
func set_roughness(value: Vector3) -> void:
roughness = value
_on_property_changed("roughness")
func get_roughness() -> Vector3:
return roughness
func set_persistence(value: Vector3) -> void:
persistence = value.clamp(Vector3.ZERO, Vector3.ONE)
_on_property_changed("persistence")
func get_persistence() -> Vector3:
return persistence

View File

@@ -0,0 +1 @@
uid://ddk408cg8156q

View File

@@ -0,0 +1,78 @@
@tool
class_name ShakerTypeCurve3D
extends ShakerTypeBase3D
@export var curve_x: Curve:
set = set_curve_x,
get = get_curve_x
@export var curve_y: Curve:
set = set_curve_y,
get = get_curve_y
@export var curve_z: Curve:
set = set_curve_z,
get = get_curve_z
@export var loop: bool = true:
set = set_loop,
get = get_loop
func _curve_changed() -> void:
_on_property_changed("curve_")
func get_value(t: float) -> Vector3:
var result: Vector3 = Vector3.ZERO
if loop && t > 1.0:
t = fmod(t, 1.0)
if curve_x:
result.x = curve_x.sample(t)
if curve_y:
result.y = curve_y.sample(t)
if curve_z:
result.z = curve_z.sample(t)
return _calc_value(t, result)
func set_curve_x(value: Curve) -> void:
if curve_x:
curve_x.changed.disconnect(_curve_changed)
curve_x = value
if curve_x:
curve_x.changed.connect(_curve_changed)
else:
_curve_changed()
func get_curve_x() -> Curve:
return curve_x
func set_curve_y(value: Curve) -> void:
if curve_y:
curve_y.changed.disconnect(_curve_changed)
curve_y = value
if curve_y:
curve_y.changed.connect(_curve_changed)
else:
_curve_changed()
func get_curve_y() -> Curve:
return curve_y
func set_curve_z(value: Curve) -> void:
if curve_z:
curve_z.changed.disconnect(_curve_changed)
curve_z = value
if curve_z:
curve_z.changed.connect(_curve_changed)
else:
_curve_changed()
func get_curve_z() -> Curve:
return curve_z
func set_loop(value: bool) -> void:
loop = value
_on_property_changed("loop")
func get_loop() -> bool:
return loop

View File

@@ -0,0 +1 @@
uid://biqfuixncau4j

View File

@@ -0,0 +1,34 @@
@tool
class_name ShakerTypeNoiseShake3D
extends ShakerTypeBase3D
@export var noise_texture: NoiseTexture3D = NoiseTexture3D.new():
set = set_noise_texture,
get = get_noise_texture
func _init() -> void:
noise_texture.changed.connect(_on_noise_changed)
func get_value(t: float) -> Vector3:
var result: Vector3 = Vector3.ZERO
if noise_texture && noise_texture.noise:
var noise_size: Vector3 = Vector3(noise_texture.width, noise_texture.height, noise_texture.depth)
var noise_offset: Vector3 = t * noise_size
result.x = noise_texture.noise.get_noise_3d(noise_offset.x, 0.0, 0.0)
result.y = noise_texture.noise.get_noise_3d(0.0, noise_offset.y, 0.0)
result.z = noise_texture.noise.get_noise_3d(0.0, 0.0, noise_offset.z)
result *= 2.0
return _calc_value(t, result)
func _on_noise_changed() -> void:
_on_property_changed("noise_texture")
func set_noise_texture(value: NoiseTexture3D) -> void:
if noise_texture:
noise_texture.changed.disconnect(_on_noise_changed)
noise_texture = value
if noise_texture:
noise_texture.changed.connect(_on_noise_changed)
func get_noise_texture() -> NoiseTexture3D:
return noise_texture

View File

@@ -0,0 +1 @@
uid://ptaespkh1sk2

View File

@@ -0,0 +1,32 @@
@tool
class_name ShakerTypeRandom3D
extends ShakerTypeBase3D
## The seed for the random number generator.
@export var seed: int = 0:
set = set_seed
## The random number generator instance.
var _generator: RandomNumberGenerator = RandomNumberGenerator.new()
## Initializes the shake type with the given seed.
func _init() -> void:
set_seed(seed)
## Calculates a random value for each axis at time t.
func get_value(t: float) -> Vector3:
var result: Vector3 = Vector3.ZERO
result.x = _generator.randf_range(-1.0, 1.0)
result.y = _generator.randf_range(-1.0, 1.0)
result.z = _generator.randf_range(-1.0, 1.0)
return _calc_value(t, result)
## Sets the seed for the random number generator.
func set_seed(value: int) -> void:
seed = value
_generator.seed = seed
_on_property_changed("seed")
## Gets the current seed of the random number generator.
func get_seed() -> int:
return seed

View File

@@ -0,0 +1 @@
uid://jyrxhux22cdm

View File

@@ -0,0 +1,43 @@
@tool
class_name ShakerTypeSawtoothWave3D
extends ShakerTypeBase3D
## The frequency of the sawtooth wave for each axis.
@export var frequency: Vector3 = Vector3.ONE * 5.0:
set = set_frequency
## The asymmetry of the sawtooth wave for each axis (0 to 1).
@export var asymmetry: Vector3 = Vector3.ONE * 0.5:
set = set_asymmetry
## Sets the frequency of the sawtooth wave.
func set_frequency(value: Vector3) -> void:
frequency = value
_on_property_changed("frequency")
## Gets the frequency of the sawtooth wave.
func get_frequency() -> Vector3:
return frequency
## Sets the asymmetry of the sawtooth wave.
func set_asymmetry(value: Vector3) -> void:
asymmetry = value.clamp(Vector3.ZERO, Vector3.ONE)
_on_property_changed("asymmetry")
## Gets the asymmetry of the sawtooth wave.
func get_asymmetry() -> Vector3:
return asymmetry
## Calculates the value of the sawtooth wave at time t.
func get_value(t: float) -> Vector3:
var result: Vector3 = Vector3.ZERO
var _real_time: float = fmod(t, 1.0) if t > 1.0 else t
var wave: Vector3 = (_real_time * frequency).posmod(1.0)
wave.x = wave.x / asymmetry.x if wave.x < asymmetry.x else (1.0 - wave.x) / (1.0 - asymmetry.x)
wave.y = wave.y / asymmetry.y if wave.y < asymmetry.y else (1.0 - wave.y) / (1.0 - asymmetry.y)
wave.z = wave.z / asymmetry.z if wave.z < asymmetry.z else (1.0 - wave.z) / (1.0 - asymmetry.z)
result = wave
result = _calc_value(t, result)
result = (result - amplitude * 0.5) * 2.0
return result

View File

@@ -0,0 +1 @@
uid://dpoggf3psdkci

View File

@@ -0,0 +1,34 @@
@tool
class_name ShakerTypeSineWave3D
extends ShakerTypeBase3D
@export_group("Sinewave Properties")
@export var frequency: Vector3 = Vector3.ONE:
set = set_frequency,
get = get_frequency
@export var phase: Vector3 = Vector3.ONE:
set = set_phase,
get = get_phase
func get_value(t: float) -> Vector3:
var result: Vector3 = Vector3.ZERO
var _real_time: float = fmod(t, 1.0) if t > 1.0 else t
result.x = sin(t * frequency.x * TAU + phase.x)
result.y = sin(t * frequency.y * TAU + phase.y + PI/2)
result.z = sin(t * frequency.z * TAU + phase.z + PI/4)
return _calc_value(_real_time, result)
func set_frequency(value: Vector3) -> void:
frequency = value
_on_property_changed("frequency")
func get_frequency() -> Vector3:
return frequency
func set_phase(value: Vector3) -> void:
phase = value
_on_property_changed("phase")
func get_phase() -> Vector3:
return phase

View File

@@ -0,0 +1 @@
uid://sih7vd0uinav

View File

@@ -0,0 +1,37 @@
@tool
class_name ShakerTypeSquareWave3D
extends ShakerTypeBase3D
## The frequency of the square wave for each axis.
@export var frequency: Vector3 = Vector3.ONE * 5.0:
set = set_frequency
## The duty cycle of the square wave for each axis (0 to 1).
@export var duty_cycle: Vector3 = Vector3.ONE * 0.5:
set = set_duty_cycle
## Sets the frequency of the square wave.
func set_frequency(value: Vector3) -> void:
frequency = value
_on_property_changed("frequency")
## Gets the frequency of the square wave.
func get_frequency() -> Vector3:
return frequency
## Sets the duty cycle of the square wave.
func set_duty_cycle(value: Vector3) -> void:
duty_cycle = value.clamp(Vector3.ZERO, Vector3.ONE)
_on_property_changed("duty_cycle")
## Gets the duty cycle of the square wave.
func get_duty_cycle() -> Vector3:
return duty_cycle
## Calculates the value of the square wave at time t.
func get_value(t: float) -> Vector3:
var result: Vector3 = Vector3.ZERO
result.x = 1.0 if fmod(t * frequency.x, 1.0) < duty_cycle.x else -1.0
result.y = 1.0 if fmod(t * frequency.y, 1.0) < duty_cycle.y else -1.0
result.z = 1.0 if fmod(t * frequency.z, 1.0) < duty_cycle.z else -1.0
return _calc_value(t, result)

View File

@@ -0,0 +1 @@
uid://drpiei33e2en