diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index 4e63566e970..a4715a229c1 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -132,7 +132,7 @@ void XMLParser::_parse_closing_xml_element() { ++P; const char *pBeginClose = P; - while (*P != '>') { + while (*P && *P != '>') { ++P; } @@ -140,7 +140,10 @@ void XMLParser::_parse_closing_xml_element() { #ifdef DEBUG_XML print_line("XML CLOSE: " + node_name); #endif - ++P; + + if (*P) { + ++P; + } } void XMLParser::_ignore_definition() { @@ -148,11 +151,14 @@ void XMLParser::_ignore_definition() { char *F = P; // move until end marked with '>' reached - while (*P != '>') { + while (*P && *P != '>') { ++P; } node_name.parse_utf8(F, P - F); - ++P; + + if (*P) { + ++P; + } } bool XMLParser::_parse_cdata() { @@ -170,6 +176,7 @@ bool XMLParser::_parse_cdata() { } if (!*P) { + node_name = ""; return true; } @@ -188,10 +195,9 @@ bool XMLParser::_parse_cdata() { } if (cDataEnd) { - node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin)); - } else { - node_name = ""; + cDataEnd = P; } + node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin)); #ifdef DEBUG_XML print_line("XML CDATA: " + node_name); #endif @@ -203,24 +209,45 @@ void XMLParser::_parse_comment() { node_type = NODE_COMMENT; P += 1; - char *pCommentBegin = P; + char *pEndOfInput = data + length; + char *pCommentBegin; + char *pCommentEnd; - int count = 1; + if (P + 1 < pEndOfInput && P[0] == '-' && P[1] == '-') { + // Comment, use '-->' as end. + pCommentBegin = P + 2; + for (pCommentEnd = pCommentBegin; pCommentEnd + 2 < pEndOfInput; pCommentEnd++) { + if (pCommentEnd[0] == '-' && pCommentEnd[1] == '-' && pCommentEnd[2] == '>') { + break; + } + } + if (pCommentEnd + 2 < pEndOfInput) { + P = pCommentEnd + 3; + } else { + P = pCommentEnd = pEndOfInput; + } + } else { + // Like document type definition, match angle brackets. + pCommentBegin = P; - // move until end of comment reached - while (count) { - if (*P == '>') { - --count; - } else if (*P == '<') { - ++count; + int count = 1; + while (*P && count) { + if (*P == '>') { + --count; + } else if (*P == '<') { + ++count; + } + ++P; } - ++P; + if (count) { + pCommentEnd = P; + } else { + pCommentEnd = P - 1; + } } - P -= 3; - node_name = String::utf8(pCommentBegin + 2, (int)(P - pCommentBegin - 2)); - P += 3; + node_name = String::utf8(pCommentBegin, (int)(pCommentEnd - pCommentBegin)); #ifdef DEBUG_XML print_line("XML COMMENT: " + node_name); #endif @@ -235,14 +262,14 @@ void XMLParser::_parse_opening_xml_element() { const char *startName = P; // find end of element - while (*P != '>' && !_is_white_space(*P)) { + while (*P && *P != '>' && !_is_white_space(*P)) { ++P; } const char *endName = P; // find attributes - while (*P != '>') { + while (*P && *P != '>') { if (_is_white_space(*P)) { ++P; } else { @@ -252,10 +279,14 @@ void XMLParser::_parse_opening_xml_element() { // read the attribute names const char *attributeNameBegin = P; - while (!_is_white_space(*P) && *P != '=') { + while (*P && !_is_white_space(*P) && *P != '=') { ++P; } + if (!*P) { + break; + } + const char *attributeNameEnd = P; ++P; @@ -266,7 +297,7 @@ void XMLParser::_parse_opening_xml_element() { } if (!*P) { // malformatted xml file - return; + break; } const char attributeQuoteChar = *P; @@ -278,12 +309,10 @@ void XMLParser::_parse_opening_xml_element() { ++P; } - if (!*P) { // malformatted xml file - return; - } - const char *attributeValueEnd = P; - ++P; + if (*P) { + ++P; + } Attribute attr; attr.name = String::utf8(attributeNameBegin, @@ -315,7 +344,9 @@ void XMLParser::_parse_opening_xml_element() { print_line("XML OPEN: " + node_name); #endif - ++P; + if (*P) { + ++P; + } } void XMLParser::_parse_current_node() { @@ -327,10 +358,6 @@ void XMLParser::_parse_current_node() { ++P; } - if (!*P) { - return; - } - if (P - start > 0) { // we found some text, store it if (_set_text(start, P)) { @@ -338,6 +365,10 @@ void XMLParser::_parse_current_node() { } } + if (!*P) { + return; + } + ++P; // based on current token, parse and report next element diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 813d5362c34..3e6d861f083 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -255,8 +255,8 @@ public: static _ALWAYS_INLINE_ double db2linear(double p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); } static _ALWAYS_INLINE_ float db2linear(float p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); } - static _ALWAYS_INLINE_ double round(double p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); } - static _ALWAYS_INLINE_ float round(float p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); } + static _ALWAYS_INLINE_ double round(double p_val) { return ::round(p_val); } + static _ALWAYS_INLINE_ float round(float p_val) { return ::roundf(p_val); } static _ALWAYS_INLINE_ int64_t wrapi(int64_t value, int64_t min, int64_t max) { int64_t range = max - min; @@ -376,28 +376,10 @@ public: return u.d; } - //this function should be as fast as possible and rounding mode should not matter + // This function should be as fast as possible and rounding mode should not matter. static _ALWAYS_INLINE_ int fast_ftoi(float a) { - static int b; - -#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603) || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // windows 8 phone? - b = (int)((a > 0.0) ? (a + 0.5) : (a - 0.5)); - -#elif defined(_MSC_VER) && _MSC_VER < 1800 - __asm fld a __asm fistp b - /*#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) - // use AT&T inline assembly style, document that - // we use memory as output (=m) and input (m) - __asm__ __volatile__ ( - "flds %1 \n\t" - "fistpl %0 \n\t" - : "=m" (b) - : "m" (a));*/ - -#else - b = lrintf(a); //assuming everything but msvc 2012 or earlier has lrint -#endif - return b; + // Assuming every supported compiler has `lrint()`. + return lrintf(a); } static _ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h) { diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 39d8d53204c..5bb216d4778 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -65,8 +65,8 @@ public: bool _set(const StringName &p_name, const Variant &p_value) { String name = p_name; - if (name.begins_with("bind/")) { - int which = name.get_slice("/", 1).to_int() - 1; + if (name.begins_with("bind/argument_")) { + int which = name.get_slice("_", 1).to_int() - 1; ERR_FAIL_INDEX_V(which, params.size(), false); params.write[which] = p_value; } else { @@ -79,8 +79,8 @@ public: bool _get(const StringName &p_name, Variant &r_ret) const { String name = p_name; - if (name.begins_with("bind/")) { - int which = name.get_slice("/", 1).to_int() - 1; + if (name.begins_with("bind/argument_")) { + int which = name.get_slice("_", 1).to_int() - 1; ERR_FAIL_INDEX_V(which, params.size(), false); r_ret = params[which]; } else { @@ -92,7 +92,7 @@ public: void _get_property_list(List *p_list) const { for (int i = 0; i < params.size(); i++) { - p_list->push_back(PropertyInfo(params[i].get_type(), "bind/" + itos(i + 1))); + p_list->push_back(PropertyInfo(params[i].get_type(), "bind/argument_" + itos(i + 1))); } } diff --git a/editor/editor_profiler.cpp b/editor/editor_profiler.cpp index f625c69cc0e..27009453143 100644 --- a/editor/editor_profiler.cpp +++ b/editor/editor_profiler.cpp @@ -613,23 +613,35 @@ Vector> EditorProfiler::get_data_as_csv() const { return res; } - // signatures - Vector signatures; - const Vector &categories = frame_metrics[0].categories; - - for (int j = 0; j < categories.size(); j++) { - const EditorProfiler::Metric::Category &c = categories[j]; - signatures.push_back(c.signature); - - for (int k = 0; k < c.items.size(); k++) { - signatures.push_back(c.items[k].signature); + // Different metrics may contain different number of categories. + Set possible_signatures; + for (int i = 0; i < frame_metrics.size(); i++) { + const Metric &m = frame_metrics[i]; + if (!m.valid) { + continue; } + for (Map::Element *E = m.category_ptrs.front(); E; E = E->next()) { + possible_signatures.insert(E->key()); + } + for (Map::Element *E = m.item_ptrs.front(); E; E = E->next()) { + possible_signatures.insert(E->key()); + } + } + + // Generate CSV header and cache indices. + Map sig_map; + Vector signatures; + signatures.resize(possible_signatures.size()); + int sig_index = 0; + for (const Set::Element *E = possible_signatures.front(); E; E = E->next()) { + signatures.write[sig_index] = E->get(); + sig_map[E->get()] = sig_index; + sig_index++; } res.push_back(signatures); // values Vector values; - values.resize(signatures.size()); int index = last_metric; @@ -640,20 +652,23 @@ Vector> EditorProfiler::get_data_as_csv() const { index = 0; } - if (!frame_metrics[index].valid) { + const Metric &m = frame_metrics[index]; + + if (!m.valid) { continue; } - int it = 0; - const Vector &frame_cat = frame_metrics[index].categories; - for (int j = 0; j < frame_cat.size(); j++) { - const EditorProfiler::Metric::Category &c = frame_cat[j]; - values.write[it++] = String::num_real(c.total_time); + // Don't keep old values since there may be empty cells. + values.clear(); + values.resize(possible_signatures.size()); - for (int k = 0; k < c.items.size(); k++) { - values.write[it++] = String::num_real(c.items[k].total); - } + for (Map::Element *E = m.category_ptrs.front(); E; E = E->next()) { + values.write[sig_map[E->key()]] = String::num_real(E->value()->total_time); } + for (Map::Element *E = m.item_ptrs.front(); E; E = E->next()) { + values.write[sig_map[E->key()]] = String::num_real(E->value()->total); + } + res.push_back(values); } diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 4c704022ceb..606f210ce3b 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -707,8 +707,10 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) { match_rect.position.y += 1 * EDSCALE; match_rect.size.y -= 2 * EDSCALE; - _results_display->draw_rect(match_rect, Color(0, 0, 0, 0.5)); - // Text is drawn by Tree already + // Use the inverted accent color to help match rectangles stand out even on the currently selected line. + _results_display->draw_rect(match_rect, get_color("accent_color", "Editor").inverted() * Color(1, 1, 1, 0.5)); + + // Text is drawn by Tree already. } void FindInFilesPanel::_on_item_edited() { diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index df220935f52..1398be5980d 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -1451,8 +1451,11 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b } } - ERR_FAIL_COND_V_MSG(img.is_null(), ERR_FILE_CORRUPT, - vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype)); + if (img.is_null()) { + ERR_PRINT(vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype)); + state.images.push_back(Ref()); + continue; + } Ref t; t.instance(); @@ -2356,6 +2359,9 @@ bool EditorSceneImporterGLTF::_skins_are_same(const Ref &skin_a, const Ref if (skin_a->get_bind_bone(i) != skin_b->get_bind_bone(i)) { return false; } + if (skin_a->get_bind_name(i) != skin_b->get_bind_name(i)) { + return false; + } Transform a_xform = skin_a->get_bind_pose(i); Transform b_xform = skin_b->get_bind_pose(i); @@ -3135,13 +3141,15 @@ void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Spatial const GLTFSkinIndex skin_i = node->skin; Map::Element *mi_element = state.scene_nodes.find(node_i); + ERR_CONTINUE_MSG(mi_element == nullptr, vformat("Unable to find node %d", node_i)); + MeshInstance *mi = Object::cast_to(mi_element->get()); - ERR_FAIL_COND(mi == nullptr); + ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to MeshInstance", node_i, mi_element->get()->get_class_name())); const GLTFSkeletonIndex skel_i = state.skins[node->skin].skeleton; const GLTFSkeleton &gltf_skeleton = state.skeletons[skel_i]; Skeleton *skeleton = gltf_skeleton.godot_skeleton; - ERR_FAIL_COND(skeleton == nullptr); + ERR_CONTINUE_MSG(skeleton == nullptr, vformat("Unable to find Skeleton for node %d skin %d", node_i, skin_i)); mi->get_parent()->remove_child(mi); skeleton->add_child(mi); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index e7c7e71c4b3..9e88c42ab12 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -80,10 +80,10 @@ void ViewportRotationControl::_notification(int p_what) { axis_menu_options.clear(); axis_menu_options.push_back(SpatialEditorViewport::VIEW_RIGHT); axis_menu_options.push_back(SpatialEditorViewport::VIEW_TOP); - axis_menu_options.push_back(SpatialEditorViewport::VIEW_FRONT); + axis_menu_options.push_back(SpatialEditorViewport::VIEW_REAR); axis_menu_options.push_back(SpatialEditorViewport::VIEW_LEFT); axis_menu_options.push_back(SpatialEditorViewport::VIEW_BOTTOM); - axis_menu_options.push_back(SpatialEditorViewport::VIEW_REAR); + axis_menu_options.push_back(SpatialEditorViewport::VIEW_FRONT); axis_colors.clear(); axis_colors.push_back(get_color("axis_x_color", "Editor")); diff --git a/misc/dist/osx/editor.entitlements b/misc/dist/osx/editor.entitlements new file mode 100644 index 00000000000..5496f65dcc3 --- /dev/null +++ b/misc/dist/osx/editor.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.device.audio-input + + com.apple.security.device.camera + + com.apple.security.cs.disable-library-validation + + + diff --git a/misc/dist/osx/editor_mono.entitlements b/misc/dist/osx/editor_mono.entitlements new file mode 100644 index 00000000000..c61c287652f --- /dev/null +++ b/misc/dist/osx/editor_mono.entitlements @@ -0,0 +1,18 @@ + + + + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + com.apple.security.device.audio-input + + com.apple.security.device.camera + + + diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 325aee8ad43..cdc9d0e84a9 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -2238,31 +2238,45 @@ MainLoop *OS_OSX::get_main_loop() const { } String OS_OSX::get_config_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well. if (has_environment("XDG_CONFIG_HOME")) { - return get_environment("XDG_CONFIG_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file("Library/Application Support"); - } else { - return "."; + if (get_environment("XDG_CONFIG_HOME").is_abs_path()) { + return get_environment("XDG_CONFIG_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Library/Application Support` or `.` per the XDG Base Directory specification."); + } } + if (has_environment("HOME")) { + return get_environment("HOME").plus_file("Library/Application Support"); + } + return "."; } String OS_OSX::get_data_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well. if (has_environment("XDG_DATA_HOME")) { - return get_environment("XDG_DATA_HOME"); - } else { - return get_config_path(); + if (get_environment("XDG_DATA_HOME").is_abs_path()) { + return get_environment("XDG_DATA_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification."); + } } + return get_config_path(); } String OS_OSX::get_cache_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well. if (has_environment("XDG_CACHE_HOME")) { - return get_environment("XDG_CACHE_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file("Library/Caches"); - } else { - return get_config_path(); + if (get_environment("XDG_CACHE_HOME").is_abs_path()) { + return get_environment("XDG_CACHE_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Libary/Caches` or `get_config_path()` per the XDG Base Directory specification."); + } } + if (has_environment("HOME")) { + return get_environment("HOME").plus_file("Library/Caches"); + } + return get_config_path(); } String OS_OSX::get_bundle_resource_dir() const { diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index c013e562462..952c83179b9 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -3316,31 +3316,45 @@ MainLoop *OS_Windows::get_main_loop() const { } String OS_Windows::get_config_path() const { - if (has_environment("XDG_CONFIG_HOME")) { // unlikely, but after all why not? - return get_environment("XDG_CONFIG_HOME"); - } else if (has_environment("APPDATA")) { - return get_environment("APPDATA"); - } else { - return "."; + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. + if (has_environment("XDG_CONFIG_HOME")) { + if (get_environment("XDG_CONFIG_HOME").is_abs_path()) { + return get_environment("XDG_CONFIG_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `%APPDATA%` or `.` per the XDG Base Directory specification."); + } } + if (has_environment("APPDATA")) { + return get_environment("APPDATA"); + } + return "."; } String OS_Windows::get_data_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. if (has_environment("XDG_DATA_HOME")) { - return get_environment("XDG_DATA_HOME"); - } else { - return get_config_path(); + if (get_environment("XDG_DATA_HOME").is_abs_path()) { + return get_environment("XDG_DATA_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification."); + } } + return get_config_path(); } String OS_Windows::get_cache_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. if (has_environment("XDG_CACHE_HOME")) { - return get_environment("XDG_CACHE_HOME"); - } else if (has_environment("TEMP")) { - return get_environment("TEMP"); - } else { - return get_config_path(); + if (get_environment("XDG_CACHE_HOME").is_abs_path()) { + return get_environment("XDG_CACHE_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `%TEMP%` or `get_config_path()` per the XDG Base Directory specification."); + } } + if (has_environment("TEMP")) { + return get_environment("TEMP"); + } + return get_config_path(); } // Get properly capitalized engine name for system paths diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 1a888ac504f..7a5c80e2cb2 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -3208,32 +3208,44 @@ bool OS_X11::_check_internal_feature_support(const String &p_feature) { String OS_X11::get_config_path() const { if (has_environment("XDG_CONFIG_HOME")) { - return get_environment("XDG_CONFIG_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file(".config"); - } else { - return "."; + if (get_environment("XDG_CONFIG_HOME").is_abs_path()) { + return get_environment("XDG_CONFIG_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.config` or `.` per the XDG Base Directory specification."); + } } + if (has_environment("HOME")) { + return get_environment("HOME").plus_file(".config"); + } + return "."; } String OS_X11::get_data_path() const { if (has_environment("XDG_DATA_HOME")) { - return get_environment("XDG_DATA_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file(".local/share"); - } else { - return get_config_path(); + if (get_environment("XDG_DATA_HOME").is_abs_path()) { + return get_environment("XDG_DATA_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.local/share` or `get_config_path()` per the XDG Base Directory specification."); + } } + if (has_environment("HOME")) { + return get_environment("HOME").plus_file(".local/share"); + } + return get_config_path(); } String OS_X11::get_cache_path() const { if (has_environment("XDG_CACHE_HOME")) { - return get_environment("XDG_CACHE_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file(".cache"); - } else { - return get_config_path(); + if (get_environment("XDG_CACHE_HOME").is_abs_path()) { + return get_environment("XDG_CACHE_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.cache` or `get_config_path()` per the XDG Base Directory specification."); + } } + if (has_environment("HOME")) { + return get_environment("HOME").plus_file(".cache"); + } + return get_config_path(); } String OS_X11::get_system_dir(SystemDir p_dir) const { diff --git a/thirdparty/misc/triangulator.cpp b/thirdparty/misc/triangulator.cpp index 75b2b064c4a..6710f592408 100644 --- a/thirdparty/misc/triangulator.cpp +++ b/thirdparty/misc/triangulator.cpp @@ -1166,7 +1166,7 @@ int TriangulatorPartition::MonotonePartition(List *inpolys, Li newedge.p1 = v->p; newedge.p2 = v->p; edgeIter = edgeTree.lower_bound(newedge); - if(edgeIter == edgeTree.front()) { + if(edgeIter == nullptr || edgeIter == edgeTree.front()) { error = true; break; } @@ -1202,7 +1202,7 @@ int TriangulatorPartition::MonotonePartition(List *inpolys, Li newedge.p1 = v->p; newedge.p2 = v->p; edgeIter = edgeTree.lower_bound(newedge); - if(edgeIter == edgeTree.front()) { + if(edgeIter == nullptr || edgeIter == edgeTree.front()) { error = true; break; } @@ -1241,7 +1241,7 @@ int TriangulatorPartition::MonotonePartition(List *inpolys, Li newedge.p1 = v->p; newedge.p2 = v->p; edgeIter = edgeTree.lower_bound(newedge); - if(edgeIter == edgeTree.front()) { + if(edgeIter == nullptr || edgeIter == edgeTree.front()) { error = true; break; }