diff options
-rw-r--r-- | drivers/alsa/audio_driver_alsa.cpp | 80 | ||||
-rw-r--r-- | drivers/coreaudio/audio_driver_coreaudio.cpp | 3 | ||||
-rw-r--r-- | drivers/pulseaudio/audio_driver_pulseaudio.cpp | 16 | ||||
-rw-r--r-- | drivers/wasapi/audio_driver_wasapi.cpp | 66 | ||||
-rw-r--r-- | drivers/wasapi/audio_driver_wasapi.h | 1 | ||||
-rw-r--r-- | editor/editor_properties.cpp | 22 | ||||
-rw-r--r-- | editor/editor_properties.h | 1 | ||||
-rw-r--r-- | editor/plugins/path_2d_editor_plugin.cpp | 55 | ||||
-rw-r--r-- | editor/plugins/path_2d_editor_plugin.h | 12 | ||||
-rw-r--r-- | editor/plugins/path_editor_plugin.cpp | 65 | ||||
-rw-r--r-- | editor/plugins/path_editor_plugin.h | 19 | ||||
-rw-r--r-- | editor/project_settings_editor.cpp | 11 | ||||
-rw-r--r-- | main/main.cpp | 2 | ||||
-rw-r--r-- | servers/audio_server.cpp | 88 | ||||
-rw-r--r-- | servers/audio_server.h | 26 |
15 files changed, 379 insertions, 88 deletions
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp index 1e17e72532..ae85ee50d1 100644 --- a/drivers/alsa/audio_driver_alsa.cpp +++ b/drivers/alsa/audio_driver_alsa.cpp @@ -142,8 +142,6 @@ Error AudioDriverALSA::init_device() { samples_in.resize(period_size * channels); samples_out.resize(period_size * channels); - snd_pcm_nonblock(pcm_handle, 0); - return OK; } @@ -168,54 +166,50 @@ void AudioDriverALSA::thread_func(void *p_udata) { AudioDriverALSA *ad = (AudioDriverALSA *)p_udata; while (!ad->exit_thread) { + + ad->lock(); + ad->start_counting_ticks(); + if (!ad->active) { for (unsigned int i = 0; i < ad->period_size * ad->channels; i++) { ad->samples_out[i] = 0; - }; - } else { - ad->lock(); + } + } else { ad->audio_server_process(ad->period_size, ad->samples_in.ptrw()); - ad->unlock(); - for (unsigned int i = 0; i < ad->period_size * ad->channels; i++) { ad->samples_out[i] = ad->samples_in[i] >> 16; } - }; + } int todo = ad->period_size; int total = 0; - while (todo) { - if (ad->exit_thread) - break; + while (todo && !ad->exit_thread) { uint8_t *src = (uint8_t *)ad->samples_out.ptr(); int wrote = snd_pcm_writei(ad->pcm_handle, (void *)(src + (total * ad->channels)), todo); - if (wrote < 0) { - if (ad->exit_thread) - break; + if (wrote > 0) { + total += wrote; + todo -= wrote; + } else if (wrote == -EAGAIN) { + ad->stop_counting_ticks(); + ad->unlock(); - if (wrote == -EAGAIN) { - //can't write yet (though this is blocking..) - usleep(1000); - continue; - } + OS::get_singleton()->delay_usec(1000); + + ad->lock(); + ad->start_counting_ticks(); + } else { wrote = snd_pcm_recover(ad->pcm_handle, wrote, 0); if (wrote < 0) { - //absolute fail - fprintf(stderr, "ALSA failed and can't recover: %s\n", snd_strerror(wrote)); + ERR_PRINTS("ALSA: Failed and can't recover: " + String(snd_strerror(wrote))); ad->active = false; ad->exit_thread = true; - break; } - continue; - }; - - total += wrote; - todo -= wrote; - }; + } + } // User selected a new device, finish the current one so we'll init the new device if (ad->device_name != ad->new_device) { @@ -232,10 +226,12 @@ void AudioDriverALSA::thread_func(void *p_udata) { if (err != OK) { ad->active = false; ad->exit_thread = true; - break; } } } + + ad->stop_counting_ticks(); + ad->unlock(); }; ad->thread_exited = true; @@ -296,7 +292,9 @@ String AudioDriverALSA::get_device() { void AudioDriverALSA::set_device(String device) { + lock(); new_device = device; + unlock(); } void AudioDriverALSA::lock() { @@ -323,21 +321,21 @@ void AudioDriverALSA::finish_device() { void AudioDriverALSA::finish() { - if (!thread) - return; - - exit_thread = true; - Thread::wait_to_finish(thread); + if (thread) { + exit_thread = true; + Thread::wait_to_finish(thread); - finish_device(); + memdelete(thread); + thread = NULL; - memdelete(thread); - if (mutex) { - memdelete(mutex); - mutex = NULL; + if (mutex) { + memdelete(mutex); + mutex = NULL; + } } - thread = NULL; -}; + + finish_device(); +} AudioDriverALSA::AudioDriverALSA() { diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index ef7858b4ca..63af4506f3 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -163,6 +163,8 @@ OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon, return 0; }; + ad->start_counting_ticks(); + for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) { AudioBuffer *abuf = &ioData->mBuffers[i]; @@ -184,6 +186,7 @@ OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon, }; }; + ad->stop_counting_ticks(); ad->unlock(); return 0; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index 0f47949b4b..ed6af04b9d 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -289,18 +289,18 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { AudioDriverPulseAudio *ad = (AudioDriverPulseAudio *)p_udata; while (!ad->exit_thread) { + + ad->lock(); + ad->start_counting_ticks(); + if (!ad->active) { for (unsigned int i = 0; i < ad->pa_buffer_size; i++) { ad->samples_out[i] = 0; } } else { - ad->lock(); - ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw()); - ad->unlock(); - if (ad->channels == ad->pa_map.channels) { for (unsigned int i = 0; i < ad->pa_buffer_size; i++) { ad->samples_out[i] = ad->samples_in[i] >> 16; @@ -323,9 +323,6 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { int error_code; int byte_size = ad->pa_buffer_size * sizeof(int16_t); - - ad->lock(); - int ret; do { ret = pa_mainloop_iterate(ad->pa_ml, 0, NULL); @@ -350,11 +347,13 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { if (ret == 0) { // If pa_mainloop_iterate returns 0 sleep for 1 msec to wait // for the stream to be able to process more bytes + ad->stop_counting_ticks(); ad->unlock(); OS::get_singleton()->delay_usec(1000); ad->lock(); + ad->start_counting_ticks(); } } } @@ -380,6 +379,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { } } + ad->stop_counting_ticks(); ad->unlock(); } @@ -453,7 +453,9 @@ String AudioDriverPulseAudio::get_device() { void AudioDriverPulseAudio::set_device(String device) { + lock(); new_device = device; + unlock(); } void AudioDriverPulseAudio::lock() { diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index e1680601ad..3c54c429d9 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -335,22 +335,6 @@ Error AudioDriverWASAPI::init() { return OK; } -Error AudioDriverWASAPI::reopen() { - Error err = finish_device(); - if (err != OK) { - ERR_PRINT("WASAPI: finish_device error"); - } else { - err = init_device(); - if (err != OK) { - ERR_PRINT("WASAPI: init_device error"); - } else { - start(); - } - } - - return err; -} - int AudioDriverWASAPI::get_mix_rate() const { return mix_rate; @@ -416,7 +400,9 @@ String AudioDriverWASAPI::get_device() { void AudioDriverWASAPI::set_device(String device) { + lock(); new_device = device; + unlock(); } void AudioDriverWASAPI::write_sample(AudioDriverWASAPI *ad, BYTE *buffer, int i, int32_t sample) { @@ -453,24 +439,31 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { AudioDriverWASAPI *ad = (AudioDriverWASAPI *)p_udata; while (!ad->exit_thread) { - if (ad->active) { - ad->lock(); - ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw()); + ad->lock(); + ad->start_counting_ticks(); - ad->unlock(); + if (ad->active) { + ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw()); } else { for (unsigned int i = 0; i < ad->buffer_size; i++) { ad->samples_in[i] = 0; } } + ad->stop_counting_ticks(); + ad->unlock(); + unsigned int left_frames = ad->buffer_frames; unsigned int buffer_idx = 0; while (left_frames > 0 && ad->audio_client) { WaitForSingleObject(ad->event, 1000); + ad->lock(); + ad->start_counting_ticks(); + UINT32 cur_frames; + bool invalidated = false; HRESULT hr = ad->audio_client->GetCurrentPadding(&cur_frames); if (hr == S_OK) { // Check how much frames are available on the WASAPI buffer @@ -506,34 +499,34 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { left_frames -= write_frames; } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) { - // Device is not valid anymore, reopen it - - Error err = ad->finish_device(); - if (err != OK) { - ERR_PRINT("WASAPI: finish_device error"); - } else { - // We reopened the device and samples_in may have resized, so invalidate the current left_frames - left_frames = 0; - } + invalidated = true; } else { ERR_PRINT("WASAPI: Get buffer error"); ad->exit_thread = true; } } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) { - // Device is not valid anymore, reopen it + invalidated = true; + } else { + ERR_PRINT("WASAPI: GetCurrentPadding error"); + } + + if (invalidated) { + // Device is not valid anymore + WARN_PRINT("WASAPI: Current device invalidated, closing device"); Error err = ad->finish_device(); if (err != OK) { ERR_PRINT("WASAPI: finish_device error"); - } else { - // We reopened the device and samples_in may have resized, so invalidate the current left_frames - left_frames = 0; } - } else { - ERR_PRINT("WASAPI: GetCurrentPadding error"); } + + ad->stop_counting_ticks(); + ad->unlock(); } + ad->lock(); + ad->start_counting_ticks(); + // If we're using the Default device and it changed finish it so we'll re-init the device if (ad->device_name == "Default" && default_device_changed) { Error err = ad->finish_device(); @@ -559,6 +552,9 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { ad->start(); } } + + ad->stop_counting_ticks(); + ad->unlock(); } ad->thread_exited = true; diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index c97f4c288c..f3ee5976eb 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -72,7 +72,6 @@ class AudioDriverWASAPI : public AudioDriver { Error init_device(bool reinit = false); Error finish_device(); - Error reopen(); public: virtual const char *get_name() const { diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 077b58a40f..ca51f6e635 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1832,7 +1832,18 @@ void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<T RES p = get_edited_object()->get(get_edited_property()); if (p.is_valid() && p->get_instance_id() == p_obj) { if (p_preview.is_valid()) { - assign->set_icon(p_preview); + String type = p->get_class_name(); + preview->set_margin(MARGIN_LEFT, assign->get_icon()->get_width() + assign->get_stylebox("normal")->get_default_margin(MARGIN_LEFT) + get_constant("hseparation", "Button")); + if (type == "GradientTexture") { + preview->set_stretch_mode(TextureRect::STRETCH_SCALE); + assign->set_custom_minimum_size(Size2(1, 1)); + } else { + preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); + int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); + thumbnail_size *= EDSCALE; + assign->set_custom_minimum_size(Size2(1, thumbnail_size)); + } + preview->set_texture(p_preview); } } } @@ -2073,6 +2084,7 @@ void EditorPropertyResource::update_property() { #endif } + preview->set_texture(Ref<Texture>()); if (res == RES()) { assign->set_icon(Ref<Texture>()); assign->set_text(TTR("[empty]")); @@ -2311,6 +2323,14 @@ EditorPropertyResource::EditorPropertyResource() { assign->connect("draw", this, "_button_draw"); hbc->add_child(assign); + preview = memnew(TextureRect); + preview->set_expand(true); + preview->set_anchors_and_margins_preset(PRESET_WIDE); + preview->set_margin(MARGIN_TOP, 1); + preview->set_margin(MARGIN_BOTTOM, -1); + preview->set_margin(MARGIN_RIGHT, -1); + assign->add_child(preview); + menu = memnew(PopupMenu); add_child(menu); edit = memnew(Button); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index ecccd7274d..b53d3ef40f 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -488,6 +488,7 @@ class EditorPropertyResource : public EditorProperty { }; Button *assign; + TextureRect *preview; Button *edit; PopupMenu *menu; EditorFileDialog *file; diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 5ec42b07aa..33e182faef 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -109,6 +109,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { action_point = i; moving_from = curve->get_point_out(i); moving_screen_from = gpoint; + orig_in_length = curve->get_point_in(action_point).length(); return true; } else if (dist_to_p_in < grab_threshold && i > 0) { @@ -116,6 +117,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { action_point = i; moving_from = curve->get_point_in(i); moving_screen_from = gpoint; + orig_out_length = curve->get_point_out(action_point).length(); return true; } } @@ -205,6 +207,11 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->create_action(TTR("Move In-Control in Curve")); undo_redo->add_do_method(curve.ptr(), "set_point_in", action_point, new_pos); undo_redo->add_undo_method(curve.ptr(), "set_point_in", action_point, moving_from); + + if (mirror_handle_angle) { + undo_redo->add_do_method(curve.ptr(), "set_point_out", action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_out_length)); + undo_redo->add_undo_method(curve.ptr(), "set_point_out", action_point, mirror_handle_length ? -moving_from : (-moving_from.normalized() * orig_out_length)); + } undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); undo_redo->commit_action(); @@ -216,6 +223,11 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->create_action(TTR("Move Out-Control in Curve")); undo_redo->add_do_method(curve.ptr(), "set_point_out", action_point, new_pos); undo_redo->add_undo_method(curve.ptr(), "set_point_out", action_point, moving_from); + + if (mirror_handle_angle) { + undo_redo->add_do_method(curve.ptr(), "set_point_in", action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_in_length)); + undo_redo->add_undo_method(curve.ptr(), "set_point_in", action_point, mirror_handle_length ? -moving_from : (-moving_from.normalized() * orig_in_length)); + } undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); undo_redo->commit_action(); @@ -255,10 +267,16 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { case ACTION_MOVING_IN: { curve->set_point_in(action_point, new_pos); + + if (mirror_handle_angle) + curve->set_point_out(action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_out_length)); } break; case ACTION_MOVING_OUT: { curve->set_point_out(action_point, new_pos); + + if (mirror_handle_angle) + curve->set_point_in(action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_in_length)); } break; } @@ -342,6 +360,7 @@ void Path2DEditor::_bind_methods() { //ClassDB::bind_method(D_METHOD("_menu_option"),&Path2DEditor::_menu_option); ClassDB::bind_method(D_METHOD("_node_visibility_changed"), &Path2DEditor::_node_visibility_changed); ClassDB::bind_method(D_METHOD("_mode_selected"), &Path2DEditor::_mode_selected); + ClassDB::bind_method(D_METHOD("_handle_option_pressed"), &Path2DEditor::_handle_option_pressed); } void Path2DEditor::_mode_selected(int p_mode) { @@ -396,11 +415,33 @@ void Path2DEditor::_mode_selected(int p_mode) { mode = Mode(p_mode); } +void Path2DEditor::_handle_option_pressed(int p_option) { + + PopupMenu *pm; + pm = handle_menu->get_popup(); + + switch (p_option) { + case HANDLE_OPTION_ANGLE: { + bool is_checked = pm->is_item_checked(HANDLE_OPTION_ANGLE); + mirror_handle_angle = !is_checked; + pm->set_item_checked(HANDLE_OPTION_ANGLE, mirror_handle_angle); + pm->set_item_disabled(HANDLE_OPTION_LENGTH, !mirror_handle_angle); + } break; + case HANDLE_OPTION_LENGTH: { + bool is_checked = pm->is_item_checked(HANDLE_OPTION_LENGTH); + mirror_handle_length = !is_checked; + pm->set_item_checked(HANDLE_OPTION_LENGTH, mirror_handle_length); + } break; + } +} + Path2DEditor::Path2DEditor(EditorNode *p_editor) { canvas_item_editor = NULL; editor = p_editor; undo_redo = editor->get_undo_redo(); + mirror_handle_angle = true; + mirror_handle_length = true; mode = MODE_EDIT; action = ACTION_NONE; @@ -444,6 +485,20 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) { curve_close->set_tooltip(TTR("Close Curve")); curve_close->connect("pressed", this, "_mode_selected", varray(ACTION_CLOSE)); base_hb->add_child(curve_close); + + PopupMenu *menu; + + handle_menu = memnew(MenuButton); + handle_menu->set_text(TTR("Options")); + base_hb->add_child(handle_menu); + + menu = handle_menu->get_popup(); + menu->add_check_item(TTR("Mirror Handle Angles")); + menu->set_item_checked(HANDLE_OPTION_ANGLE, mirror_handle_angle); + menu->add_check_item(TTR("Mirror Handle Lengths")); + menu->set_item_checked(HANDLE_OPTION_LENGTH, mirror_handle_length); + menu->connect("id_pressed", this, "_handle_option_pressed"); + base_hb->hide(); curve_edit->set_pressed(true); diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index c92a696967..1e3955f84f 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -69,6 +69,15 @@ class Path2DEditor : public HBoxContainer { ToolButton *curve_edit_curve; ToolButton *curve_del; ToolButton *curve_close; + MenuButton *handle_menu; + + bool mirror_handle_angle; + bool mirror_handle_length; + + enum HandleOption { + HANDLE_OPTION_ANGLE, + HANDLE_OPTION_LENGTH + }; enum Action { @@ -82,8 +91,11 @@ class Path2DEditor : public HBoxContainer { int action_point; Point2 moving_from; Point2 moving_screen_from; + float orig_in_length; + float orig_out_length; void _mode_selected(int p_mode); + void _handle_option_pressed(int p_option); void _node_visibility_changed(); friend class Path2DEditorPlugin; diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp index 6dde639c54..72a8b55a52 100644 --- a/editor/plugins/path_editor_plugin.cpp +++ b/editor/plugins/path_editor_plugin.cpp @@ -128,11 +128,22 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p if (p.intersects_ray(ray_from, ray_dir, &inters)) { + if (!PathEditorPlugin::singleton->is_handle_clicked()) { + orig_in_length = c->get_point_in(idx).length(); + orig_out_length = c->get_point_out(idx).length(); + PathEditorPlugin::singleton->set_handle_clicked(true); + } + Vector3 local = gi.xform(inters) - base; if (t == 0) { c->set_point_in(idx, local); + + if (PathEditorPlugin::singleton->mirror_angle_enabled()) + c->set_point_out(idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -local : (-local.normalized() * orig_out_length)); } else { c->set_point_out(idx, local); + if (PathEditorPlugin::singleton->mirror_angle_enabled()) + c->set_point_in(idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -local : (-local.normalized() * orig_in_length)); } } } @@ -165,8 +176,6 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p int idx = p_idx / 2; int t = p_idx % 2; - Vector3 ofs; - if (t == 0) { if (p_cancel) { c->set_point_in(p_idx, p_restore); @@ -176,6 +185,11 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p ur->create_action(TTR("Set Curve In Position")); ur->add_do_method(c.ptr(), "set_point_in", idx, c->get_point_in(idx)); ur->add_undo_method(c.ptr(), "set_point_in", idx, p_restore); + + if (PathEditorPlugin::singleton->mirror_angle_enabled()) { + ur->add_do_method(c.ptr(), "set_point_out", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_in(idx) : (-c->get_point_in(idx).normalized() * orig_out_length)); + ur->add_undo_method(c.ptr(), "set_point_out", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_out_length)); + } ur->commit_action(); } else { @@ -188,6 +202,11 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p ur->create_action(TTR("Set Curve Out Position")); ur->add_do_method(c.ptr(), "set_point_out", idx, c->get_point_out(idx)); ur->add_undo_method(c.ptr(), "set_point_out", idx, p_restore); + + if (PathEditorPlugin::singleton->mirror_angle_enabled()) { + ur->add_do_method(c.ptr(), "set_point_in", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_out(idx) : (-c->get_point_out(idx).normalized() * orig_in_length)); + ur->add_undo_method(c.ptr(), "set_point_in", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_in_length)); + } ur->commit_action(); } } @@ -291,6 +310,9 @@ bool PathEditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp Point2 mbpos(mb->get_position().x, mb->get_position().y); + if (!mb->is_pressed()) + set_handle_clicked(false); + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->get_control()))) { //click into curve, break it down PoolVector<Vector3> v3a = c->tessellate(); @@ -459,6 +481,7 @@ void PathEditorPlugin::make_visible(bool p_visible) { curve_edit->show(); curve_del->show(); curve_close->show(); + handle_menu->show(); sep->show(); } else { @@ -466,6 +489,7 @@ void PathEditorPlugin::make_visible(bool p_visible) { curve_edit->hide(); curve_del->hide(); curve_close->hide(); + handle_menu->hide(); sep->hide(); { @@ -495,6 +519,26 @@ void PathEditorPlugin::_close_curve() { c->add_point(c->get_point_position(0), c->get_point_in(0), c->get_point_out(0)); } +void PathEditorPlugin::_handle_option_pressed(int p_option) { + + PopupMenu *pm; + pm = handle_menu->get_popup(); + + switch (p_option) { + case HANDLE_OPTION_ANGLE: { + bool is_checked = pm->is_item_checked(HANDLE_OPTION_ANGLE); + mirror_handle_angle = !is_checked; + pm->set_item_checked(HANDLE_OPTION_ANGLE, mirror_handle_angle); + pm->set_item_disabled(HANDLE_OPTION_LENGTH, !mirror_handle_angle); + } break; + case HANDLE_OPTION_LENGTH: { + bool is_checked = pm->is_item_checked(HANDLE_OPTION_LENGTH); + mirror_handle_length = !is_checked; + pm->set_item_checked(HANDLE_OPTION_LENGTH, mirror_handle_length); + } break; + } +} + void PathEditorPlugin::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { @@ -510,6 +554,7 @@ void PathEditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("_mode_changed"), &PathEditorPlugin::_mode_changed); ClassDB::bind_method(D_METHOD("_close_curve"), &PathEditorPlugin::_close_curve); + ClassDB::bind_method(D_METHOD("_handle_option_pressed"), &PathEditorPlugin::_handle_option_pressed); } PathEditorPlugin *PathEditorPlugin::singleton = NULL; @@ -519,6 +564,8 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { path = NULL; editor = p_node; singleton = this; + mirror_handle_angle = true; + mirror_handle_length = true; path_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); path_material->set_albedo(Color(0.5, 0.5, 1.0, 0.8)); @@ -567,6 +614,20 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { curve_close->set_tooltip(TTR("Close Curve")); SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_close); + PopupMenu *menu; + + handle_menu = memnew(MenuButton); + handle_menu->set_text(TTR("Options")); + handle_menu->hide(); + SpatialEditor::get_singleton()->add_control_to_menu_panel(handle_menu); + + menu = handle_menu->get_popup(); + menu->add_check_item(TTR("Mirror Handle Angles")); + menu->set_item_checked(HANDLE_OPTION_ANGLE, mirror_handle_angle); + menu->add_check_item(TTR("Mirror Handle Lengths")); + menu->set_item_checked(HANDLE_OPTION_LENGTH, mirror_handle_length); + menu->connect("id_pressed", this, "_handle_option_pressed"); + curve_edit->set_pressed(true); /* collision_polygon_editor = memnew( PathEditor(p_node) ); diff --git a/editor/plugins/path_editor_plugin.h b/editor/plugins/path_editor_plugin.h index 6d5f07f729..52dfb78b61 100644 --- a/editor/plugins/path_editor_plugin.h +++ b/editor/plugins/path_editor_plugin.h @@ -1,4 +1,4 @@ -/*************************************************************************/ +/*************************************************************************/ /* path_editor_plugin.h */ /*************************************************************************/ /* This file is part of: */ @@ -40,6 +40,8 @@ class PathSpatialGizmo : public EditorSpatialGizmo { Path *path; mutable Vector3 original; + mutable float orig_in_length; + mutable float orig_out_length; public: virtual String get_handle_name(int p_idx) const; @@ -60,6 +62,7 @@ class PathEditorPlugin : public EditorPlugin { ToolButton *curve_edit; ToolButton *curve_del; ToolButton *curve_close; + MenuButton *handle_menu; EditorNode *editor; @@ -67,6 +70,15 @@ class PathEditorPlugin : public EditorPlugin { void _mode_changed(int p_idx); void _close_curve(); + void _handle_option_pressed(int p_option); + bool handle_clicked; + bool mirror_handle_angle; + bool mirror_handle_length; + + enum HandleOption { + HANDLE_OPTION_ANGLE, + HANDLE_OPTION_LENGTH + }; protected: void _notification(int p_what); @@ -88,6 +100,11 @@ public: virtual bool handles(Object *p_object) const; virtual void make_visible(bool p_visible); + bool mirror_angle_enabled() { return mirror_handle_angle; } + bool mirror_length_enabled() { return mirror_handle_length; } + bool is_handle_clicked() { return handle_clicked; } + void set_handle_clicked(bool clicked) { handle_clicked = clicked; } + PathEditorPlugin(EditorNode *p_node); ~PathEditorPlugin(); }; diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 8c7565a441..7e4e589bb4 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -394,6 +394,7 @@ void ProjectSettingsEditor::_show_last_added(const Ref<InputEvent> &p_event, con while (child) { Variant input = child->get_meta("__input"); if (p_event == input) { + r->set_collapsed(false); child->select(0); found = true; break; @@ -654,6 +655,14 @@ void ProjectSettingsEditor::_update_actions() { if (setting) return; + Map<String, bool> collapsed; + + if (input_editor->get_root() && input_editor->get_root()->get_children()) { + for (TreeItem *item = input_editor->get_root()->get_children(); item; item = item->get_next()) { + collapsed[item->get_text(0)] = item->is_collapsed(); + } + } + input_editor->clear(); TreeItem *root = input_editor->create_item(); input_editor->set_hide_root(true); @@ -677,6 +686,8 @@ void ProjectSettingsEditor::_update_actions() { TreeItem *item = input_editor->create_item(root); item->set_text(0, name); item->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); + if (collapsed.has(name)) + item->set_collapsed(collapsed[name]); item->set_editable(1, true); item->set_cell_mode(1, TreeItem::CELL_MODE_RANGE); diff --git a/main/main.cpp b/main/main.cpp index 23acb60c89..23f2776737 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1823,6 +1823,8 @@ bool Main::iteration() { ScriptServer::get_language(i)->frame(); } + AudioServer::get_singleton()->update(); + if (script_debugger) { if (script_debugger->is_profiling()) { script_debugger->profiling_set_frame_times(USEC_TO_SEC(frame_time), USEC_TO_SEC(idle_process_ticks), USEC_TO_SEC(physics_process_ticks), frame_slice); diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 69c1318a48..ef794ac380 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -117,6 +117,10 @@ AudioDriver::AudioDriver() { _last_mix_time = 0; _mix_amount = 0; + +#ifdef DEBUG_ENABLED + prof_time = 0; +#endif } AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS]; @@ -184,6 +188,10 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) { int todo = p_frames; +#ifdef DEBUG_ENABLED + uint64_t prof_ticks = OS::get_singleton()->get_ticks_usec(); +#endif + if (channel_count != get_channel_count()) { // Amount of channels changed due to a device change // reinitialize the buses channels and buffers @@ -241,6 +249,10 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) { output_latency = (ticks - output_latency_ticks) / 1000000.f; output_latency_ticks = ticks; } + +#ifdef DEBUG_ENABLED + prof_time += OS::get_singleton()->get_ticks_usec() - prof_ticks; +#endif } void AudioServer::_mix_step() { @@ -314,6 +326,10 @@ void AudioServer::_mix_step() { if (!bus->effects[j].enabled) continue; +#ifdef DEBUG_ENABLED + uint64_t ticks = OS::get_singleton()->get_ticks_usec(); +#endif + for (int k = 0; k < bus->channels.size(); k++) { if (!bus->channels[k].active) @@ -328,6 +344,10 @@ void AudioServer::_mix_step() { continue; SWAP(bus->channels[k].buffer, temp_buffer[k]); } + +#ifdef DEBUG_ENABLED + bus->effects[j].prof_time += OS::get_singleton()->get_ticks_usec() - ticks; +#endif } } @@ -768,6 +788,9 @@ void AudioServer::add_bus_effect(int p_bus, const Ref<AudioEffect> &p_effect, in fx.effect = p_effect; //fx.instance=p_effect->instance(); fx.enabled = true; +#ifdef DEBUG_ENABLED + fx.prof_time = 0; +#endif if (p_at_pos >= buses[p_bus]->effects.size() || p_at_pos < 0) { buses[p_bus]->effects.push_back(fx); @@ -900,6 +923,68 @@ void AudioServer::init() { GLOBAL_DEF("audio/video_delay_compensation_ms", 0); } +void AudioServer::update() { +#ifdef DEBUG_ENABLED + if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) { + + // Driver time includes server time + effects times + // Server time includes effects times + uint64_t driver_time = AudioDriver::get_singleton()->get_profiling_time(); + uint64_t server_time = prof_time; + + // Substract the server time from the driver time + if (driver_time > server_time) + driver_time -= server_time; + + Array values; + + for (int i = buses.size() - 1; i >= 0; i--) { + Bus *bus = buses[i]; + if (bus->bypass) + continue; + + for (int j = 0; j < bus->effects.size(); j++) { + if (!bus->effects[j].enabled) + continue; + + values.push_back(String(bus->name) + bus->effects[j].effect->get_name()); + values.push_back(USEC_TO_SEC(bus->effects[j].prof_time)); + + // Substract the effect time from the driver and server times + if (driver_time > bus->effects[j].prof_time) + driver_time -= bus->effects[j].prof_time; + if (server_time > bus->effects[j].prof_time) + server_time -= bus->effects[j].prof_time; + } + } + + values.push_back("audio_server"); + values.push_back(USEC_TO_SEC(server_time)); + values.push_back("audio_driver"); + values.push_back(USEC_TO_SEC(driver_time)); + + ScriptDebugger::get_singleton()->add_profiling_frame_data("audio_thread", values); + } + + // Reset profiling times + for (int i = buses.size() - 1; i >= 0; i--) { + Bus *bus = buses[i]; + if (bus->bypass) + continue; + + for (int j = 0; j < bus->effects.size(); j++) { + if (!bus->effects[j].enabled) + continue; + + bus->effects[j].prof_time = 0; + } + } + + AudioDriver::get_singleton()->reset_profiling_time(); + prof_time = 0; +#endif +} + void AudioServer::load_default_bus_layout() { if (FileAccess::exists("res://default_bus_layout.tres")) { @@ -1187,6 +1272,9 @@ AudioServer::AudioServer() { to_mix = 0; output_latency = 0; output_latency_ticks = 0; +#ifdef DEBUG_ENABLED + prof_time = 0; +#endif } AudioServer::~AudioServer() { diff --git a/servers/audio_server.h b/servers/audio_server.h index f928acc7b5..258fd1d9b0 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -33,6 +33,7 @@ #include "audio_frame.h" #include "object.h" +#include "os/os.h" #include "servers/audio/audio_effect.h" #include "variant.h" @@ -44,10 +45,23 @@ class AudioDriver { uint64_t _last_mix_time; uint64_t _mix_amount; +#ifdef DEBUG_ENABLED + uint64_t prof_ticks; + uint64_t prof_time; +#endif + protected: void audio_server_process(int p_frames, int32_t *p_buffer, bool p_update_mix_time = true); void update_mix_time(int p_frames); +#ifdef DEBUG_ENABLED + _FORCE_INLINE_ void start_counting_ticks() { prof_ticks = OS::get_singleton()->get_ticks_usec(); } + _FORCE_INLINE_ void stop_counting_ticks() { prof_time += OS::get_singleton()->get_ticks_usec() - prof_ticks; } +#else + _FORCE_INLINE_ void start_counting_ticks() {} + _FORCE_INLINE_ void stop_counting_ticks() {} +#endif + public: double get_mix_time() const; //useful for video -> audio sync @@ -82,6 +96,11 @@ public: SpeakerMode get_speaker_mode_by_total_channels(int p_channels) const; int get_total_channels_by_speaker_mode(SpeakerMode) const; +#ifdef DEBUG_ENABLED + uint64_t get_profiling_time() const { return prof_time; } + void reset_profiling_time() { prof_time = 0; } +#endif + AudioDriver(); virtual ~AudioDriver() {} }; @@ -129,6 +148,9 @@ private: uint32_t buffer_size; uint64_t mix_count; uint64_t mix_frames; +#ifdef DEBUG_ENABLED + uint64_t prof_time; +#endif float channel_disable_threshold_db; uint32_t channel_disable_frames; @@ -166,6 +188,9 @@ private: struct Effect { Ref<AudioEffect> effect; bool enabled; +#ifdef DEBUG_ENABLED + uint64_t prof_time; +#endif }; Vector<Effect> effects; @@ -276,6 +301,7 @@ public: virtual void init(); virtual void finish(); + virtual void update(); virtual void load_default_bus_layout(); /* MISC config */ |