1 | /**************************************************************************/ |
2 | /* editor_audio_buses.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "editor_audio_buses.h" |
32 | |
33 | #include "core/config/project_settings.h" |
34 | #include "core/input/input.h" |
35 | #include "core/io/resource_saver.h" |
36 | #include "core/os/keyboard.h" |
37 | #include "editor/editor_node.h" |
38 | #include "editor/editor_scale.h" |
39 | #include "editor/editor_settings.h" |
40 | #include "editor/editor_string_names.h" |
41 | #include "editor/editor_undo_redo_manager.h" |
42 | #include "editor/filesystem_dock.h" |
43 | #include "editor/gui/editor_file_dialog.h" |
44 | #include "scene/gui/separator.h" |
45 | #include "scene/resources/font.h" |
46 | #include "servers/audio_server.h" |
47 | |
48 | void EditorAudioBus::_update_visible_channels() { |
49 | int i = 0; |
50 | for (; i < cc; i++) { |
51 | if (!channel[i].vu_l->is_visible()) { |
52 | channel[i].vu_l->show(); |
53 | } |
54 | if (!channel[i].vu_r->is_visible()) { |
55 | channel[i].vu_r->show(); |
56 | } |
57 | } |
58 | |
59 | for (; i < CHANNELS_MAX; i++) { |
60 | if (channel[i].vu_l->is_visible()) { |
61 | channel[i].vu_l->hide(); |
62 | } |
63 | if (channel[i].vu_r->is_visible()) { |
64 | channel[i].vu_r->hide(); |
65 | } |
66 | } |
67 | } |
68 | |
69 | void EditorAudioBus::_notification(int p_what) { |
70 | switch (p_what) { |
71 | case NOTIFICATION_ENTER_TREE: |
72 | case NOTIFICATION_THEME_CHANGED: { |
73 | Ref<Texture2D> active_bus_texture = get_editor_theme_icon(SNAME("BusVuActive" )); |
74 | for (int i = 0; i < CHANNELS_MAX; i++) { |
75 | channel[i].vu_l->set_under_texture(active_bus_texture); |
76 | channel[i].vu_l->set_tint_under(Color(0.75, 0.75, 0.75)); |
77 | channel[i].vu_l->set_progress_texture(active_bus_texture); |
78 | |
79 | channel[i].vu_r->set_under_texture(active_bus_texture); |
80 | channel[i].vu_r->set_tint_under(Color(0.75, 0.75, 0.75)); |
81 | channel[i].vu_r->set_progress_texture(active_bus_texture); |
82 | channel[i].prev_active = true; |
83 | } |
84 | |
85 | disabled_vu = get_editor_theme_icon(SNAME("BusVuFrozen" )); |
86 | |
87 | Color solo_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0, 0.89, 0.22) : Color(1.0, 0.92, 0.44); |
88 | Color mute_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0, 0.16, 0.16) : Color(1.0, 0.44, 0.44); |
89 | Color bypass_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(0.13, 0.8, 1.0) : Color(0.44, 0.87, 1.0); |
90 | |
91 | solo->set_icon(get_editor_theme_icon(SNAME("AudioBusSolo" ))); |
92 | solo->add_theme_color_override("icon_pressed_color" , solo_color); |
93 | mute->set_icon(get_editor_theme_icon(SNAME("AudioBusMute" ))); |
94 | mute->add_theme_color_override("icon_pressed_color" , mute_color); |
95 | bypass->set_icon(get_editor_theme_icon(SNAME("AudioBusBypass" ))); |
96 | bypass->add_theme_color_override("icon_pressed_color" , bypass_color); |
97 | |
98 | bus_options->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl" ))); |
99 | |
100 | audio_value_preview_label->add_theme_color_override("font_color" , get_theme_color(SNAME("font_color" ), SNAME("TooltipLabel" ))); |
101 | audio_value_preview_label->add_theme_color_override("font_shadow_color" , get_theme_color(SNAME("font_shadow_color" ), SNAME("TooltipLabel" ))); |
102 | audio_value_preview_box->add_theme_style_override("panel" , get_theme_stylebox(SNAME("panel" ), SNAME("TooltipPanel" ))); |
103 | |
104 | for (int i = 0; i < effect_options->get_item_count(); i++) { |
105 | String class_name = effect_options->get_item_metadata(i); |
106 | Ref<Texture> icon = EditorNode::get_singleton()->get_class_icon(class_name); |
107 | effect_options->set_item_icon(i, icon); |
108 | } |
109 | } break; |
110 | |
111 | case NOTIFICATION_READY: { |
112 | update_bus(); |
113 | set_process(true); |
114 | } break; |
115 | |
116 | case NOTIFICATION_DRAW: { |
117 | if (is_master) { |
118 | draw_style_box(get_theme_stylebox(SNAME("disabled" ), SNAME("Button" )), Rect2(Vector2(), get_size())); |
119 | } else if (has_focus()) { |
120 | draw_style_box(get_theme_stylebox(SNAME("focus" ), SNAME("Button" )), Rect2(Vector2(), get_size())); |
121 | } else { |
122 | draw_style_box(get_theme_stylebox(SNAME("panel" ), SNAME("TabContainer" )), Rect2(Vector2(), get_size())); |
123 | } |
124 | |
125 | if (get_index() != 0 && hovering_drop) { |
126 | Color accent = get_theme_color(SNAME("accent_color" ), EditorStringName(Editor)); |
127 | accent.a *= 0.7; |
128 | draw_rect(Rect2(Point2(), get_size()), accent, false); |
129 | } |
130 | } break; |
131 | |
132 | case NOTIFICATION_PROCESS: { |
133 | if (cc != AudioServer::get_singleton()->get_bus_channels(get_index())) { |
134 | cc = AudioServer::get_singleton()->get_bus_channels(get_index()); |
135 | _update_visible_channels(); |
136 | } |
137 | |
138 | for (int i = 0; i < cc; i++) { |
139 | float real_peak[2] = { -100, -100 }; |
140 | bool activity_found = false; |
141 | |
142 | if (AudioServer::get_singleton()->is_bus_channel_active(get_index(), i)) { |
143 | activity_found = true; |
144 | real_peak[0] = MAX(real_peak[0], AudioServer::get_singleton()->get_bus_peak_volume_left_db(get_index(), i)); |
145 | real_peak[1] = MAX(real_peak[1], AudioServer::get_singleton()->get_bus_peak_volume_right_db(get_index(), i)); |
146 | } |
147 | |
148 | if (real_peak[0] > channel[i].peak_l) { |
149 | channel[i].peak_l = real_peak[0]; |
150 | } else { |
151 | channel[i].peak_l -= get_process_delta_time() * 60.0; |
152 | } |
153 | |
154 | if (real_peak[1] > channel[i].peak_r) { |
155 | channel[i].peak_r = real_peak[1]; |
156 | } else { |
157 | channel[i].peak_r -= get_process_delta_time() * 60.0; |
158 | } |
159 | |
160 | channel[i].vu_l->set_value(channel[i].peak_l); |
161 | channel[i].vu_r->set_value(channel[i].peak_r); |
162 | |
163 | if (activity_found != channel[i].prev_active) { |
164 | if (activity_found) { |
165 | channel[i].vu_l->set_over_texture(Ref<Texture2D>()); |
166 | channel[i].vu_r->set_over_texture(Ref<Texture2D>()); |
167 | } else { |
168 | channel[i].vu_l->set_over_texture(disabled_vu); |
169 | channel[i].vu_r->set_over_texture(disabled_vu); |
170 | } |
171 | |
172 | channel[i].prev_active = activity_found; |
173 | } |
174 | } |
175 | } break; |
176 | |
177 | case NOTIFICATION_VISIBILITY_CHANGED: { |
178 | for (int i = 0; i < CHANNELS_MAX; i++) { |
179 | channel[i].peak_l = -100; |
180 | channel[i].peak_r = -100; |
181 | channel[i].prev_active = true; |
182 | } |
183 | |
184 | set_process(is_visible_in_tree()); |
185 | } break; |
186 | |
187 | case NOTIFICATION_MOUSE_EXIT: |
188 | case NOTIFICATION_DRAG_END: { |
189 | if (hovering_drop) { |
190 | hovering_drop = false; |
191 | queue_redraw(); |
192 | } |
193 | } break; |
194 | } |
195 | } |
196 | |
197 | void EditorAudioBus::update_send() { |
198 | send->clear(); |
199 | if (is_master) { |
200 | send->set_disabled(true); |
201 | send->set_text(TTR("Speakers" )); |
202 | } else { |
203 | send->set_disabled(false); |
204 | StringName current_send = AudioServer::get_singleton()->get_bus_send(get_index()); |
205 | int current_send_index = 0; //by default to master |
206 | |
207 | for (int i = 0; i < get_index(); i++) { |
208 | StringName send_name = AudioServer::get_singleton()->get_bus_name(i); |
209 | send->add_item(send_name); |
210 | if (send_name == current_send) { |
211 | current_send_index = i; |
212 | } |
213 | } |
214 | |
215 | send->select(current_send_index); |
216 | } |
217 | } |
218 | |
219 | void EditorAudioBus::update_bus() { |
220 | if (updating_bus) { |
221 | return; |
222 | } |
223 | |
224 | updating_bus = true; |
225 | |
226 | int index = get_index(); |
227 | |
228 | float db_value = AudioServer::get_singleton()->get_bus_volume_db(index); |
229 | slider->set_value(_scaled_db_to_normalized_volume(db_value)); |
230 | track_name->set_text(AudioServer::get_singleton()->get_bus_name(index)); |
231 | if (is_master) { |
232 | track_name->set_editable(false); |
233 | } |
234 | |
235 | solo->set_pressed(AudioServer::get_singleton()->is_bus_solo(index)); |
236 | mute->set_pressed(AudioServer::get_singleton()->is_bus_mute(index)); |
237 | bypass->set_pressed(AudioServer::get_singleton()->is_bus_bypassing_effects(index)); |
238 | // effects.. |
239 | effects->clear(); |
240 | |
241 | TreeItem *root = effects->create_item(); |
242 | for (int i = 0; i < AudioServer::get_singleton()->get_bus_effect_count(index); i++) { |
243 | Ref<AudioEffect> afx = AudioServer::get_singleton()->get_bus_effect(index, i); |
244 | |
245 | TreeItem *fx = effects->create_item(root); |
246 | fx->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); |
247 | fx->set_editable(0, true); |
248 | fx->set_checked(0, AudioServer::get_singleton()->is_bus_effect_enabled(index, i)); |
249 | fx->set_text(0, afx->get_name()); |
250 | fx->set_metadata(0, i); |
251 | } |
252 | |
253 | TreeItem *add = effects->create_item(root); |
254 | add->set_cell_mode(0, TreeItem::CELL_MODE_CUSTOM); |
255 | add->set_editable(0, true); |
256 | add->set_selectable(0, false); |
257 | add->set_text(0, TTR("Add Effect" )); |
258 | |
259 | update_send(); |
260 | |
261 | updating_bus = false; |
262 | } |
263 | |
264 | void EditorAudioBus::_name_changed(const String &p_new_name) { |
265 | if (updating_bus) { |
266 | return; |
267 | } |
268 | updating_bus = true; |
269 | track_name->release_focus(); |
270 | |
271 | if (p_new_name == AudioServer::get_singleton()->get_bus_name(get_index())) { |
272 | updating_bus = false; |
273 | return; |
274 | } |
275 | |
276 | String attempt = p_new_name; |
277 | int attempts = 1; |
278 | |
279 | while (true) { |
280 | bool name_free = true; |
281 | for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { |
282 | if (AudioServer::get_singleton()->get_bus_name(i) == attempt) { |
283 | name_free = false; |
284 | break; |
285 | } |
286 | } |
287 | |
288 | if (name_free) { |
289 | break; |
290 | } |
291 | |
292 | attempts++; |
293 | attempt = p_new_name + " " + itos(attempts); |
294 | } |
295 | |
296 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
297 | |
298 | StringName current = AudioServer::get_singleton()->get_bus_name(get_index()); |
299 | |
300 | ur->create_action(TTR("Rename Audio Bus" )); |
301 | ur->add_do_method(buses, "_set_renaming_buses" , true); |
302 | ur->add_undo_method(buses, "_set_renaming_buses" , true); |
303 | |
304 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_name" , get_index(), attempt); |
305 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_name" , get_index(), current); |
306 | |
307 | for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { |
308 | if (AudioServer::get_singleton()->get_bus_send(i) == current) { |
309 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_send" , i, attempt); |
310 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_send" , i, current); |
311 | } |
312 | } |
313 | |
314 | ur->add_do_method(buses, "_update_bus" , get_index()); |
315 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
316 | |
317 | ur->add_do_method(buses, "_update_sends" ); |
318 | ur->add_undo_method(buses, "_update_sends" ); |
319 | |
320 | ur->add_do_method(buses, "_set_renaming_buses" , false); |
321 | ur->add_undo_method(buses, "_set_renaming_buses" , false); |
322 | ur->commit_action(); |
323 | |
324 | updating_bus = false; |
325 | } |
326 | |
327 | void EditorAudioBus::_volume_changed(float p_normalized) { |
328 | if (updating_bus) { |
329 | return; |
330 | } |
331 | |
332 | updating_bus = true; |
333 | |
334 | const float p_db = this->_normalized_volume_to_scaled_db(p_normalized); |
335 | |
336 | if (Input::get_singleton()->is_key_pressed(Key::CTRL)) { |
337 | // Snap the value when holding Ctrl for easier editing. |
338 | // To do so, it needs to be converted back to normalized volume (as the slider uses that unit). |
339 | slider->set_value(_scaled_db_to_normalized_volume(Math::round(p_db))); |
340 | } |
341 | |
342 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
343 | ur->create_action(TTR("Change Audio Bus Volume" ), UndoRedo::MERGE_ENDS); |
344 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_volume_db" , get_index(), p_db); |
345 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_volume_db" , get_index(), AudioServer::get_singleton()->get_bus_volume_db(get_index())); |
346 | ur->add_do_method(buses, "_update_bus" , get_index()); |
347 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
348 | ur->commit_action(); |
349 | |
350 | updating_bus = false; |
351 | } |
352 | |
353 | float EditorAudioBus::_normalized_volume_to_scaled_db(float normalized) { |
354 | /* There are three different formulas for the conversion from normalized |
355 | * values to relative decibal values. |
356 | * One formula is an exponential graph which intends to counteract |
357 | * the logarithmic nature of human hearing. This is an approximation |
358 | * of the behavior of a 'logarithmic potentiometer' found on most |
359 | * musical instruments and also emulated in popular software. |
360 | * The other two equations are hand-tuned linear tapers that intend to |
361 | * try to ease the exponential equation in areas where it makes sense.*/ |
362 | |
363 | if (normalized > 0.6f) { |
364 | return 22.22f * normalized - 16.2f; |
365 | } else if (normalized < 0.05f) { |
366 | return 830.72 * normalized - 80.0f; |
367 | } else { |
368 | return 45.0f * Math::pow(normalized - 1.0, 3); |
369 | } |
370 | } |
371 | |
372 | float EditorAudioBus::_scaled_db_to_normalized_volume(float db) { |
373 | /* Inversion of equations found in _normalized_volume_to_scaled_db. |
374 | * IMPORTANT: If one function changes, the other much change to reflect it. */ |
375 | if (db > -2.88) { |
376 | return (db + 16.2f) / 22.22f; |
377 | } else if (db < -38.602f) { |
378 | return (db + 80.00f) / 830.72f; |
379 | } else { |
380 | if (db < 0.0) { |
381 | /* To accommodate for NaN on negative numbers for root, we will mirror the |
382 | * results of the positive db range in order to get the desired numerical |
383 | * value on the negative side. */ |
384 | float positive_x = Math::pow(Math::abs(db) / 45.0f, 1.0f / 3.0f) + 1.0f; |
385 | Vector2 translation = Vector2(1.0f, 0.0f) - Vector2(positive_x, Math::abs(db)); |
386 | Vector2 reflected_position = Vector2(1.0, 0.0f) + translation; |
387 | return reflected_position.x; |
388 | } else { |
389 | return Math::pow(db / 45.0f, 1.0f / 3.0f) + 1.0f; |
390 | } |
391 | } |
392 | } |
393 | |
394 | void EditorAudioBus::_show_value(float slider_value) { |
395 | float db; |
396 | if (Input::get_singleton()->is_key_pressed(Key::CTRL)) { |
397 | // Display the correct (snapped) value when holding Ctrl |
398 | db = Math::round(_normalized_volume_to_scaled_db(slider_value)); |
399 | } else { |
400 | db = _normalized_volume_to_scaled_db(slider_value); |
401 | } |
402 | |
403 | String text; |
404 | if (Math::is_zero_approx(Math::snapped(db, 0.1))) { |
405 | // Prevent displaying `-0.0 dB` and show ` 0.0 dB` instead. |
406 | // The leading space makes the text visually line up with its positive/negative counterparts. |
407 | text = " 0.0 dB" ; |
408 | } else { |
409 | // Show an explicit `+` sign if positive. |
410 | text = vformat("%+.1f dB" , db); |
411 | } |
412 | |
413 | // Also set the preview text as a standard Control tooltip. |
414 | // This way, it can be seen when the slider is merely hovered (instead of dragged). |
415 | slider->set_tooltip_text(text); |
416 | audio_value_preview_label->set_text(text); |
417 | const Vector2 slider_size = slider->get_size(); |
418 | const Vector2 slider_position = slider->get_global_position(); |
419 | const float vert_padding = 10.0f; |
420 | const Vector2 box_position = Vector2(slider_size.x, (slider_size.y - vert_padding) * (1.0f - slider->get_value()) - vert_padding); |
421 | audio_value_preview_box->set_position(slider_position + box_position); |
422 | audio_value_preview_box->set_size(audio_value_preview_label->get_size()); |
423 | if (slider->has_focus() && !audio_value_preview_box->is_visible()) { |
424 | audio_value_preview_box->show(); |
425 | } |
426 | preview_timer->start(); |
427 | } |
428 | |
429 | void EditorAudioBus::_hide_value_preview() { |
430 | audio_value_preview_box->hide(); |
431 | } |
432 | |
433 | void EditorAudioBus::_solo_toggled() { |
434 | updating_bus = true; |
435 | |
436 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
437 | ur->create_action(TTR("Toggle Audio Bus Solo" )); |
438 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_solo" , get_index(), solo->is_pressed()); |
439 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_solo" , get_index(), AudioServer::get_singleton()->is_bus_solo(get_index())); |
440 | ur->add_do_method(buses, "_update_bus" , get_index()); |
441 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
442 | ur->commit_action(); |
443 | |
444 | updating_bus = false; |
445 | } |
446 | |
447 | void EditorAudioBus::_mute_toggled() { |
448 | updating_bus = true; |
449 | |
450 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
451 | ur->create_action(TTR("Toggle Audio Bus Mute" )); |
452 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_mute" , get_index(), mute->is_pressed()); |
453 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_mute" , get_index(), AudioServer::get_singleton()->is_bus_mute(get_index())); |
454 | ur->add_do_method(buses, "_update_bus" , get_index()); |
455 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
456 | ur->commit_action(); |
457 | |
458 | updating_bus = false; |
459 | } |
460 | |
461 | void EditorAudioBus::_bypass_toggled() { |
462 | updating_bus = true; |
463 | |
464 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
465 | ur->create_action(TTR("Toggle Audio Bus Bypass Effects" )); |
466 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_bypass_effects" , get_index(), bypass->is_pressed()); |
467 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_bypass_effects" , get_index(), AudioServer::get_singleton()->is_bus_bypassing_effects(get_index())); |
468 | ur->add_do_method(buses, "_update_bus" , get_index()); |
469 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
470 | ur->commit_action(); |
471 | |
472 | updating_bus = false; |
473 | } |
474 | |
475 | void EditorAudioBus::_send_selected(int p_which) { |
476 | updating_bus = true; |
477 | |
478 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
479 | ur->create_action(TTR("Select Audio Bus Send" )); |
480 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_send" , get_index(), send->get_item_text(p_which)); |
481 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_send" , get_index(), AudioServer::get_singleton()->get_bus_send(get_index())); |
482 | ur->add_do_method(buses, "_update_bus" , get_index()); |
483 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
484 | ur->commit_action(); |
485 | |
486 | updating_bus = false; |
487 | } |
488 | |
489 | void EditorAudioBus::_effect_selected() { |
490 | TreeItem *effect = effects->get_selected(); |
491 | if (!effect) { |
492 | return; |
493 | } |
494 | updating_bus = true; |
495 | |
496 | if (effect->get_metadata(0) != Variant()) { |
497 | int index = effect->get_metadata(0); |
498 | Ref<AudioEffect> effect2 = AudioServer::get_singleton()->get_bus_effect(get_index(), index); |
499 | if (effect2.is_valid()) { |
500 | EditorNode::get_singleton()->push_item(effect2.ptr()); |
501 | } |
502 | } |
503 | |
504 | updating_bus = false; |
505 | } |
506 | |
507 | void EditorAudioBus::_effect_edited() { |
508 | if (updating_bus) { |
509 | return; |
510 | } |
511 | |
512 | TreeItem *effect = effects->get_edited(); |
513 | if (!effect) { |
514 | return; |
515 | } |
516 | |
517 | if (effect->get_metadata(0) == Variant()) { |
518 | Rect2 area = effects->get_item_rect(effect); |
519 | |
520 | effect_options->set_position(effects->get_screen_position() + area.position + Vector2(0, area.size.y)); |
521 | effect_options->reset_size(); |
522 | effect_options->popup(); |
523 | //add effect |
524 | } else { |
525 | int index = effect->get_metadata(0); |
526 | updating_bus = true; |
527 | |
528 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
529 | ur->create_action(TTR("Select Audio Bus Send" )); |
530 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_effect_enabled" , get_index(), index, effect->is_checked(0)); |
531 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_effect_enabled" , get_index(), index, AudioServer::get_singleton()->is_bus_effect_enabled(get_index(), index)); |
532 | ur->add_do_method(buses, "_update_bus" , get_index()); |
533 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
534 | ur->commit_action(); |
535 | |
536 | updating_bus = false; |
537 | } |
538 | } |
539 | |
540 | void EditorAudioBus::_effect_add(int p_which) { |
541 | if (updating_bus) { |
542 | return; |
543 | } |
544 | |
545 | StringName name = effect_options->get_item_metadata(p_which); |
546 | |
547 | Object *fx = ClassDB::instantiate(name); |
548 | ERR_FAIL_NULL(fx); |
549 | AudioEffect *afx = Object::cast_to<AudioEffect>(fx); |
550 | ERR_FAIL_NULL(afx); |
551 | Ref<AudioEffect> afxr = Ref<AudioEffect>(afx); |
552 | |
553 | afxr->set_name(effect_options->get_item_text(p_which)); |
554 | |
555 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
556 | ur->create_action(TTR("Add Audio Bus Effect" )); |
557 | ur->add_do_method(AudioServer::get_singleton(), "add_bus_effect" , get_index(), afxr, -1); |
558 | ur->add_undo_method(AudioServer::get_singleton(), "remove_bus_effect" , get_index(), AudioServer::get_singleton()->get_bus_effect_count(get_index())); |
559 | ur->add_do_method(buses, "_update_bus" , get_index()); |
560 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
561 | ur->commit_action(); |
562 | } |
563 | |
564 | void EditorAudioBus::gui_input(const Ref<InputEvent> &p_event) { |
565 | ERR_FAIL_COND(p_event.is_null()); |
566 | |
567 | Ref<InputEventMouseButton> mb = p_event; |
568 | if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { |
569 | bus_popup->set_position(get_screen_position() + mb->get_position()); |
570 | bus_popup->reset_size(); |
571 | bus_popup->popup(); |
572 | } |
573 | } |
574 | |
575 | void EditorAudioBus::_effects_gui_input(Ref<InputEvent> p_event) { |
576 | Ref<InputEventKey> k = p_event; |
577 | if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == Key::KEY_DELETE) { |
578 | TreeItem *current_effect = effects->get_selected(); |
579 | if (current_effect && current_effect->get_metadata(0).get_type() == Variant::INT) { |
580 | _delete_effect_pressed(0); |
581 | accept_event(); |
582 | } |
583 | } |
584 | } |
585 | |
586 | void EditorAudioBus::(int p_option) { |
587 | if (p_option == 2) { |
588 | // Reset volume |
589 | emit_signal(SNAME("vol_reset_request" )); |
590 | } else if (p_option == 1) { |
591 | emit_signal(SNAME("delete_request" )); |
592 | } else if (p_option == 0) { |
593 | //duplicate |
594 | emit_signal(SNAME("duplicate_request" ), get_index()); |
595 | } |
596 | } |
597 | |
598 | Variant EditorAudioBus::get_drag_data(const Point2 &p_point) { |
599 | if (get_index() == 0) { |
600 | return Variant(); |
601 | } |
602 | |
603 | Control *c = memnew(Control); |
604 | Panel *p = memnew(Panel); |
605 | c->add_child(p); |
606 | p->set_modulate(Color(1, 1, 1, 0.7)); |
607 | p->add_theme_style_override("panel" , get_theme_stylebox(SNAME("focus" ), SNAME("Button" ))); |
608 | p->set_size(get_size()); |
609 | p->set_position(-p_point); |
610 | set_drag_preview(c); |
611 | Dictionary d; |
612 | d["type" ] = "move_audio_bus" ; |
613 | d["index" ] = get_index(); |
614 | |
615 | if (get_index() < AudioServer::get_singleton()->get_bus_count() - 1) { |
616 | emit_signal(SNAME("drop_end_request" )); |
617 | } |
618 | |
619 | return d; |
620 | } |
621 | |
622 | bool EditorAudioBus::can_drop_data(const Point2 &p_point, const Variant &p_data) const { |
623 | if (get_index() == 0) { |
624 | return false; |
625 | } |
626 | |
627 | Dictionary d = p_data; |
628 | if (d.has("type" ) && String(d["type" ]) == "move_audio_bus" && (int)d["index" ] != get_index()) { |
629 | hovering_drop = true; |
630 | return true; |
631 | } |
632 | |
633 | return false; |
634 | } |
635 | |
636 | void EditorAudioBus::drop_data(const Point2 &p_point, const Variant &p_data) { |
637 | Dictionary d = p_data; |
638 | emit_signal(SNAME("dropped" ), d["index" ], get_index()); |
639 | } |
640 | |
641 | Variant EditorAudioBus::get_drag_data_fw(const Point2 &p_point, Control *p_from) { |
642 | TreeItem *item = effects->get_item_at_position(p_point); |
643 | if (!item) { |
644 | return Variant(); |
645 | } |
646 | |
647 | Variant md = item->get_metadata(0); |
648 | if (md.get_type() == Variant::INT) { |
649 | Dictionary fxd; |
650 | fxd["type" ] = "audio_bus_effect" ; |
651 | fxd["bus" ] = get_index(); |
652 | fxd["effect" ] = md; |
653 | |
654 | Label *l = memnew(Label); |
655 | l->set_text(item->get_text(0)); |
656 | effects->set_drag_preview(l); |
657 | |
658 | return fxd; |
659 | } |
660 | |
661 | return Variant(); |
662 | } |
663 | |
664 | bool EditorAudioBus::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { |
665 | Dictionary d = p_data; |
666 | if (!d.has("type" ) || String(d["type" ]) != "audio_bus_effect" ) { |
667 | return false; |
668 | } |
669 | |
670 | TreeItem *item = effects->get_item_at_position(p_point); |
671 | if (!item) { |
672 | return false; |
673 | } |
674 | |
675 | effects->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); |
676 | |
677 | return true; |
678 | } |
679 | |
680 | void EditorAudioBus::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { |
681 | Dictionary d = p_data; |
682 | |
683 | TreeItem *item = effects->get_item_at_position(p_point); |
684 | if (!item) { |
685 | return; |
686 | } |
687 | int pos = effects->get_drop_section_at_position(p_point); |
688 | Variant md = item->get_metadata(0); |
689 | |
690 | int paste_at; |
691 | int bus = d["bus" ]; |
692 | int effect = d["effect" ]; |
693 | |
694 | if (md.get_type() == Variant::INT) { |
695 | paste_at = md; |
696 | if (pos > 0) { |
697 | paste_at++; |
698 | } |
699 | |
700 | if (bus == get_index() && paste_at > effect) { |
701 | paste_at--; |
702 | } |
703 | } else { |
704 | paste_at = -1; |
705 | } |
706 | |
707 | bool enabled = AudioServer::get_singleton()->is_bus_effect_enabled(bus, effect); |
708 | |
709 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
710 | ur->create_action(TTR("Move Bus Effect" )); |
711 | ur->add_do_method(AudioServer::get_singleton(), "remove_bus_effect" , bus, effect); |
712 | ur->add_do_method(AudioServer::get_singleton(), "add_bus_effect" , get_index(), AudioServer::get_singleton()->get_bus_effect(bus, effect), paste_at); |
713 | |
714 | if (paste_at == -1) { |
715 | paste_at = AudioServer::get_singleton()->get_bus_effect_count(get_index()); |
716 | if (bus == get_index()) { |
717 | paste_at--; |
718 | } |
719 | } |
720 | if (!enabled) { |
721 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_effect_enabled" , get_index(), paste_at, false); |
722 | } |
723 | |
724 | ur->add_undo_method(AudioServer::get_singleton(), "remove_bus_effect" , get_index(), paste_at); |
725 | ur->add_undo_method(AudioServer::get_singleton(), "add_bus_effect" , bus, AudioServer::get_singleton()->get_bus_effect(bus, effect), effect); |
726 | if (!enabled) { |
727 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_effect_enabled" , bus, effect, false); |
728 | } |
729 | |
730 | ur->add_do_method(buses, "_update_bus" , get_index()); |
731 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
732 | if (get_index() != bus) { |
733 | ur->add_do_method(buses, "_update_bus" , bus); |
734 | ur->add_undo_method(buses, "_update_bus" , bus); |
735 | } |
736 | ur->commit_action(); |
737 | } |
738 | |
739 | void EditorAudioBus::_delete_effect_pressed(int p_option) { |
740 | TreeItem *item = effects->get_selected(); |
741 | if (!item) { |
742 | return; |
743 | } |
744 | |
745 | if (item->get_metadata(0).get_type() != Variant::INT) { |
746 | return; |
747 | } |
748 | |
749 | int index = item->get_metadata(0); |
750 | |
751 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
752 | ur->create_action(TTR("Delete Bus Effect" )); |
753 | ur->add_do_method(AudioServer::get_singleton(), "remove_bus_effect" , get_index(), index); |
754 | ur->add_undo_method(AudioServer::get_singleton(), "add_bus_effect" , get_index(), AudioServer::get_singleton()->get_bus_effect(get_index(), index), index); |
755 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_effect_enabled" , get_index(), index, AudioServer::get_singleton()->is_bus_effect_enabled(get_index(), index)); |
756 | ur->add_do_method(buses, "_update_bus" , get_index()); |
757 | ur->add_undo_method(buses, "_update_bus" , get_index()); |
758 | ur->commit_action(); |
759 | } |
760 | |
761 | void EditorAudioBus::_effect_rmb(const Vector2 &p_pos, MouseButton p_button) { |
762 | if (p_button != MouseButton::RIGHT) { |
763 | return; |
764 | } |
765 | |
766 | TreeItem *item = effects->get_selected(); |
767 | if (!item) { |
768 | return; |
769 | } |
770 | |
771 | if (item->get_metadata(0).get_type() != Variant::INT) { |
772 | return; |
773 | } |
774 | |
775 | delete_effect_popup->set_position(get_screen_position() + get_local_mouse_position()); |
776 | delete_effect_popup->reset_size(); |
777 | delete_effect_popup->popup(); |
778 | } |
779 | |
780 | void EditorAudioBus::_bind_methods() { |
781 | ClassDB::bind_method("update_bus" , &EditorAudioBus::update_bus); |
782 | ClassDB::bind_method("update_send" , &EditorAudioBus::update_send); |
783 | |
784 | ADD_SIGNAL(MethodInfo("duplicate_request" )); |
785 | ADD_SIGNAL(MethodInfo("delete_request" )); |
786 | ADD_SIGNAL(MethodInfo("vol_reset_request" )); |
787 | ADD_SIGNAL(MethodInfo("drop_end_request" )); |
788 | ADD_SIGNAL(MethodInfo("dropped" )); |
789 | } |
790 | |
791 | EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { |
792 | buses = p_buses; |
793 | is_master = p_is_master; |
794 | |
795 | set_tooltip_text(TTR("Drag & drop to rearrange." )); |
796 | |
797 | VBoxContainer *vb = memnew(VBoxContainer); |
798 | add_child(vb); |
799 | |
800 | set_v_size_flags(SIZE_EXPAND_FILL); |
801 | |
802 | track_name = memnew(LineEdit); |
803 | track_name->connect("text_submitted" , callable_mp(this, &EditorAudioBus::_name_changed)); |
804 | track_name->connect("focus_exited" , callable_mp(this, &EditorAudioBus::_name_focus_exit)); |
805 | vb->add_child(track_name); |
806 | |
807 | HBoxContainer *hbc = memnew(HBoxContainer); |
808 | vb->add_child(hbc); |
809 | solo = memnew(Button); |
810 | solo->set_flat(true); |
811 | solo->set_toggle_mode(true); |
812 | solo->set_tooltip_text(TTR("Solo" )); |
813 | solo->set_focus_mode(FOCUS_NONE); |
814 | solo->connect("pressed" , callable_mp(this, &EditorAudioBus::_solo_toggled)); |
815 | hbc->add_child(solo); |
816 | mute = memnew(Button); |
817 | mute->set_flat(true); |
818 | mute->set_toggle_mode(true); |
819 | mute->set_tooltip_text(TTR("Mute" )); |
820 | mute->set_focus_mode(FOCUS_NONE); |
821 | mute->connect("pressed" , callable_mp(this, &EditorAudioBus::_mute_toggled)); |
822 | hbc->add_child(mute); |
823 | bypass = memnew(Button); |
824 | bypass->set_flat(true); |
825 | bypass->set_toggle_mode(true); |
826 | bypass->set_tooltip_text(TTR("Bypass" )); |
827 | bypass->set_focus_mode(FOCUS_NONE); |
828 | bypass->connect("pressed" , callable_mp(this, &EditorAudioBus::_bypass_toggled)); |
829 | hbc->add_child(bypass); |
830 | hbc->add_spacer(); |
831 | |
832 | Ref<StyleBoxEmpty> sbempty = memnew(StyleBoxEmpty); |
833 | for (int i = 0; i < hbc->get_child_count(); i++) { |
834 | Control *child = Object::cast_to<Control>(hbc->get_child(i)); |
835 | child->add_theme_style_override("normal" , sbempty); |
836 | child->add_theme_style_override("hover" , sbempty); |
837 | child->add_theme_style_override("focus" , sbempty); |
838 | child->add_theme_style_override("pressed" , sbempty); |
839 | } |
840 | |
841 | HSeparator *separator = memnew(HSeparator); |
842 | separator->set_mouse_filter(MOUSE_FILTER_PASS); |
843 | vb->add_child(separator); |
844 | |
845 | HBoxContainer *hb = memnew(HBoxContainer); |
846 | vb->add_child(hb); |
847 | slider = memnew(VSlider); |
848 | slider->set_min(0.0); |
849 | slider->set_max(1.0); |
850 | slider->set_step(0.0001); |
851 | slider->set_clip_contents(false); |
852 | |
853 | audio_value_preview_box = memnew(Panel); |
854 | slider->add_child(audio_value_preview_box); |
855 | audio_value_preview_box->set_as_top_level(true); |
856 | audio_value_preview_box->set_mouse_filter(MOUSE_FILTER_PASS); |
857 | audio_value_preview_box->hide(); |
858 | |
859 | HBoxContainer *audioprev_hbc = memnew(HBoxContainer); |
860 | audioprev_hbc->set_v_size_flags(SIZE_EXPAND_FILL); |
861 | audioprev_hbc->set_h_size_flags(SIZE_EXPAND_FILL); |
862 | audio_value_preview_box->add_child(audioprev_hbc); |
863 | |
864 | audio_value_preview_label = memnew(Label); |
865 | audio_value_preview_label->set_v_size_flags(SIZE_EXPAND_FILL); |
866 | audio_value_preview_label->set_h_size_flags(SIZE_EXPAND_FILL); |
867 | audio_value_preview_label->set_mouse_filter(MOUSE_FILTER_PASS); |
868 | audioprev_hbc->add_child(audio_value_preview_label); |
869 | |
870 | preview_timer = memnew(Timer); |
871 | preview_timer->set_wait_time(0.8f); |
872 | preview_timer->set_one_shot(true); |
873 | add_child(preview_timer); |
874 | |
875 | slider->connect("value_changed" , callable_mp(this, &EditorAudioBus::_volume_changed)); |
876 | slider->connect("value_changed" , callable_mp(this, &EditorAudioBus::_show_value)); |
877 | preview_timer->connect("timeout" , callable_mp(this, &EditorAudioBus::_hide_value_preview)); |
878 | hb->add_child(slider); |
879 | |
880 | cc = 0; |
881 | for (int i = 0; i < CHANNELS_MAX; i++) { |
882 | channel[i].vu_l = memnew(TextureProgressBar); |
883 | channel[i].vu_l->set_fill_mode(TextureProgressBar::FILL_BOTTOM_TO_TOP); |
884 | hb->add_child(channel[i].vu_l); |
885 | channel[i].vu_l->set_min(-80); |
886 | channel[i].vu_l->set_max(24); |
887 | channel[i].vu_l->set_step(0.1); |
888 | |
889 | channel[i].vu_r = memnew(TextureProgressBar); |
890 | channel[i].vu_r->set_fill_mode(TextureProgressBar::FILL_BOTTOM_TO_TOP); |
891 | hb->add_child(channel[i].vu_r); |
892 | channel[i].vu_r->set_min(-80); |
893 | channel[i].vu_r->set_max(24); |
894 | channel[i].vu_r->set_step(0.1); |
895 | |
896 | channel[i].peak_l = 0.0f; |
897 | channel[i].peak_r = 0.0f; |
898 | } |
899 | |
900 | EditorAudioMeterNotches *scale = memnew(EditorAudioMeterNotches); |
901 | |
902 | for (float db = 6.0f; db >= -80.0f; db -= 6.0f) { |
903 | bool renderNotch = (db >= -6.0f || db == -24.0f || db == -72.0f); |
904 | scale->add_notch(_scaled_db_to_normalized_volume(db), db, renderNotch); |
905 | } |
906 | scale->set_mouse_filter(MOUSE_FILTER_PASS); |
907 | hb->add_child(scale); |
908 | |
909 | effects = memnew(Tree); |
910 | effects->set_hide_root(true); |
911 | effects->set_custom_minimum_size(Size2(0, 80) * EDSCALE); |
912 | effects->set_hide_folding(true); |
913 | effects->set_v_size_flags(SIZE_EXPAND_FILL); |
914 | vb->add_child(effects); |
915 | effects->connect("item_edited" , callable_mp(this, &EditorAudioBus::_effect_edited)); |
916 | effects->connect("cell_selected" , callable_mp(this, &EditorAudioBus::_effect_selected)); |
917 | effects->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); |
918 | SET_DRAG_FORWARDING_GCD(effects, EditorAudioBus); |
919 | effects->connect("item_mouse_selected" , callable_mp(this, &EditorAudioBus::_effect_rmb)); |
920 | effects->set_allow_rmb_select(true); |
921 | effects->set_focus_mode(FOCUS_CLICK); |
922 | effects->set_allow_reselect(true); |
923 | effects->connect("gui_input" , callable_mp(this, &EditorAudioBus::_effects_gui_input)); |
924 | |
925 | send = memnew(OptionButton); |
926 | send->set_clip_text(true); |
927 | send->connect("item_selected" , callable_mp(this, &EditorAudioBus::_send_selected)); |
928 | vb->add_child(send); |
929 | |
930 | set_focus_mode(FOCUS_CLICK); |
931 | |
932 | effect_options = memnew(PopupMenu); |
933 | effect_options->connect("index_pressed" , callable_mp(this, &EditorAudioBus::_effect_add)); |
934 | add_child(effect_options); |
935 | List<StringName> effect_list; |
936 | ClassDB::get_inheriters_from_class("AudioEffect" , &effect_list); |
937 | effect_list.sort_custom<StringName::AlphCompare>(); |
938 | for (const StringName &E : effect_list) { |
939 | if (!ClassDB::can_instantiate(E) || ClassDB::is_virtual(E)) { |
940 | continue; |
941 | } |
942 | |
943 | String name = E.operator String().replace("AudioEffect" , "" ); |
944 | effect_options->add_item(name); |
945 | effect_options->set_item_metadata(-1, E); |
946 | } |
947 | |
948 | bus_options = memnew(MenuButton); |
949 | bus_options->set_shortcut_context(this); |
950 | bus_options->set_h_size_flags(SIZE_SHRINK_END); |
951 | bus_options->set_anchor(SIDE_RIGHT, 0.0); |
952 | bus_options->set_tooltip_text(TTR("Bus Options" )); |
953 | hbc->add_child(bus_options); |
954 | |
955 | bus_popup = bus_options->get_popup(); |
956 | bus_popup->add_shortcut(ED_SHORTCUT("audio_bus_editor/duplicate_selected_bus" , TTR("Duplicate Bus" ), KeyModifierMask::CMD_OR_CTRL | Key::D)); |
957 | bus_popup->add_shortcut(ED_SHORTCUT("audio_bus_editor/delete_selected_bus" , TTR("Delete Bus" ), Key::KEY_DELETE)); |
958 | bus_popup->set_item_disabled(1, is_master); |
959 | bus_popup->add_item(TTR("Reset Volume" )); |
960 | bus_popup->connect("index_pressed" , callable_mp(this, &EditorAudioBus::_bus_popup_pressed)); |
961 | |
962 | delete_effect_popup = memnew(PopupMenu); |
963 | delete_effect_popup->add_item(TTR("Delete Effect" )); |
964 | add_child(delete_effect_popup); |
965 | delete_effect_popup->connect("index_pressed" , callable_mp(this, &EditorAudioBus::_delete_effect_pressed)); |
966 | } |
967 | |
968 | void EditorAudioBusDrop::_notification(int p_what) { |
969 | switch (p_what) { |
970 | case NOTIFICATION_DRAW: { |
971 | draw_style_box(get_theme_stylebox(SNAME("normal" ), SNAME("Button" )), Rect2(Vector2(), get_size())); |
972 | |
973 | if (hovering_drop) { |
974 | Color accent = get_theme_color(SNAME("accent_color" ), EditorStringName(Editor)); |
975 | accent.a *= 0.7; |
976 | draw_rect(Rect2(Point2(), get_size()), accent, false); |
977 | } |
978 | } break; |
979 | |
980 | case NOTIFICATION_MOUSE_ENTER: { |
981 | if (!hovering_drop) { |
982 | hovering_drop = true; |
983 | queue_redraw(); |
984 | } |
985 | } break; |
986 | |
987 | case NOTIFICATION_MOUSE_EXIT: |
988 | case NOTIFICATION_DRAG_END: { |
989 | if (hovering_drop) { |
990 | hovering_drop = false; |
991 | queue_redraw(); |
992 | } |
993 | } break; |
994 | } |
995 | } |
996 | |
997 | bool EditorAudioBusDrop::can_drop_data(const Point2 &p_point, const Variant &p_data) const { |
998 | Dictionary d = p_data; |
999 | return (d.has("type" ) && String(d["type" ]) == "move_audio_bus" ); |
1000 | } |
1001 | |
1002 | void EditorAudioBusDrop::drop_data(const Point2 &p_point, const Variant &p_data) { |
1003 | Dictionary d = p_data; |
1004 | emit_signal(SNAME("dropped" ), d["index" ], AudioServer::get_singleton()->get_bus_count()); |
1005 | } |
1006 | |
1007 | void EditorAudioBusDrop::_bind_methods() { |
1008 | ADD_SIGNAL(MethodInfo("dropped" )); |
1009 | } |
1010 | |
1011 | EditorAudioBusDrop::EditorAudioBusDrop() { |
1012 | } |
1013 | |
1014 | void EditorAudioBuses::_set_renaming_buses(bool p_renaming) { |
1015 | renaming_buses = p_renaming; |
1016 | } |
1017 | |
1018 | void EditorAudioBuses::_update_buses() { |
1019 | if (renaming_buses) { |
1020 | // This case will be handled more gracefully, no need to trigger a full rebuild. |
1021 | // This is possibly a mistake in the AudioServer, which fires bus_layout_changed |
1022 | // on a rename. This may not be intended, but no way to tell at the moment. |
1023 | return; |
1024 | } |
1025 | |
1026 | for (int i = bus_hb->get_child_count() - 1; i >= 0; i--) { |
1027 | EditorAudioBus *audio_bus = Object::cast_to<EditorAudioBus>(bus_hb->get_child(i)); |
1028 | if (audio_bus) { |
1029 | bus_hb->remove_child(audio_bus); |
1030 | audio_bus->queue_free(); |
1031 | } |
1032 | } |
1033 | |
1034 | if (drop_end) { |
1035 | bus_hb->remove_child(drop_end); |
1036 | drop_end->queue_free(); |
1037 | drop_end = nullptr; |
1038 | } |
1039 | |
1040 | for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { |
1041 | bool is_master = (i == 0); |
1042 | EditorAudioBus *audio_bus = memnew(EditorAudioBus(this, is_master)); |
1043 | bus_hb->add_child(audio_bus); |
1044 | audio_bus->connect("delete_request" , callable_mp(this, &EditorAudioBuses::_delete_bus).bind(audio_bus), CONNECT_DEFERRED); |
1045 | audio_bus->connect("duplicate_request" , callable_mp(this, &EditorAudioBuses::_duplicate_bus), CONNECT_DEFERRED); |
1046 | audio_bus->connect("vol_reset_request" , callable_mp(this, &EditorAudioBuses::_reset_bus_volume).bind(audio_bus), CONNECT_DEFERRED); |
1047 | audio_bus->connect("drop_end_request" , callable_mp(this, &EditorAudioBuses::_request_drop_end)); |
1048 | audio_bus->connect("dropped" , callable_mp(this, &EditorAudioBuses::_drop_at_index), CONNECT_DEFERRED); |
1049 | } |
1050 | } |
1051 | |
1052 | EditorAudioBuses *EditorAudioBuses::register_editor() { |
1053 | EditorAudioBuses *audio_buses = memnew(EditorAudioBuses); |
1054 | EditorNode::get_singleton()->add_bottom_panel_item(TTR("Audio" ), audio_buses); |
1055 | return audio_buses; |
1056 | } |
1057 | |
1058 | void EditorAudioBuses::_notification(int p_what) { |
1059 | switch (p_what) { |
1060 | case NOTIFICATION_ENTER_TREE: |
1061 | case NOTIFICATION_THEME_CHANGED: { |
1062 | bus_scroll->add_theme_style_override("panel" , get_theme_stylebox(SNAME("panel" ), SNAME("Tree" ))); |
1063 | } break; |
1064 | |
1065 | case NOTIFICATION_READY: { |
1066 | _update_buses(); |
1067 | } break; |
1068 | |
1069 | case NOTIFICATION_DRAG_END: { |
1070 | if (drop_end) { |
1071 | bus_hb->remove_child(drop_end); |
1072 | drop_end->queue_free(); |
1073 | drop_end = nullptr; |
1074 | } |
1075 | } break; |
1076 | |
1077 | case NOTIFICATION_PROCESS: { |
1078 | // Check if anything was edited. |
1079 | bool edited = AudioServer::get_singleton()->is_edited(); |
1080 | for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { |
1081 | for (int j = 0; j < AudioServer::get_singleton()->get_bus_effect_count(i); j++) { |
1082 | Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(i, j); |
1083 | if (effect->is_edited()) { |
1084 | edited = true; |
1085 | effect->set_edited(false); |
1086 | } |
1087 | } |
1088 | } |
1089 | |
1090 | AudioServer::get_singleton()->set_edited(false); |
1091 | |
1092 | if (edited) { |
1093 | save_timer->start(); |
1094 | } |
1095 | } break; |
1096 | } |
1097 | } |
1098 | |
1099 | void EditorAudioBuses::_add_bus() { |
1100 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
1101 | |
1102 | ur->create_action(TTR("Add Audio Bus" )); |
1103 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_count" , AudioServer::get_singleton()->get_bus_count() + 1); |
1104 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_count" , AudioServer::get_singleton()->get_bus_count()); |
1105 | ur->add_do_method(this, "_update_buses" ); |
1106 | ur->add_undo_method(this, "_update_buses" ); |
1107 | ur->commit_action(); |
1108 | } |
1109 | |
1110 | void EditorAudioBuses::_update_bus(int p_index) { |
1111 | if (p_index >= bus_hb->get_child_count()) { |
1112 | return; |
1113 | } |
1114 | |
1115 | bus_hb->get_child(p_index)->call("update_bus" ); |
1116 | } |
1117 | |
1118 | void EditorAudioBuses::_update_sends() { |
1119 | for (int i = 0; i < bus_hb->get_child_count(); i++) { |
1120 | bus_hb->get_child(i)->call("update_send" ); |
1121 | } |
1122 | } |
1123 | |
1124 | void EditorAudioBuses::_delete_bus(Object *p_which) { |
1125 | EditorAudioBus *bus = Object::cast_to<EditorAudioBus>(p_which); |
1126 | int index = bus->get_index(); |
1127 | if (index == 0) { |
1128 | EditorNode::get_singleton()->show_warning(TTR("Master bus can't be deleted!" )); |
1129 | return; |
1130 | } |
1131 | |
1132 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
1133 | |
1134 | ur->create_action(TTR("Delete Audio Bus" )); |
1135 | ur->add_do_method(AudioServer::get_singleton(), "remove_bus" , index); |
1136 | ur->add_undo_method(AudioServer::get_singleton(), "add_bus" , index); |
1137 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_name" , index, AudioServer::get_singleton()->get_bus_name(index)); |
1138 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_volume_db" , index, AudioServer::get_singleton()->get_bus_volume_db(index)); |
1139 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_send" , index, AudioServer::get_singleton()->get_bus_send(index)); |
1140 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_solo" , index, AudioServer::get_singleton()->is_bus_solo(index)); |
1141 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_mute" , index, AudioServer::get_singleton()->is_bus_mute(index)); |
1142 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_bypass_effects" , index, AudioServer::get_singleton()->is_bus_bypassing_effects(index)); |
1143 | for (int i = 0; i < AudioServer::get_singleton()->get_bus_effect_count(index); i++) { |
1144 | ur->add_undo_method(AudioServer::get_singleton(), "add_bus_effect" , index, AudioServer::get_singleton()->get_bus_effect(index, i)); |
1145 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_effect_enabled" , index, i, AudioServer::get_singleton()->is_bus_effect_enabled(index, i)); |
1146 | } |
1147 | ur->add_do_method(this, "_update_buses" ); |
1148 | ur->add_undo_method(this, "_update_buses" ); |
1149 | ur->commit_action(); |
1150 | } |
1151 | |
1152 | void EditorAudioBuses::_duplicate_bus(int p_which) { |
1153 | int add_at_pos = p_which + 1; |
1154 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
1155 | ur->create_action(TTR("Duplicate Audio Bus" )); |
1156 | ur->add_do_method(AudioServer::get_singleton(), "add_bus" , add_at_pos); |
1157 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_name" , add_at_pos, AudioServer::get_singleton()->get_bus_name(p_which) + " Copy" ); |
1158 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_volume_db" , add_at_pos, AudioServer::get_singleton()->get_bus_volume_db(p_which)); |
1159 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_send" , add_at_pos, AudioServer::get_singleton()->get_bus_send(p_which)); |
1160 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_solo" , add_at_pos, AudioServer::get_singleton()->is_bus_solo(p_which)); |
1161 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_mute" , add_at_pos, AudioServer::get_singleton()->is_bus_mute(p_which)); |
1162 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_bypass_effects" , add_at_pos, AudioServer::get_singleton()->is_bus_bypassing_effects(p_which)); |
1163 | for (int i = 0; i < AudioServer::get_singleton()->get_bus_effect_count(p_which); i++) { |
1164 | ur->add_do_method(AudioServer::get_singleton(), "add_bus_effect" , add_at_pos, AudioServer::get_singleton()->get_bus_effect(p_which, i)); |
1165 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_effect_enabled" , add_at_pos, i, AudioServer::get_singleton()->is_bus_effect_enabled(p_which, i)); |
1166 | } |
1167 | ur->add_undo_method(AudioServer::get_singleton(), "remove_bus" , add_at_pos); |
1168 | ur->add_do_method(this, "_update_buses" ); |
1169 | ur->add_undo_method(this, "_update_buses" ); |
1170 | ur->commit_action(); |
1171 | } |
1172 | |
1173 | void EditorAudioBuses::_reset_bus_volume(Object *p_which) { |
1174 | EditorAudioBus *bus = Object::cast_to<EditorAudioBus>(p_which); |
1175 | int index = bus->get_index(); |
1176 | |
1177 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
1178 | ur->create_action(TTR("Reset Bus Volume" )); |
1179 | ur->add_do_method(AudioServer::get_singleton(), "set_bus_volume_db" , index, 0.f); |
1180 | ur->add_undo_method(AudioServer::get_singleton(), "set_bus_volume_db" , index, AudioServer::get_singleton()->get_bus_volume_db(index)); |
1181 | ur->add_do_method(this, "_update_buses" ); |
1182 | ur->add_undo_method(this, "_update_buses" ); |
1183 | ur->commit_action(); |
1184 | } |
1185 | |
1186 | void EditorAudioBuses::_request_drop_end() { |
1187 | if (!drop_end && bus_hb->get_child_count()) { |
1188 | drop_end = memnew(EditorAudioBusDrop); |
1189 | |
1190 | bus_hb->add_child(drop_end); |
1191 | drop_end->set_custom_minimum_size(Object::cast_to<Control>(bus_hb->get_child(0))->get_size()); |
1192 | drop_end->connect("dropped" , callable_mp(this, &EditorAudioBuses::_drop_at_index), CONNECT_DEFERRED); |
1193 | } |
1194 | } |
1195 | |
1196 | void EditorAudioBuses::_drop_at_index(int p_bus, int p_index) { |
1197 | EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); |
1198 | ur->create_action(TTR("Move Audio Bus" )); |
1199 | |
1200 | ur->add_do_method(AudioServer::get_singleton(), "move_bus" , p_bus, p_index); |
1201 | int real_bus = p_index > p_bus ? p_bus : p_bus + 1; |
1202 | int real_index = p_index > p_bus ? p_index - 1 : p_index; |
1203 | ur->add_undo_method(AudioServer::get_singleton(), "move_bus" , real_index, real_bus); |
1204 | |
1205 | ur->add_do_method(this, "_update_buses" ); |
1206 | ur->add_undo_method(this, "_update_buses" ); |
1207 | ur->commit_action(); |
1208 | } |
1209 | |
1210 | void EditorAudioBuses::_server_save() { |
1211 | Ref<AudioBusLayout> state = AudioServer::get_singleton()->generate_bus_layout(); |
1212 | ResourceSaver::save(state, edited_path); |
1213 | } |
1214 | |
1215 | void EditorAudioBuses::_select_layout() { |
1216 | FileSystemDock::get_singleton()->select_file(edited_path); |
1217 | } |
1218 | |
1219 | void EditorAudioBuses::_save_as_layout() { |
1220 | file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); |
1221 | file_dialog->set_title(TTR("Save Audio Bus Layout As..." )); |
1222 | file_dialog->set_current_path(edited_path); |
1223 | file_dialog->popup_file_dialog(); |
1224 | new_layout = false; |
1225 | } |
1226 | |
1227 | void EditorAudioBuses::_new_layout() { |
1228 | file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); |
1229 | file_dialog->set_title(TTR("Location for New Layout..." )); |
1230 | file_dialog->set_current_path(edited_path); |
1231 | file_dialog->popup_file_dialog(); |
1232 | new_layout = true; |
1233 | } |
1234 | |
1235 | void EditorAudioBuses::_load_layout() { |
1236 | file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); |
1237 | file_dialog->set_title(TTR("Open Audio Bus Layout" )); |
1238 | file_dialog->set_current_path(edited_path); |
1239 | file_dialog->popup_file_dialog(); |
1240 | new_layout = false; |
1241 | } |
1242 | |
1243 | void EditorAudioBuses::_load_default_layout() { |
1244 | String layout_path = GLOBAL_GET("audio/buses/default_bus_layout" ); |
1245 | |
1246 | Ref<AudioBusLayout> state = ResourceLoader::load(layout_path, "" , ResourceFormatLoader::CACHE_MODE_IGNORE); |
1247 | if (state.is_null()) { |
1248 | EditorNode::get_singleton()->show_warning(vformat(TTR("There is no '%s' file." ), layout_path)); |
1249 | return; |
1250 | } |
1251 | |
1252 | edited_path = layout_path; |
1253 | file->set_text(String(TTR("Layout:" )) + " " + layout_path.get_file()); |
1254 | AudioServer::get_singleton()->set_bus_layout(state); |
1255 | _update_buses(); |
1256 | EditorUndoRedoManager::get_singleton()->clear_history(true, EditorUndoRedoManager::GLOBAL_HISTORY); |
1257 | call_deferred(SNAME("_select_layout" )); |
1258 | } |
1259 | |
1260 | void EditorAudioBuses::_file_dialog_callback(const String &p_string) { |
1261 | if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_OPEN_FILE) { |
1262 | Ref<AudioBusLayout> state = ResourceLoader::load(p_string, "" , ResourceFormatLoader::CACHE_MODE_IGNORE); |
1263 | if (state.is_null()) { |
1264 | EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an audio bus layout." )); |
1265 | return; |
1266 | } |
1267 | |
1268 | edited_path = p_string; |
1269 | file->set_text(String(TTR("Layout:" )) + " " + p_string.get_file()); |
1270 | AudioServer::get_singleton()->set_bus_layout(state); |
1271 | _update_buses(); |
1272 | EditorUndoRedoManager::get_singleton()->clear_history(true, EditorUndoRedoManager::GLOBAL_HISTORY); |
1273 | call_deferred(SNAME("_select_layout" )); |
1274 | |
1275 | } else if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { |
1276 | if (new_layout) { |
1277 | Ref<AudioBusLayout> empty_state; |
1278 | empty_state.instantiate(); |
1279 | AudioServer::get_singleton()->set_bus_layout(empty_state); |
1280 | } |
1281 | |
1282 | Error err = ResourceSaver::save(AudioServer::get_singleton()->generate_bus_layout(), p_string); |
1283 | |
1284 | if (err != OK) { |
1285 | EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s" ), p_string)); |
1286 | return; |
1287 | } |
1288 | |
1289 | edited_path = p_string; |
1290 | file->set_text(String(TTR("Layout:" )) + " " + p_string.get_file()); |
1291 | _update_buses(); |
1292 | EditorUndoRedoManager::get_singleton()->clear_history(true, EditorUndoRedoManager::GLOBAL_HISTORY); |
1293 | call_deferred(SNAME("_select_layout" )); |
1294 | } |
1295 | } |
1296 | |
1297 | void EditorAudioBuses::_bind_methods() { |
1298 | ClassDB::bind_method("_set_renaming_buses" , &EditorAudioBuses::_set_renaming_buses); |
1299 | ClassDB::bind_method("_update_buses" , &EditorAudioBuses::_update_buses); |
1300 | ClassDB::bind_method("_update_bus" , &EditorAudioBuses::_update_bus); |
1301 | ClassDB::bind_method("_update_sends" , &EditorAudioBuses::_update_sends); |
1302 | ClassDB::bind_method("_select_layout" , &EditorAudioBuses::_select_layout); |
1303 | } |
1304 | |
1305 | EditorAudioBuses::EditorAudioBuses() { |
1306 | top_hb = memnew(HBoxContainer); |
1307 | add_child(top_hb); |
1308 | |
1309 | file = memnew(Label); |
1310 | String layout_path = GLOBAL_GET("audio/buses/default_bus_layout" ); |
1311 | file->set_text(String(TTR("Layout:" )) + " " + layout_path.get_file()); |
1312 | file->set_clip_text(true); |
1313 | file->set_h_size_flags(SIZE_EXPAND_FILL); |
1314 | top_hb->add_child(file); |
1315 | |
1316 | add = memnew(Button); |
1317 | top_hb->add_child(add); |
1318 | add->set_text(TTR("Add Bus" )); |
1319 | add->set_tooltip_text(TTR("Add a new Audio Bus to this layout." )); |
1320 | add->connect("pressed" , callable_mp(this, &EditorAudioBuses::_add_bus)); |
1321 | |
1322 | VSeparator *separator = memnew(VSeparator); |
1323 | top_hb->add_child(separator); |
1324 | |
1325 | load = memnew(Button); |
1326 | load->set_text(TTR("Load" )); |
1327 | load->set_tooltip_text(TTR("Load an existing Bus Layout." )); |
1328 | top_hb->add_child(load); |
1329 | load->connect("pressed" , callable_mp(this, &EditorAudioBuses::_load_layout)); |
1330 | |
1331 | save_as = memnew(Button); |
1332 | save_as->set_text(TTR("Save As" )); |
1333 | save_as->set_tooltip_text(TTR("Save this Bus Layout to a file." )); |
1334 | top_hb->add_child(save_as); |
1335 | save_as->connect("pressed" , callable_mp(this, &EditorAudioBuses::_save_as_layout)); |
1336 | |
1337 | _default = memnew(Button); |
1338 | _default->set_text(TTR("Load Default" )); |
1339 | _default->set_tooltip_text(TTR("Load the default Bus Layout." )); |
1340 | top_hb->add_child(_default); |
1341 | _default->connect("pressed" , callable_mp(this, &EditorAudioBuses::_load_default_layout)); |
1342 | |
1343 | _new = memnew(Button); |
1344 | _new->set_text(TTR("Create" )); |
1345 | _new->set_tooltip_text(TTR("Create a new Bus Layout." )); |
1346 | top_hb->add_child(_new); |
1347 | _new->connect("pressed" , callable_mp(this, &EditorAudioBuses::_new_layout)); |
1348 | |
1349 | bus_scroll = memnew(ScrollContainer); |
1350 | bus_scroll->set_v_size_flags(SIZE_EXPAND_FILL); |
1351 | bus_scroll->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); |
1352 | add_child(bus_scroll); |
1353 | bus_hb = memnew(HBoxContainer); |
1354 | bus_hb->set_v_size_flags(SIZE_EXPAND_FILL); |
1355 | bus_scroll->add_child(bus_hb); |
1356 | |
1357 | save_timer = memnew(Timer); |
1358 | save_timer->set_wait_time(0.8); |
1359 | save_timer->set_one_shot(true); |
1360 | add_child(save_timer); |
1361 | save_timer->connect("timeout" , callable_mp(this, &EditorAudioBuses::_server_save)); |
1362 | |
1363 | set_v_size_flags(SIZE_EXPAND_FILL); |
1364 | |
1365 | edited_path = GLOBAL_GET("audio/buses/default_bus_layout" ); |
1366 | |
1367 | file_dialog = memnew(EditorFileDialog); |
1368 | List<String> ext; |
1369 | ResourceLoader::get_recognized_extensions_for_type("AudioBusLayout" , &ext); |
1370 | for (const String &E : ext) { |
1371 | file_dialog->add_filter("*." + E, TTR("Audio Bus Layout" )); |
1372 | } |
1373 | add_child(file_dialog); |
1374 | file_dialog->connect("file_selected" , callable_mp(this, &EditorAudioBuses::_file_dialog_callback)); |
1375 | |
1376 | AudioServer::get_singleton()->connect("bus_layout_changed" , callable_mp(this, &EditorAudioBuses::_update_buses)); |
1377 | |
1378 | set_process(true); |
1379 | } |
1380 | |
1381 | void EditorAudioBuses::open_layout(const String &p_path) { |
1382 | EditorNode::get_singleton()->make_bottom_panel_item_visible(this); |
1383 | |
1384 | Ref<AudioBusLayout> state = ResourceLoader::load(p_path, "" , ResourceFormatLoader::CACHE_MODE_IGNORE); |
1385 | if (state.is_null()) { |
1386 | EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an audio bus layout." )); |
1387 | return; |
1388 | } |
1389 | |
1390 | edited_path = p_path; |
1391 | file->set_text(p_path.get_file()); |
1392 | AudioServer::get_singleton()->set_bus_layout(state); |
1393 | _update_buses(); |
1394 | EditorUndoRedoManager::get_singleton()->clear_history(true, EditorUndoRedoManager::GLOBAL_HISTORY); |
1395 | call_deferred(SNAME("_select_layout" )); |
1396 | } |
1397 | |
1398 | void AudioBusesEditorPlugin::edit(Object *p_node) { |
1399 | if (Object::cast_to<AudioBusLayout>(p_node)) { |
1400 | String path = Object::cast_to<AudioBusLayout>(p_node)->get_path(); |
1401 | if (path.is_resource_file()) { |
1402 | audio_bus_editor->open_layout(path); |
1403 | } |
1404 | } |
1405 | } |
1406 | |
1407 | bool AudioBusesEditorPlugin::handles(Object *p_node) const { |
1408 | return (Object::cast_to<AudioBusLayout>(p_node) != nullptr); |
1409 | } |
1410 | |
1411 | void AudioBusesEditorPlugin::make_visible(bool p_visible) { |
1412 | } |
1413 | |
1414 | AudioBusesEditorPlugin::AudioBusesEditorPlugin(EditorAudioBuses *p_node) { |
1415 | audio_bus_editor = p_node; |
1416 | } |
1417 | |
1418 | AudioBusesEditorPlugin::~AudioBusesEditorPlugin() { |
1419 | } |
1420 | |
1421 | void EditorAudioMeterNotches::add_notch(float p_normalized_offset, float p_db_value, bool p_render_value) { |
1422 | notches.push_back(AudioNotch(p_normalized_offset, p_db_value, p_render_value)); |
1423 | } |
1424 | |
1425 | Size2 EditorAudioMeterNotches::get_minimum_size() const { |
1426 | Ref<Font> font = get_theme_font(SNAME("font" ), SNAME("Label" )); |
1427 | int font_size = get_theme_font_size(SNAME("font_size" ), SNAME("Label" )); |
1428 | float font_height = font->get_height(font_size); |
1429 | |
1430 | float width = 0; |
1431 | float height = top_padding + btm_padding; |
1432 | |
1433 | for (int i = 0; i < notches.size(); i++) { |
1434 | if (notches[i].render_db_value) { |
1435 | width = MAX(width, font->get_string_size(String::num(Math::abs(notches[i].db_value)) + "dB" , HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x); |
1436 | height += font_height; |
1437 | } |
1438 | } |
1439 | width += line_length + label_space; |
1440 | |
1441 | return Size2(width, height); |
1442 | } |
1443 | |
1444 | void EditorAudioMeterNotches::_update_theme_item_cache() { |
1445 | Control::_update_theme_item_cache(); |
1446 | |
1447 | theme_cache.notch_color = get_theme_color(SNAME("font_color" ), EditorStringName(Editor)); |
1448 | |
1449 | theme_cache.font = get_theme_font(SNAME("font" ), SNAME("Label" )); |
1450 | theme_cache.font_size = get_theme_font_size(SNAME("font_size" ), SNAME("Label" )); |
1451 | } |
1452 | |
1453 | void EditorAudioMeterNotches::_bind_methods() { |
1454 | ClassDB::bind_method("add_notch" , &EditorAudioMeterNotches::add_notch); |
1455 | ClassDB::bind_method("_draw_audio_notches" , &EditorAudioMeterNotches::_draw_audio_notches); |
1456 | } |
1457 | |
1458 | void EditorAudioMeterNotches::_notification(int p_what) { |
1459 | switch (p_what) { |
1460 | case NOTIFICATION_DRAW: { |
1461 | _draw_audio_notches(); |
1462 | } break; |
1463 | } |
1464 | } |
1465 | |
1466 | void EditorAudioMeterNotches::_draw_audio_notches() { |
1467 | float font_height = theme_cache.font->get_height(theme_cache.font_size); |
1468 | |
1469 | for (int i = 0; i < notches.size(); i++) { |
1470 | AudioNotch n = notches[i]; |
1471 | draw_line(Vector2(0, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding), |
1472 | Vector2(line_length * EDSCALE, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding), |
1473 | theme_cache.notch_color, |
1474 | Math::round(EDSCALE)); |
1475 | |
1476 | if (n.render_db_value) { |
1477 | draw_string(theme_cache.font, |
1478 | Vector2((line_length + label_space) * EDSCALE, |
1479 | (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + (font_height / 4) + top_padding), |
1480 | String::num(Math::abs(n.db_value)) + "dB" , |
1481 | HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size, |
1482 | theme_cache.notch_color); |
1483 | } |
1484 | } |
1485 | } |
1486 | |