diff options
23 files changed, 179 insertions, 62 deletions
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index e7f94b5826..0af11eec31 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -259,6 +259,13 @@ <description> </description> </method> + <method name="is_readonly" qualifiers="const"> ++ <return type="bool"> ++ </return> ++ <description> ++ Return true if the text editor is in read-only mode (see [method set_readonly]). ++ </description> ++ </method> <method name="is_selection_active" qualifiers="const"> <return type="bool"> </return> @@ -458,6 +465,9 @@ </method> </methods> <members> + <member name="readonly" type="bool" setter="set_readonly" getter="is_readonly"> + If [code]true[/code] read-only mode is enabled. Existing text cannot be modified and new text cannot be added. + </member> <member name="caret_blink" type="bool" setter="cursor_set_blink_enabled" getter="cursor_get_blink_enabled"> </member> <member name="caret_blink_speed" type="float" setter="cursor_set_blink_speed" getter="cursor_get_blink_speed"> diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 731d6968ce..4bbb18ce42 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -381,8 +381,7 @@ void main() { if (clip_rect_uv) { - vec2 half_texpixel = color_texpixel_size * 0.5; - uv = clamp(uv,src_rect.xy+half_texpixel,src_rect.xy+abs(src_rect.zw)-color_texpixel_size); + uv = clamp(uv,src_rect.xy,src_rect.xy+abs(src_rect.zw)); } #endif diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 0675cf2c75..9931f75314 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -284,9 +284,10 @@ void EditorNode::_notification(int p_what) { if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/editor/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true))); - Ref<Theme> theme = create_editor_theme(theme_base->get_theme()); + Ref<Theme> theme = create_custom_theme(theme_base->get_theme()); theme_base->set_theme(theme); + gui_base->set_theme(theme); gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles")); play_button_panel->add_style_override("panel", gui_base->get_stylebox("PlayButtonPanel", "EditorStyles")); @@ -4691,9 +4692,9 @@ EditorNode::EditorNode() { theme_base->add_child(gui_base); gui_base->set_anchors_and_margins_preset(Control::PRESET_WIDE); - Ref<Theme> theme = create_editor_theme(); + Ref<Theme> theme = create_custom_theme(); theme_base->set_theme(theme); - gui_base->set_theme(create_custom_theme()); + gui_base->set_theme(theme); gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles")); resource_preview = memnew(EditorResourcePreview); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index ffa978e194..0f9f50095d 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -582,7 +582,22 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_color_disabled", "CheckButton", font_color_disabled); theme->set_color("icon_color_hover", "CheckButton", font_color_hl); + theme->set_constant("hseparation", "CheckButton", 4 * EDSCALE); + theme->set_constant("check_vadjust", "CheckButton", 0 * EDSCALE); + // Checkbox + Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate(); + // HACK, in reality, the checkbox draws the text over the icon by default, so the margin compensates that. + const int cb_w = theme->get_icon("GuiChecked", "EditorIcons")->get_width() + default_margin_size; + sb_checkbox->set_default_margin(MARGIN_LEFT, cb_w * EDSCALE); + sb_checkbox->set_default_margin(MARGIN_RIGHT, default_margin_size * EDSCALE); + sb_checkbox->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE); + sb_checkbox->set_default_margin(MARGIN_BOTTOM, default_margin_size * EDSCALE); + + theme->set_stylebox("normal", "CheckBox", sb_checkbox); + theme->set_stylebox("pressed", "CheckBox", sb_checkbox); + theme->set_stylebox("disabled", "CheckBox", sb_checkbox); + theme->set_stylebox("hover", "CheckBox", sb_checkbox); theme->set_icon("checked", "CheckBox", theme->get_icon("GuiChecked", "EditorIcons")); theme->set_icon("unchecked", "CheckBox", theme->get_icon("GuiUnchecked", "EditorIcons")); theme->set_icon("radio_checked", "CheckBox", theme->get_icon("GuiRadioChecked", "EditorIcons")); @@ -594,6 +609,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_color_disabled", "CheckBox", font_color_disabled); theme->set_color("icon_color_hover", "CheckBox", font_color_hl); + theme->set_constant("hseparation", "CheckBox", 4 * EDSCALE); + theme->set_constant("check_vadjust", "CheckBox", 0 * EDSCALE); + // PopupMenu Ref<StyleBoxFlat> style_popup_menu = style_popup; theme->set_stylebox("panel", "PopupMenu", style_popup_menu); @@ -1049,12 +1067,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { return theme; } -Ref<Theme> create_custom_theme() { - Ref<Theme> theme = create_editor_theme(); +Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) { + Ref<Theme> theme; String custom_theme = EditorSettings::get_singleton()->get("interface/theme/custom_theme"); if (custom_theme != "") { theme = ResourceLoader::load(custom_theme); + } else { + theme = create_editor_theme(p_theme); } String global_font = EditorSettings::get_singleton()->get("interface/editor/custom_font"); diff --git a/editor/editor_themes.h b/editor/editor_themes.h index a644c5936f..6f3b83e0b0 100644 --- a/editor/editor_themes.h +++ b/editor/editor_themes.h @@ -34,6 +34,6 @@ Ref<Theme> create_editor_theme(Ref<Theme> p_theme = NULL); -Ref<Theme> create_custom_theme(); +Ref<Theme> create_custom_theme(Ref<Theme> p_theme = NULL); #endif diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 16564ce45f..38467369db 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4373,11 +4373,11 @@ void CanvasItemEditorViewport::_on_mouse_exit() { void CanvasItemEditorViewport::_on_select_type(Object *selected) { CheckBox *check = Object::cast_to<CheckBox>(selected); String type = check->get_text(); - selector_label->set_text(vformat(TTR("Add %s"), type)); + selector->set_title(vformat(TTR("Add %s"), type)); label->set_text(vformat(TTR("Adding %s..."), type)); } -void CanvasItemEditorViewport::_on_change_type() { +void CanvasItemEditorViewport::_on_change_type_confirmed() { if (!button_group->get_pressed_button()) return; @@ -4387,6 +4387,11 @@ void CanvasItemEditorViewport::_on_change_type() { selector->hide(); } +void CanvasItemEditorViewport::_on_change_type_closed() { + + _remove_preview(); +} + void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) const { label->set_position(get_global_position() + Point2(14, 14) * EDSCALE); label_desc->set_position(label->get_position() + Point2(0, label->get_size().height)); @@ -4698,7 +4703,7 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]); check->set_pressed(check->get_text() == default_type); } - selector_label->set_text(vformat(TTR("Add %s"), default_type)); + selector->set_title(vformat(TTR("Add %s"), default_type)); selector->popup_centered_minsize(); } else { _perform_drop_data(); @@ -4721,7 +4726,8 @@ void CanvasItemEditorViewport::_notification(int p_what) { void CanvasItemEditorViewport::_bind_methods() { ClassDB::bind_method(D_METHOD("_on_select_type"), &CanvasItemEditorViewport::_on_select_type); - ClassDB::bind_method(D_METHOD("_on_change_type"), &CanvasItemEditorViewport::_on_change_type); + ClassDB::bind_method(D_METHOD("_on_change_type_confirmed"), &CanvasItemEditorViewport::_on_change_type_confirmed); + ClassDB::bind_method(D_METHOD("_on_change_type_closed"), &CanvasItemEditorViewport::_on_change_type_closed); ClassDB::bind_method(D_METHOD("_on_mouse_exit"), &CanvasItemEditorViewport::_on_mouse_exit); } @@ -4749,7 +4755,8 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte selector = memnew(AcceptDialog); editor->get_gui_base()->add_child(selector); selector->set_title(TTR("Change default type")); - selector->connect("confirmed", this, "_on_change_type"); + selector->connect("confirmed", this, "_on_change_type_confirmed"); + selector->connect("popup_hide", this, "_on_change_type_closed"); VBoxContainer *vbc = memnew(VBoxContainer); selector->add_child(vbc); @@ -4757,12 +4764,6 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte vbc->set_v_size_flags(SIZE_EXPAND_FILL); vbc->set_custom_minimum_size(Size2(200, 260) * EDSCALE); - selector_label = memnew(Label); - vbc->add_child(selector_label); - selector_label->set_align(Label::ALIGN_CENTER); - selector_label->set_valign(Label::VALIGN_BOTTOM); - selector_label->set_custom_minimum_size(Size2(0, 30) * EDSCALE); - btn_group = memnew(VBoxContainer); vbc->add_child(btn_group); btn_group->set_h_size_flags(0); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 97e3b03569..457833e1a7 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -568,7 +568,8 @@ class CanvasItemEditorViewport : public Control { void _on_mouse_exit(); void _on_select_type(Object *selected); - void _on_change_type(); + void _on_change_type_confirmed(); + void _on_change_type_closed(); void _create_preview(const Vector<String> &files) const; void _remove_preview(); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index e8714cece6..cc144344a6 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -2917,7 +2917,9 @@ bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const P } } - instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path)); + if (scene != NULL) { + instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path)); + } editor_data->get_undo_redo().add_do_method(parent, "add_child", instanced_scene); editor_data->get_undo_redo().add_do_method(instanced_scene, "set_owner", editor->get_edited_scene()); diff --git a/modules/mobile_vr/mobile_interface.cpp b/modules/mobile_vr/mobile_interface.cpp index 93d5c22ef8..dccdcd3070 100644 --- a/modules/mobile_vr/mobile_interface.cpp +++ b/modules/mobile_vr/mobile_interface.cpp @@ -156,17 +156,6 @@ void MobileVRInterface::set_position_from_sensors() { has_gyro = true; }; -#ifdef ANDROID_ENABLED - ///@TODO needs testing, i don't have a gyro, potentially can be removed depending on what comes out of issue #8101 - // On Android x and z axis seem inverted - gyro.x = -gyro.x; - gyro.z = -gyro.z; - grav.x = -grav.x; - grav.z = -grav.z; - magneto.x = -magneto.x; - magneto.z = -magneto.z; -#endif - if (has_gyro) { // start with applying our gyro (do NOT smooth our gyro!) Basis rotate; diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 03015df844..15e20effc0 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -2764,6 +2764,23 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_global_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y)); default_value_edit->set_size(Size2(1, 1)); + + if (pinfo.type == Variant::NODE_PATH) { + + Node *edited_scene = get_tree()->get_edited_scene_root(); + Node *script_node = _find_script_node(edited_scene, edited_scene, script); + + if (script_node) { + //pick a node relative to the script, IF the script exists + pinfo.hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE; + pinfo.hint_string = script_node->get_path(); + } else { + //pick a path relative to edited scene + pinfo.hint = PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE; + pinfo.hint_string = get_tree()->get_edited_scene_root()->get_path(); + } + } + if (default_value_edit->edit(NULL, pinfo.name, pinfo.type, existing, pinfo.hint, pinfo.hint_string)) { if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT) default_value_edit->popup_centered_ratio(); diff --git a/platform/android/godot_android.cpp b/platform/android/godot_android.cpp index 8235683496..abe5e3b77a 100644 --- a/platform/android/godot_android.cpp +++ b/platform/android/godot_android.cpp @@ -669,6 +669,14 @@ static void engine_handle_cmd(struct android_app *app, int32_t cmd) { ASensorEventQueue_setEventRate(engine->sensorEventQueue, engine->accelerometerSensor, (1000L / 60) * 1000); } + // start monitoring gravity + if (engine->gravitySensor != NULL) { + ASensorEventQueue_enableSensor(engine->sensorEventQueue, + engine->gravitySensor); + // We'd like to get 60 events per second (in us). + ASensorEventQueue_setEventRate(engine->sensorEventQueue, + engine->gravitySensor, (1000L / 60) * 1000); + } // Also start monitoring the magnetometer. if (engine->magnetometerSensor != NULL) { ASensorEventQueue_enableSensor(engine->sensorEventQueue, @@ -694,6 +702,10 @@ static void engine_handle_cmd(struct android_app *app, int32_t cmd) { ASensorEventQueue_disableSensor(engine->sensorEventQueue, engine->accelerometerSensor); } + if (engine->gravitySensor != NULL) { + ASensorEventQueue_disableSensor(engine->sensorEventQueue, + engine->gravitySensor); + } if (engine->magnetometerSensor != NULL) { ASensorEventQueue_disableSensor(engine->sensorEventQueue, engine->magnetometerSensor); @@ -729,6 +741,8 @@ void android_main(struct android_app *app) { engine.sensorManager = ASensorManager_getInstance(); engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, ASENSOR_TYPE_ACCELEROMETER); + engine.gravitySensor = ASensorManager_getDefaultSensor(engine.sensorManager, + ASENSOR_TYPE_GRAVITY); engine.magnetometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, ASENSOR_TYPE_MAGNETIC_FIELD); engine.gyroscopeSensor = ASensorManager_getDefaultSensor(engine.sensorManager, diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java index 59fefc498f..41dcba5c2c 100644 --- a/platform/android/java/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -219,6 +219,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC private SensorManager mSensorManager; private Sensor mAccelerometer; + private Sensor mGravity; private Sensor mMagnetometer; private Sensor mGyroscope; @@ -435,6 +436,8 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); + mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY); + mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME); mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME); mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); @@ -667,6 +670,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC } }); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); + mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME); mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME); mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); @@ -734,13 +738,16 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC @Override public void run() { if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) { - GodotLib.accelerometer(x,y,z); + GodotLib.accelerometer(-x,y,-z); + } + if (typeOfSensor == Sensor.TYPE_GRAVITY) { + GodotLib.gravity(-x,y,-z); } if (typeOfSensor == Sensor.TYPE_MAGNETIC_FIELD) { - GodotLib.magnetometer(x,y,z); + GodotLib.magnetometer(-x,y,-z); } if (typeOfSensor == Sensor.TYPE_GYROSCOPE) { - GodotLib.gyroscope(x,y,z); + GodotLib.gyroscope(x,-y,z); } } }); diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java index e0ed4cd38c..6b84ad6555 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java @@ -53,6 +53,7 @@ public class GodotLib { public static native void step(); public static native void touch(int what,int pointer,int howmany, int[] arr); public static native void accelerometer(float x, float y, float z); + public static native void gravity(float x, float y, float z); public static native void magnetometer(float x, float y, float z); public static native void gyroscope(float x, float y, float z); public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed); diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index 0b193f5882..87f20bee91 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -608,6 +608,7 @@ static bool resized = false; static bool resized_reload = false; static Size2 new_size; static Vector3 accelerometer; +static Vector3 gravity; static Vector3 magnetometer; static Vector3 gyroscope; static HashMap<String, JNISingleton *> jni_singletons; @@ -1012,6 +1013,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job os_android->process_accelerometer(accelerometer); + os_android->process_gravity(gravity); + os_android->process_magnetometer(magnetometer); os_android->process_gyroscope(gyroscope); @@ -1386,6 +1389,10 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv accelerometer = Vector3(x, y, z); } +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gravity(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) { + gravity = Vector3(x, y, z); +} + JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) { magnetometer = Vector3(x, y, z); } diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h index 0aa2489813..4790c65617 100644 --- a/platform/android/java_glue.h +++ b/platform/android/java_glue.h @@ -50,6 +50,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jobject obj, jint p_device, jboolean p_connected, jstring p_name); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jobject obj); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gravity(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv *env, jobject obj); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 970e0cdf68..a36df0675c 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -490,6 +490,11 @@ void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) { input->set_accelerometer(p_accelerometer); } +void OS_Android::process_gravity(const Vector3 &p_gravity) { + + input->set_gravity(p_gravity); +} + void OS_Android::process_magnetometer(const Vector3 &p_magnetometer) { input->set_magnetometer(p_magnetometer); diff --git a/platform/android/os_android.h b/platform/android/os_android.h index fee91b9a55..750afa7a14 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -219,6 +219,7 @@ public: virtual String get_system_dir(SystemDir p_dir) const; void process_accelerometer(const Vector3 &p_accelerometer); + void process_gravity(const Vector3 &p_gravity); void process_magnetometer(const Vector3 &p_magnetometer); void process_gyroscope(const Vector3 &p_gyroscope); void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points); diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index 058b162e83..08b01c6a4c 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -31,20 +31,7 @@ #include "engine.h" -void AudioStreamPlayer::_mix_audio() { - - if (!stream_playback.is_valid()) { - return; - } - - if (!active) { - return; - } - - if (setseek >= 0.0) { - stream_playback->start(setseek); - setseek = -1.0; //reset seek - } +void AudioStreamPlayer::_mix_internal(bool p_fadeout) { int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus); @@ -52,19 +39,24 @@ void AudioStreamPlayer::_mix_audio() { AudioFrame *buffer = mix_buffer.ptr(); int buffer_size = mix_buffer.size(); + if (p_fadeout) { + buffer_size = MIN(buffer_size, 16); //short fadeout ramp + } + //mix stream_playback->mix(buffer, 1.0, buffer_size); //multiply volume interpolating to avoid clicks if this changes + float target_volume = p_fadeout ? -80.0 : volume_db; float vol = Math::db2linear(mix_volume_db); - float vol_inc = (Math::db2linear(volume_db) - vol) / float(buffer_size); + float vol_inc = (Math::db2linear(target_volume) - vol) / float(buffer_size); for (int i = 0; i < buffer_size; i++) { buffer[i] *= vol; vol += vol_inc; } //set volume for next mix - mix_volume_db = volume_db; + mix_volume_db = target_volume; AudioFrame *targets[4] = { NULL, NULL, NULL, NULL }; @@ -95,6 +87,30 @@ void AudioStreamPlayer::_mix_audio() { } } +void AudioStreamPlayer::_mix_audio() { + + if (!stream_playback.is_valid()) { + return; + } + + if (!active) { + return; + } + + if (setseek >= 0.0) { + if (stream_playback->is_playing()) { + + //fade out to avoid pops + _mix_internal(true); + } + stream_playback->start(setseek); + setseek = -1.0; //reset seek + mix_volume_db = volume_db; //reset ramp + } + + _mix_internal(false); +} + void AudioStreamPlayer::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { @@ -163,7 +179,7 @@ float AudioStreamPlayer::get_volume_db() const { void AudioStreamPlayer::play(float p_from_pos) { if (stream_playback.is_valid()) { - mix_volume_db = volume_db; //reset volume ramp + //mix_volume_db = volume_db; do not reset volume ramp here, can cause clicks setseek = p_from_pos; active = true; set_process_internal(true); diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h index 4bfc44730d..6e9d623433 100644 --- a/scene/audio/audio_player.h +++ b/scene/audio/audio_player.h @@ -59,6 +59,7 @@ private: MixTarget mix_target; + void _mix_internal(bool p_fadeout); void _mix_audio(); static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer *>(self)->_mix_audio(); } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index f4876668f6..a568b6fab0 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -3668,6 +3668,11 @@ void TextEdit::set_readonly(bool p_readonly) { readonly = p_readonly; } +bool TextEdit::is_readonly() const { + + return readonly; +} + void TextEdit::set_wrap(bool p_wrap) { wrap = p_wrap; @@ -4914,6 +4919,8 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode); ClassDB::bind_method(D_METHOD("set_readonly", "enable"), &TextEdit::set_readonly); + ClassDB::bind_method(D_METHOD("is_readonly"), &TextEdit::is_readonly); + ClassDB::bind_method(D_METHOD("set_wrap", "enable"), &TextEdit::set_wrap); ClassDB::bind_method(D_METHOD("set_max_chars", "amount"), &TextEdit::set_max_chars); ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &TextEdit::set_context_menu_enabled); @@ -4964,6 +4971,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option); ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "readonly"), "set_readonly", "is_readonly"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled"); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 094474b264..b90571e0ab 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -448,6 +448,7 @@ public: bool cursor_is_block_mode() const; void set_readonly(bool p_readonly); + bool is_readonly() const; void set_max_chars(int p_max_chars); void set_wrap(bool p_wrap); diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index fdc3b79db6..f81f460521 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -31,17 +31,23 @@ void AudioStreamPlaybackSample::start(float p_from_pos) { - for (int i = 0; i < 2; i++) { - ima_adpcm[i].step_index = 0; - ima_adpcm[i].predictor = 0; - ima_adpcm[i].loop_step_index = 0; - ima_adpcm[i].loop_predictor = 0; - ima_adpcm[i].last_nibble = -1; - ima_adpcm[i].loop_pos = 0x7FFFFFFF; - ima_adpcm[i].window_ofs = 0; + if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) { + //no seeking in IMA_ADPCM + for (int i = 0; i < 2; i++) { + ima_adpcm[i].step_index = 0; + ima_adpcm[i].predictor = 0; + ima_adpcm[i].loop_step_index = 0; + ima_adpcm[i].loop_predictor = 0; + ima_adpcm[i].last_nibble = -1; + ima_adpcm[i].loop_pos = 0x7FFFFFFF; + ima_adpcm[i].window_ofs = 0; + } + + offset = 0; + } else { + seek(p_from_pos); } - seek(p_from_pos); sign = 1; active = true; } @@ -373,6 +379,14 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in dst_buff += target; } + + if (todo) { + //bit was missing from mix + int todo_ofs = p_frames - todo; + for (int i = todo_ofs; i < p_frames; i++) { + p_buffer[i] = AudioFrame(0, 0); + } + } } float AudioStreamPlaybackSample::get_length() const { diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 232f690074..fe59450f2e 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -1184,7 +1184,8 @@ Environment::Environment() { bg_energy = 1.0; bg_canvas_max_layer = 0; ambient_energy = 1.0; - ambient_sky_contribution = 1.0; + //ambient_sky_contribution = 1.0; + set_ambient_light_sky_contribution(1.0); tone_mapper = TONE_MAPPER_LINEAR; tonemap_exposure = 1.0; |