Add a gizmo to visualize AudioStreamPlayer3D's audible radius
The ring's color changes depending on the attenuation model chosen, and whether Max Distance is capping the distance the sound can be heard at. Cold colors are used when the volume cap is a "soft" cap (the sound can still be heard past the distance, but only faintly). Warm colors are used when the volume cap is a "hard" cap (the sound can't be heard past the distance at all). White is used for linear fade performed when the attenuation model is Disabled and Max Distance is greater than 0. No ring is drawn when the attenuation model is Disabled and Max Distance is equal to 0 (since the sound can be heard from anywhere).
This commit is contained in:
parent
2e8862887c
commit
93933e4085
|
@ -1497,6 +1497,9 @@ AudioStreamPlayer3DGizmoPlugin::AudioStreamPlayer3DGizmoPlugin() {
|
|||
create_icon_material("stream_player_3d_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("Gizmo3DSamplePlayer"), SNAME("EditorIcons")));
|
||||
create_material("stream_player_3d_material_primary", gizmo_color);
|
||||
create_material("stream_player_3d_material_secondary", gizmo_color * Color(1, 1, 1, 0.35));
|
||||
// Enable vertex colors for the billboard material as the gizmo color depends on the
|
||||
// AudioStreamPlayer3D attenuation type and source (Unit Size or Max Distance).
|
||||
create_material("stream_player_3d_material_billboard", Color(1, 1, 1), true, false, true);
|
||||
create_handle_material("handles");
|
||||
}
|
||||
|
||||
|
@ -1580,6 +1583,88 @@ void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
|||
|
||||
const Ref<Material> icon = get_material("stream_player_3d_icon", p_gizmo);
|
||||
|
||||
if (player->get_attenuation_model() != AudioStreamPlayer3D::ATTENUATION_DISABLED || player->get_max_distance() > CMP_EPSILON) {
|
||||
// Draw a circle to represent sound volume attenuation.
|
||||
// Use only a billboard circle to represent radius.
|
||||
// This helps distinguish AudioStreamPlayer3D gizmos from OmniLight3D gizmos.
|
||||
const Ref<Material> lines_billboard_material = get_material("stream_player_3d_material_billboard", p_gizmo);
|
||||
|
||||
// Soft distance cap varies depending on attenuation model, as some will fade out more aggressively than others.
|
||||
// Multipliers were empirically determined through testing.
|
||||
float soft_multiplier;
|
||||
switch (player->get_attenuation_model()) {
|
||||
case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
|
||||
soft_multiplier = 12.0;
|
||||
break;
|
||||
case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
|
||||
soft_multiplier = 4.0;
|
||||
break;
|
||||
case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
|
||||
soft_multiplier = 3.25;
|
||||
break;
|
||||
default:
|
||||
// Ensures Max Distance's radius visualization is not capped by Unit Size
|
||||
// (when the attenuation mode is Disabled).
|
||||
soft_multiplier = 10000.0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw the distance at which the sound can be reasonably heard.
|
||||
// This can be either a hard distance cap with the Max Distance property (if set above 0.0),
|
||||
// or a soft distance cap with the Unit Size property (sound never reaches true zero).
|
||||
// When Max Distance is 0.0, `r` represents the distance above which the
|
||||
// sound can't be heard in *most* (but not all) scenarios.
|
||||
float r;
|
||||
if (player->get_max_distance() > CMP_EPSILON) {
|
||||
r = MIN(player->get_unit_size() * soft_multiplier, player->get_max_distance());
|
||||
} else {
|
||||
r = player->get_unit_size() * soft_multiplier;
|
||||
}
|
||||
Vector<Vector3> points_billboard;
|
||||
|
||||
for (int i = 0; i < 120; i++) {
|
||||
// Create a circle.
|
||||
const float ra = Math::deg2rad((float)(i * 3));
|
||||
const float rb = Math::deg2rad((float)((i + 1) * 3));
|
||||
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
|
||||
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
|
||||
|
||||
// Draw a billboarded circle.
|
||||
points_billboard.push_back(Vector3(a.x, a.y, 0));
|
||||
points_billboard.push_back(Vector3(b.x, b.y, 0));
|
||||
}
|
||||
|
||||
Color color;
|
||||
switch (player->get_attenuation_model()) {
|
||||
// Pick cold colors for all attenuation models (except Disabled),
|
||||
// so that soft caps can be easily distinguished from hard caps
|
||||
// (which use warm colors).
|
||||
case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
|
||||
color = Color(0.4, 0.8, 1);
|
||||
break;
|
||||
case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
|
||||
color = Color(0.4, 0.5, 1);
|
||||
break;
|
||||
case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
|
||||
color = Color(0.4, 0.2, 1);
|
||||
break;
|
||||
default:
|
||||
// Disabled attenuation mode.
|
||||
// This is never reached when Max Distance is 0, but the
|
||||
// hue-inverted form of this color will be used if Max Distance is greater than 0.
|
||||
color = Color(1, 1, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (player->get_max_distance() > CMP_EPSILON) {
|
||||
// Sound is hard-capped by max distance. The attenuation model still matters,
|
||||
// so invert the hue of the color that was chosen above.
|
||||
color.set_h(color.get_h() + 0.5);
|
||||
}
|
||||
|
||||
p_gizmo->add_lines(points_billboard, lines_billboard_material, true, color);
|
||||
}
|
||||
|
||||
if (player->is_emission_angle_enabled()) {
|
||||
const float pc = player->get_emission_angle();
|
||||
const float ofs = -Math::cos(Math::deg2rad(pc));
|
||||
|
|
|
@ -541,6 +541,7 @@ float AudioStreamPlayer3D::get_unit_db() const {
|
|||
|
||||
void AudioStreamPlayer3D::set_unit_size(float p_volume) {
|
||||
unit_size = p_volume;
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
float AudioStreamPlayer3D::get_unit_size() const {
|
||||
|
@ -669,6 +670,7 @@ void AudioStreamPlayer3D::_bus_layout_changed() {
|
|||
void AudioStreamPlayer3D::set_max_distance(float p_metres) {
|
||||
ERR_FAIL_COND(p_metres < 0.0);
|
||||
max_distance = p_metres;
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
float AudioStreamPlayer3D::get_max_distance() const {
|
||||
|
@ -729,6 +731,7 @@ float AudioStreamPlayer3D::get_attenuation_filter_db() const {
|
|||
void AudioStreamPlayer3D::set_attenuation_model(AttenuationModel p_model) {
|
||||
ERR_FAIL_INDEX((int)p_model, 4);
|
||||
attenuation_model = p_model;
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
AudioStreamPlayer3D::AttenuationModel AudioStreamPlayer3D::get_attenuation_model() const {
|
||||
|
|
Loading…
Reference in New Issue