diff --git a/.gitignore b/.gitignore index 539003ca6b9..f1e173c5b21 100644 --- a/.gitignore +++ b/.gitignore @@ -154,6 +154,7 @@ gmon.out # Jetbrains IDEs .idea/ +.fleet/ # Kate *.kate-swp diff --git a/core/math/bvh_structs.inc b/core/math/bvh_structs.inc index b0d9ae36157..7b5cc2c3508 100644 --- a/core/math/bvh_structs.inc +++ b/core/math/bvh_structs.inc @@ -88,7 +88,11 @@ public: num_items++; return id; } +#ifdef DEV_ENABLED return -1; +#else + ERR_FAIL_V_MSG(0, "BVH request_item error."); +#endif } }; diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 5e9f692dadb..63d7e39c83f 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -353,6 +353,7 @@ Sorts the array. + [b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/wiki/Sorting_algorithm#Stability]stable[/url]. This means that values considered equal may have their order changed when using [method sort]. [b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural order). This may lead to unexpected behavior when sorting an array of strings ending with a sequence of numbers. Consider the following example: [codeblock] var strings = ["string1", "string2", "string10", "string11"] @@ -367,7 +368,8 @@ Sorts the array using a custom method. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return either [code]true[/code] or [code]false[/code]. For two elements [code]a[/code] and [code]b[/code], if the given method returns [code]true[/code], element [code]b[/code] will be after element [code]a[/code] in the array. - [b]Note:[/b] You cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior. + [b]Note:[/b] The sorting algorithm used is not [url=https://en.wikipedia.org/wiki/Sorting_algorithm#Stability]stable[/url]. This means that values considered equal may have their order changed when using [method sort_custom]. + [b]Note:[/b] You cannot randomize the return value as the heapsort algorithm expects a deterministic result. Randomizing the return value will result in unexpected behavior. [codeblock] class MyCustomSorter: static func sort_ascending(a, b): diff --git a/doc/classes/EditorScript.xml b/doc/classes/EditorScript.xml index 5fa00a6f6cc..29ea87a358f 100644 --- a/doc/classes/EditorScript.xml +++ b/doc/classes/EditorScript.xml @@ -15,6 +15,7 @@ print("Hello from the Godot Editor!") [/codeblock] [b]Note:[/b] The script is run in the Editor context, which means the output is visible in the console window started with the Editor (stdout) instead of the usual Godot [b]Output[/b] dock. + [b]Note:[/b] EditorScript is reference counted, meaning it is destroyed when nothing references it. This can cause errors during asynchronous operations if there are no references to the script. diff --git a/drivers/alsamidi/midi_driver_alsamidi.cpp b/drivers/alsamidi/midi_driver_alsamidi.cpp index 73f6a2eaa72..fa192e01d1f 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.cpp +++ b/drivers/alsamidi/midi_driver_alsamidi.cpp @@ -37,85 +37,135 @@ #include -static int get_message_size(uint8_t message) { - switch (message & 0xF0) { - case 0x80: // note off - case 0x90: // note on - case 0xA0: // aftertouch - case 0xB0: // continuous controller - case 0xE0: // pitch bend - case 0xF2: // song position pointer - return 3; +MIDIDriverALSAMidi::MessageCategory MIDIDriverALSAMidi::msg_category(uint8_t msg_part) { + if (msg_part >= 0xf8) { + return MessageCategory::RealTime; + } else if (msg_part >= 0xf0) { + // System Exclusive begin/end are specified as System Common Category messages, + // but we separate them here and give them their own categories as their + // behaviour is significantly different. + if (msg_part == 0xf0) { + return MessageCategory::SysExBegin; + } else if (msg_part == 0xf7) { + return MessageCategory::SysExEnd; + } + return MessageCategory::SystemCommon; + } else if (msg_part >= 0x80) { + return MessageCategory::Voice; + } + return MessageCategory::Data; +} - case 0xC0: // patch change - case 0xD0: // channel pressure - case 0xF1: // time code quarter frame - case 0xF3: // song select +size_t MIDIDriverALSAMidi::msg_expected_data(uint8_t status_byte) { + if (msg_category(status_byte) == MessageCategory::Voice) { + // Voice messages have a channel number in the status byte, mask it out. + status_byte &= 0xf0; + } + + switch (status_byte) { + case 0x80: // Note Off + case 0x90: // Note On + case 0xA0: // Polyphonic Key Pressure (Aftertouch) + case 0xB0: // Control Change (CC) + case 0xE0: // Pitch Bend Change + case 0xF2: // Song Position Pointer return 2; - case 0xF0: // SysEx start - case 0xF4: // reserved - case 0xF5: // reserved - case 0xF6: // tune request - case 0xF7: // SysEx end - case 0xF8: // timing clock - case 0xF9: // reserved - case 0xFA: // start - case 0xFB: // continue - case 0xFC: // stop - case 0xFD: // reserved - case 0xFE: // active sensing - case 0xFF: // reset + case 0xC0: // Program Change + case 0xD0: // Channel Pressure (Aftertouch) + case 0xF1: // MIDI Time Code Quarter Frame + case 0xF3: // Song Select return 1; } - return 256; + return 0; +} + +void MIDIDriverALSAMidi::InputConnection::parse_byte(uint8_t byte, MIDIDriverALSAMidi &driver, + uint64_t timestamp) { + switch (msg_category(byte)) { + case MessageCategory::RealTime: + // Real-Time messages are single byte messages that can + // occur at any point. + // We pass them straight through. + driver.receive_input_packet(timestamp, &byte, 1); + break; + + case MessageCategory::Data: + // We don't currently forward System Exclusive messages so skip their data. + // Collect any expected data for other message types. + if (!skipping_sys_ex && expected_data > received_data) { + buffer[received_data + 1] = byte; + received_data++; + + // Forward a complete message and reset relevant state. + if (received_data == expected_data) { + driver.receive_input_packet(timestamp, buffer, received_data + 1); + received_data = 0; + + if (msg_category(buffer[0]) != MessageCategory::Voice) { + // Voice Category messages can be sent with "running status". + // This means they don't resend the status byte until it changes. + // For other categories, we reset expected data, to require a new status byte. + expected_data = 0; + } + } + } + break; + + case MessageCategory::SysExBegin: + buffer[0] = byte; + skipping_sys_ex = true; + break; + + case MessageCategory::SysExEnd: + expected_data = 0; + skipping_sys_ex = false; + break; + + case MessageCategory::Voice: + case MessageCategory::SystemCommon: + buffer[0] = byte; + received_data = 0; + expected_data = msg_expected_data(byte); + skipping_sys_ex = false; + if (expected_data == 0) { + driver.receive_input_packet(timestamp, &byte, 1); + } + break; + } +} + +int MIDIDriverALSAMidi::InputConnection::read_in(MIDIDriverALSAMidi &driver, uint64_t timestamp) { + int ret; + do { + uint8_t byte = 0; + ret = snd_rawmidi_read(rawmidi_ptr, &byte, 1); + + if (ret < 0) { + if (ret != -EAGAIN) { + ERR_PRINT("snd_rawmidi_read error: " + String(snd_strerror(ret))); + } + } else { + parse_byte(byte, driver, timestamp); + } + } while (ret > 0); + + return ret; } void MIDIDriverALSAMidi::thread_func(void *p_udata) { MIDIDriverALSAMidi *md = (MIDIDriverALSAMidi *)p_udata; uint64_t timestamp = 0; - uint8_t buffer[256]; - int expected_size = 255; - int bytes = 0; while (!md->exit_thread.is_set()) { - int ret; - md->lock(); - for (int i = 0; i < md->connected_inputs.size(); i++) { - snd_rawmidi_t *midi_in = md->connected_inputs[i]; - do { - uint8_t byte = 0; - ret = snd_rawmidi_read(midi_in, &byte, 1); - if (ret < 0) { - if (ret != -EAGAIN) { - ERR_PRINT("snd_rawmidi_read error: " + String(snd_strerror(ret))); - } - } else { - if (byte & 0x80) { - // Flush previous packet if there is any - if (bytes) { - md->receive_input_packet(timestamp, buffer, bytes); - bytes = 0; - } - expected_size = get_message_size(byte); - // After a SysEx start, all bytes are data until a SysEx end, so - // we're going to end the command at the SES, and let the common - // driver ignore the following data bytes. - } + InputConnection *connections = md->connected_inputs.ptrw(); + size_t connection_count = md->connected_inputs.size(); - if (bytes < 256) { - buffer[bytes++] = byte; - // If we know the size of the current packet receive it if it reached the expected size - if (bytes >= expected_size) { - md->receive_input_packet(timestamp, buffer, bytes); - bytes = 0; - } - } - } - } while (ret > 0); + for (size_t i = 0; i < connection_count; i++) { + connections[i].read_in(*md, timestamp); } md->unlock(); @@ -139,7 +189,7 @@ Error MIDIDriverALSAMidi::open() { snd_rawmidi_t *midi_in; int ret = snd_rawmidi_open(&midi_in, nullptr, name, SND_RAWMIDI_NONBLOCK); if (ret >= 0) { - connected_inputs.insert(i++, midi_in); + connected_inputs.insert(i++, InputConnection(midi_in)); } } @@ -160,7 +210,7 @@ void MIDIDriverALSAMidi::close() { thread.wait_to_finish(); for (int i = 0; i < connected_inputs.size(); i++) { - snd_rawmidi_t *midi_in = connected_inputs[i]; + snd_rawmidi_t *midi_in = connected_inputs[i].rawmidi_ptr; snd_rawmidi_close(midi_in); } connected_inputs.clear(); @@ -179,7 +229,7 @@ PoolStringArray MIDIDriverALSAMidi::get_connected_inputs() { lock(); for (int i = 0; i < connected_inputs.size(); i++) { - snd_rawmidi_t *midi_in = connected_inputs[i]; + snd_rawmidi_t *midi_in = connected_inputs[i].rawmidi_ptr; snd_rawmidi_info_t *info; snd_rawmidi_info_malloc(&info); diff --git a/drivers/alsamidi/midi_driver_alsamidi.h b/drivers/alsamidi/midi_driver_alsamidi.h index 96554f462d8..0891ce48043 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.h +++ b/drivers/alsamidi/midi_driver_alsamidi.h @@ -46,12 +46,48 @@ class MIDIDriverALSAMidi : public MIDIDriver { Thread thread; Mutex mutex; - Vector connected_inputs; + class InputConnection { + public: + InputConnection() = default; + InputConnection(snd_rawmidi_t *midi_in) : + rawmidi_ptr{ midi_in } {} + + // Read in and parse available data, forwarding any complete messages through the driver. + int read_in(MIDIDriverALSAMidi &driver, uint64_t timestamp); + + snd_rawmidi_t *rawmidi_ptr = nullptr; + + private: + static const size_t MSG_BUFFER_SIZE = 3; + uint8_t buffer[MSG_BUFFER_SIZE] = { 0 }; + size_t expected_data = 0; + size_t received_data = 0; + bool skipping_sys_ex = false; + void parse_byte(uint8_t byte, MIDIDriverALSAMidi &driver, uint64_t timestamp); + }; + + Vector connected_inputs; SafeFlag exit_thread; static void thread_func(void *p_udata); + enum class MessageCategory { + Data, + Voice, + SysExBegin, + SystemCommon, // excluding System Exclusive Begin/End + SysExEnd, + RealTime, + }; + + // If the passed byte is a status byte, return the associated message category, + // else return MessageCategory::Data. + static MessageCategory msg_category(uint8_t msg_part); + + // Return the number of data bytes expected for the provided status byte. + static size_t msg_expected_data(uint8_t status_byte); + void lock() const; void unlock() const; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index e766c0a3a57..caf94e68c86 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -51,6 +51,7 @@ void EditorResourcePicker::_update_resource() { if (edited_resource == RES()) { assign_button->set_icon(Ref()); assign_button->set_text(TTR("[empty]")); + assign_button->set_tooltip(""); } else { assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object")); @@ -58,14 +59,15 @@ void EditorResourcePicker::_update_resource() { assign_button->set_text(edited_resource->get_name()); } else if (edited_resource->get_path().is_resource_file()) { assign_button->set_text(edited_resource->get_path().get_file()); - assign_button->set_tooltip(edited_resource->get_path()); } else { assign_button->set_text(edited_resource->get_class()); } + String resource_path; if (edited_resource->get_path().is_resource_file()) { - assign_button->set_tooltip(edited_resource->get_path()); + resource_path = edited_resource->get_path() + "\n"; } + assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class()); // Preview will override the above, so called at the end. EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id()); @@ -520,6 +522,8 @@ void EditorResourcePicker::_get_allowed_types(bool p_with_convert, Set * p_vector->insert("Texture"); } else if (base == "ShaderMaterial") { p_vector->insert("Shader"); + } else if (base == "Texture") { + p_vector->insert("Image"); } } } @@ -638,18 +642,35 @@ void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_ String at = E->get().strip_edges(); if (at == "SpatialMaterial" && ClassDB::is_parent_class(dropped_resource->get_class(), "Texture")) { - Ref mat = memnew(SpatialMaterial); + // Use existing resource if possible and only replace its data. + Ref mat = edited_resource; + if (mat.is_null()) { + mat.instance(); + } mat->set_texture(SpatialMaterial::TextureParam::TEXTURE_ALBEDO, dropped_resource); dropped_resource = mat; break; } if (at == "ShaderMaterial" && ClassDB::is_parent_class(dropped_resource->get_class(), "Shader")) { - Ref mat = memnew(ShaderMaterial); + Ref mat = edited_resource; + if (mat.is_null()) { + mat.instance(); + } mat->set_shader(dropped_resource); dropped_resource = mat; break; } + + if (at == "Texture" && ClassDB::is_parent_class(dropped_resource->get_class(), "Image")) { + Ref texture = edited_resource; + if (texture.is_null()) { + texture.instance(); + } + texture->create_from_image(dropped_resource); + dropped_resource = texture; + break; + } } } diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index 56826671cde..2e6d359f466 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -104,9 +104,10 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s file->get_buffer((uint8_t *)&riff, 4); //RIFF if (riff[0] != 'R' || riff[1] != 'I' || riff[2] != 'F' || riff[3] != 'F') { + uint64_t length = file->get_len(); file->close(); memdelete(file); - ERR_FAIL_V(ERR_FILE_UNRECOGNIZED); + ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Not a WAV file. File should start with 'RIFF', but found '%s', in file of size %d bytes", riff, length)); } /* GET FILESIZE */ @@ -114,14 +115,15 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s /* CHECK WAVE */ - char wave[4]; - - file->get_buffer((uint8_t *)&wave, 4); //RIFF + char wave[5]; + wave[4] = 0; + file->get_buffer((uint8_t *)&wave, 4); //WAVE if (wave[0] != 'W' || wave[1] != 'A' || wave[2] != 'V' || wave[3] != 'E') { + uint64_t length = file->get_len(); file->close(); memdelete(file); - ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Not a WAV file (no WAVE RIFF header)."); + ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Not a WAV file. Header should contain 'WAVE', but found '%s', in file of size %d bytes", wave, length)); } // Let users override potential loop points from the WAV. diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml index 2436a73d0d7..5eb7be2e5b8 100644 --- a/modules/gltf/doc_classes/GLTFState.xml +++ b/modules/gltf/doc_classes/GLTFState.xml @@ -208,6 +208,8 @@ + + diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index ed5de983cd8..bf4453fadf0 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -81,6 +81,8 @@ void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skeletons", "skeletons"), &GLTFState::set_skeletons); ClassDB::bind_method(D_METHOD("get_skeleton_to_node"), &GLTFState::get_skeleton_to_node); ClassDB::bind_method(D_METHOD("set_skeleton_to_node", "skeleton_to_node"), &GLTFState::set_skeleton_to_node); + ClassDB::bind_method(D_METHOD("get_create_animations"), &GLTFState::get_create_animations); + ClassDB::bind_method(D_METHOD("set_create_animations", "create_animations"), &GLTFState::set_create_animations); ClassDB::bind_method(D_METHOD("get_animations"), &GLTFState::get_animations); ClassDB::bind_method(D_METHOD("set_animations", "animations"), &GLTFState::set_animations); ClassDB::bind_method(D_METHOD("get_scene_node", "idx"), &GLTFState::get_scene_node); @@ -108,6 +110,7 @@ void GLTFState::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_animation_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_animation_names", "get_unique_animation_names"); // Set ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skeletons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeletons", "get_skeletons"); // Vector> ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "skeleton_to_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeleton_to_node", "get_skeleton_to_node"); // Map> } @@ -295,6 +298,14 @@ void GLTFState::set_skeleton_to_node(Dictionary p_skeleton_to_node) { GLTFTemplateConvert::set_from_dict(skeleton_to_node, p_skeleton_to_node); } +bool GLTFState::get_create_animations() { + return create_animations; +} + +void GLTFState::set_create_animations(bool p_create_animations) { + create_animations = p_create_animations; +} + Array GLTFState::get_animations() { return GLTFTemplateConvert::to_array(animations); } diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 3087a77751e..cd1ba2bf428 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -59,6 +59,7 @@ class GLTFState : public Resource { bool use_khr_texture_transform = false; bool use_legacy_names = false; uint32_t compress_flags = 0; + bool create_animations = true; Vector> nodes; Vector> buffers; @@ -166,6 +167,9 @@ public: Dictionary get_skeleton_to_node(); void set_skeleton_to_node(Dictionary p_skeleton_to_node); + bool get_create_animations(); + void set_create_animations(bool p_create_animations); + Array get_animations(); void set_animations(Array p_animations); diff --git a/modules/gltf/packed_scene_gltf.cpp b/modules/gltf/packed_scene_gltf.cpp index 409d938831e..a7f94b114ce 100644 --- a/modules/gltf/packed_scene_gltf.cpp +++ b/modules/gltf/packed_scene_gltf.cpp @@ -67,6 +67,7 @@ Node *PackedSceneGLTF::import_scene(const String &p_path, uint32_t p_flags, r_state->use_legacy_names = p_flags & EditorSceneImporter::IMPORT_USE_LEGACY_NAMES; r_state->compress_flags = p_compress_flags; + r_state->set_create_animations(p_flags & EditorSceneImporter::IMPORT_ANIMATION); Ref gltf_document; gltf_document.instance(); @@ -84,7 +85,7 @@ Node *PackedSceneGLTF::import_scene(const String &p_path, uint32_t p_flags, gltf_document->_generate_scene_node(r_state, root, root, r_state->root_nodes[root_i]); } gltf_document->_process_mesh_instances(r_state, root); - if (r_state->animations.size()) { + if (r_state->get_create_animations() && r_state->animations.size()) { AnimationPlayer *ap = memnew(AnimationPlayer); root->add_child(ap); ap->set_owner(root); diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp index a05664f475b..938d3ad6dda 100644 --- a/modules/tga/image_loader_tga.cpp +++ b/modules/tga/image_loader_tga.cpp @@ -100,7 +100,7 @@ Error ImageLoaderTGA::convert_to_image(Ref p_image, const uint8_t *p_buff uint32_t width = p_header.image_width; uint32_t height = p_header.image_height; tga_origin_e origin = static_cast((p_header.image_descriptor & TGA_ORIGIN_MASK) >> TGA_ORIGIN_SHIFT); - + uint8_t alpha_bits = p_header.image_descriptor & TGA_IMAGE_DESCRIPTOR_ALPHA_MASK; uint32_t x_start; int32_t x_step; uint32_t x_end; @@ -184,6 +184,27 @@ Error ImageLoaderTGA::convert_to_image(Ref p_image, const uint8_t *p_buff y += y_step; } } + } else if (p_header.pixel_depth == 16) { + while (y != y_end) { + while (x != x_end) { + if (i + 1 >= p_input_size) { + return ERR_PARSE_ERROR; + } + + // Always stored as RGBA5551 + uint8_t r = (p_buffer[i + 1] & 0x7c) << 1; + uint8_t g = ((p_buffer[i + 1] & 0x03) << 6) | ((p_buffer[i + 0] & 0xe0) >> 2); + uint8_t b = (p_buffer[i + 0] & 0x1f) << 3; + uint8_t a = (p_buffer[i + 1] & 0x80) ? 0xff : 0; + + TGA_PUT_PIXEL(r, g, b, alpha_bits ? a : 0xff); + + x += x_step; + i += 2; + } + x = x_start; + y += y_step; + } } else if (p_header.pixel_depth == 24) { while (y != y_end) { while (x != x_end) { @@ -286,7 +307,7 @@ Error ImageLoaderTGA::load_image(Ref p_image, FileAccess *f, bool p_force err = FAILED; } - if (!(tga_header.pixel_depth == 8 || tga_header.pixel_depth == 24 || tga_header.pixel_depth == 32)) { + if (!(tga_header.pixel_depth == 8 || tga_header.pixel_depth == 16 || tga_header.pixel_depth == 24 || tga_header.pixel_depth == 32)) { err = FAILED; } diff --git a/modules/tga/image_loader_tga.h b/modules/tga/image_loader_tga.h index 05957c1b303..475ea228d1d 100644 --- a/modules/tga/image_loader_tga.h +++ b/modules/tga/image_loader_tga.h @@ -36,6 +36,8 @@ /** @author SaracenOne */ +#define TGA_IMAGE_DESCRIPTOR_ALPHA_MASK 0xf + class ImageLoaderTGA : public ImageFormatLoader { enum tga_type_e { TGA_TYPE_NO_DATA = 0, diff --git a/platform/android/detect.py b/platform/android/detect.py index 274181a7d18..cbf76257852 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -126,11 +126,10 @@ def configure(env): # `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces # when using `target=release_debug`. opt = "-O3" if env["target"] == "release" else "-O2" - env.Append(CCFLAGS=[opt, "-fomit-frame-pointer"]) + env.Append(CCFLAGS=[opt]) elif env["optimize"] == "size": # optimize for size env.Append(CCFLAGS=["-Oz"]) env.Append(CPPDEFINES=["NDEBUG"]) - env.Append(CCFLAGS=["-ftree-vectorize"]) elif env["target"] == "debug": env.Append(LINKFLAGS=["-O0"]) env.Append(CCFLAGS=["-O0", "-g", "-fno-limit-debug-info"]) diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index 4652f4772b8..2b81fe5cbde 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -54,10 +54,10 @@ def configure(env): # `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces # when using `target=release_debug`. opt = "-O3" if env["target"] == "release" else "-O2" - env.Append(CCFLAGS=[opt, "-ftree-vectorize", "-fomit-frame-pointer"]) + env.Append(CCFLAGS=[opt]) env.Append(LINKFLAGS=[opt]) elif env["optimize"] == "size": # optimize for size - env.Append(CCFLAGS=["-Os", "-ftree-vectorize"]) + env.Append(CCFLAGS=["-Os"]) env.Append(LINKFLAGS=["-Os"]) elif env["target"] == "debug": diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 89662e23f93..5a3517ef369 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -43,9 +43,9 @@ def configure(env): if env["target"] == "release": if env["optimize"] == "speed": # optimize for speed (default) - env.Prepend(CCFLAGS=["-O3", "-fomit-frame-pointer", "-ftree-vectorize"]) + env.Prepend(CCFLAGS=["-O3"]) elif env["optimize"] == "size": # optimize for size - env.Prepend(CCFLAGS=["-Os", "-ftree-vectorize"]) + env.Prepend(CCFLAGS=["-Os"]) if env["arch"] != "arm64": env.Prepend(CCFLAGS=["-msse2"]) diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 44d568407d8..4bfed54122b 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -1337,7 +1337,6 @@ float AnimationPlayer::get_current_animation_length() const { void AnimationPlayer::_animation_changed() { clear_caches(); - emit_signal("caches_cleared"); if (is_playing()) { playback.seeked = true; //need to restart stuff, like audio } @@ -1376,6 +1375,8 @@ void AnimationPlayer::clear_caches() { cache_update_size = 0; cache_update_prop_size = 0; cache_update_bezier_size = 0; + + emit_signal("caches_cleared"); } void AnimationPlayer::set_active(bool p_active) { diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index f371824c029..b333b780d7c 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -713,7 +713,6 @@ void AnimationTree::_clear_caches() { memdelete(track_cache[*K]); } playing_caches.clear(); - track_cache.clear(); cache_valid = false; }