diff options
28 files changed, 643 insertions, 203 deletions
diff --git a/SConstruct b/SConstruct index c05a4332ab..9d536e0d16 100644 --- a/SConstruct +++ b/SConstruct @@ -11,7 +11,8 @@ import glob import sys import methods -methods.update_version() +# moved below to compensate with module version string +# methods.update_version() # scan possible build platforms @@ -87,6 +88,7 @@ env_base.android_appattributes_chunk = "" env_base.disabled_modules = [] env_base.use_ptrcall = False env_base.split_drivers = False +env_base.module_version_string = "" # To decide whether to rebuild a file, use the MD5 sum only if the timestamp has changed. # http://scons.org/doc/production/HTML/scons-user/ch06.html#idm139837621851792 @@ -111,6 +113,8 @@ env_base.__class__.android_add_gradle_plugin = methods.android_add_gradle_plugin env_base.__class__.android_add_gradle_classpath = methods.android_add_gradle_classpath env_base.__class__.disable_module = methods.disable_module +env_base.__class__.add_module_version_string = methods.add_module_version_string + env_base.__class__.add_source_files = methods.add_source_files env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix env_base.__class__.split_lib = methods.split_lib @@ -139,6 +143,7 @@ opts.Add('p', "Platform (alias for 'platform')", '') opts.Add('platform', "Target platform (%s)" % ('|'.join(platform_list), ), '') opts.Add(EnumVariable('target', "Compilation target", 'debug', ('debug', 'release_debug', 'release'))) opts.Add(BoolVariable('tools', "Build the tools a.k.a. the Godot editor", True)) +opts.Add(BoolVariable('use_lto', 'Use linking time optimization', False)) # Components opts.Add(BoolVariable('deprecated', "Enable deprecated features", True)) @@ -358,11 +363,6 @@ if selected_platform in platform_list: suffix += env.extra_suffix - env["PROGSUFFIX"] = suffix + env["PROGSUFFIX"] - env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"] - env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"] - env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"] - sys.path.remove("./platform/" + selected_platform) sys.modules.pop('detect') @@ -391,6 +391,15 @@ if selected_platform in platform_list: sys.path.remove(tmppath) sys.modules.pop('config') + methods.update_version(env.module_version_string) + + suffix += env.module_version_string + + env["PROGSUFFIX"] = suffix + env["PROGSUFFIX"] + env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"] + env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"] + env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"] + if (env.use_ptrcall): env.Append(CPPFLAGS=['-DPTRCALL_ENABLED']) diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index daa6b01d6e..b5d41bacbb 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -75,7 +75,7 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V } else { if (!values.has(p_section)) { - values[p_section] = Map<String, Variant>(); + values[p_section] = OrderedHashMap<String, Variant>(); } values[p_section][p_key] = p_value; @@ -106,7 +106,7 @@ bool ConfigFile::has_section_key(const String &p_section, const String &p_key) c void ConfigFile::get_sections(List<String> *r_sections) const { - for (const Map<String, Map<String, Variant> >::Element *E = values.front(); E; E = E->next()) { + for (const Map<String, OrderedHashMap<String, Variant> >::Element *E = values.front(); E; E = E->next()) { r_sections->push_back(E->key()); } } @@ -114,8 +114,8 @@ void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) ERR_FAIL_COND(!values.has(p_section)); - for (const Map<String, Variant>::Element *E = values[p_section].front(); E; E = E->next()) { - r_keys->push_back(E->key()); + for (OrderedHashMap<String, Variant>::ConstElement E = values[p_section].front(); E; E = E.next()) { + r_keys->push_back(E.key()); } } @@ -135,17 +135,17 @@ Error ConfigFile::save(const String &p_path) { return err; } - for (Map<String, Map<String, Variant> >::Element *E = values.front(); E; E = E->next()) { + for (Map<String, OrderedHashMap<String, Variant> >::Element *E = values.front(); E; E = E->next()) { if (E != values.front()) file->store_string("\n"); file->store_string("[" + E->key() + "]\n\n"); - for (Map<String, Variant>::Element *F = E->get().front(); F; F = F->next()) { + for (OrderedHashMap<String, Variant>::Element F = E->get().front(); F; F = F.next()) { String vstr; - VariantWriter::write_to_string(F->get(), vstr); - file->store_string(F->key() + "=" + vstr + "\n"); + VariantWriter::write_to_string(F.get(), vstr); + file->store_string(F.key() + "=" + vstr + "\n"); } } diff --git a/core/io/config_file.h b/core/io/config_file.h index 8ed8a069e4..2be196faa2 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -30,13 +30,14 @@ #ifndef CONFIG_FILE_H #define CONFIG_FILE_H +#include "core/ordered_hash_map.h" #include "reference.h" class ConfigFile : public Reference { GDCLASS(ConfigFile, Reference); - Map<String, Map<String, Variant> > values; + Map<String, OrderedHashMap<String, Variant> > values; PoolStringArray _get_sections() const; PoolStringArray _get_section_keys(const String &p_section) const; diff --git a/core/ordered_hash_map.h b/core/ordered_hash_map.h index 9e95f963e1..62eeedb437 100644 --- a/core/ordered_hash_map.h +++ b/core/ordered_hash_map.h @@ -181,7 +181,7 @@ public: }; ConstElement find(const K &p_key) const { - typename InternalList::Element **list_element = map.getptr(p_key); + typename InternalList::Element *const *list_element = map.getptr(p_key); if (list_element) { return ConstElement(*list_element); } diff --git a/core/version.h b/core/version.h index 436f30ef01..7d2c47df6a 100644 --- a/core/version.h +++ b/core/version.h @@ -30,8 +30,8 @@ #include "version_generated.gen.h" #ifdef VERSION_PATCH -#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION) +#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION) VERSION_MODULE_CONFIG #else -#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION) +#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION) VERSION_MODULE_CONFIG #endif // VERSION_PATCH #define VERSION_FULL_NAME "" _MKSTR(VERSION_NAME) " v" VERSION_MKSTRING diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index d867404f3d..164d02c580 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -31,10 +31,10 @@ #include "editor_node.h" #include "editor_scale.h" +#include "io/json.h" #include "io/zip_io.h" #include "os/dir_access.h" #include "version.h" - void ExportTemplateManager::_update_template_list() { while (current_hb->get_child_count()) { @@ -66,7 +66,7 @@ void ExportTemplateManager::_update_template_list() { memdelete(d); - String current_version = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + _MKSTR(VERSION_STATUS); + String current_version = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + _MKSTR(VERSION_STATUS) + VERSION_MODULE_CONFIG; Label *current = memnew(Label); current->set_h_size_flags(SIZE_EXPAND_FILL); @@ -120,6 +120,16 @@ void ExportTemplateManager::_update_template_list() { void ExportTemplateManager::_download_template(const String &p_version) { print_line("download " + p_version); + while (template_list->get_child_count()) { + memdelete(template_list->get_child(0)); + } + template_downloader->popup_centered_minsize(); + template_list_state->set_text(TTR("Retrieving mirrors, please wait..")); + template_download_progress->set_max(100); + template_download_progress->set_value(0); + request_mirror->request("https://www.godotengine.org/download_mirrors.php?version=" + p_version); + template_list_state->show(); + template_download_progress->show(); } void ExportTemplateManager::_uninstall_template(const String &p_version) { @@ -307,12 +317,195 @@ void ExportTemplateManager::ok_pressed() { template_open->popup_centered_ratio(); } +void ExportTemplateManager::_http_download_mirror_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data) { + + print_line("mirror complete"); + String mirror_str = "{ \"mirrors\":[{\"name\":\"Official\",\"url\":\"http://op.godotengine.org:81/downloads/2.1.4/Godot_v2.1.4-stable_linux_server.64.zip\"}] }"; + + template_list_state->hide(); + template_download_progress->hide(); + + Variant r; + String errs; + int errline; + Error err = JSON::parse(mirror_str, r, errs, errline); + if (err != OK) { + EditorNode::get_singleton()->show_warning("Error parsing JSON with mirror list. Please report this issue!"); + return; + } + + bool mirrors_found = false; + + Dictionary d = r; + print_line(r); + if (d.has("mirrors")) { + Array mirrors = d["mirrors"]; + for (int i = 0; i < mirrors.size(); i++) { + Dictionary m = mirrors[i]; + ERR_CONTINUE(!m.has("url") || !m.has("name")); + LinkButton *lb = memnew(LinkButton); + lb->set_text(m["name"]); + lb->connect("pressed", this, "_begin_template_download", varray(m["url"])); + template_list->add_child(lb); + mirrors_found = true; + } + } + + if (!mirrors_found) { + EditorNode::get_singleton()->show_warning(TTR("No download links found for this version. Direct download is only available for official releases.")); + return; + } +} +void ExportTemplateManager::_http_download_templates_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data) { + + switch (p_status) { + + case HTTPRequest::RESULT_CANT_RESOLVE: { + template_list_state->set_text(TTR("Can't resolve.")); + } break; + case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED: + case HTTPRequest::RESULT_CONNECTION_ERROR: + case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH: { + template_list_state->set_text(TTR("Can't connect.")); + } break; + case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR: + case HTTPRequest::RESULT_CANT_CONNECT: { + template_list_state->set_text(TTR("Can't connect.")); + } break; + case HTTPRequest::RESULT_NO_RESPONSE: { + template_list_state->set_text(TTR("No response.")); + } break; + case HTTPRequest::RESULT_REQUEST_FAILED: { + template_list_state->set_text(TTR("Req. Failed.")); + } break; + case HTTPRequest::RESULT_REDIRECT_LIMIT_REACHED: { + template_list_state->set_text(TTR("Redirect Loop.")); + } break; + default: { + if (p_code != 200) { + template_list_state->set_text(TTR("Failed:") + " " + itos(p_code)); + } else { + String path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("tmp_templates.tpz"); + FileAccess *f = FileAccess::open(path, FileAccess::WRITE); + if (!f) { + template_list_state->set_text(TTR("Can't write file.")); + } else { + int size = p_data.size(); + PoolVector<uint8_t>::Read r = p_data.read(); + f->store_buffer(r.ptr(), size); + memdelete(f); + template_list_state->set_text(TTR("Download Complete.")); + template_downloader->hide(); + _install_from_file(path); + } + } + } break; + } + + set_process(false); +} + +void ExportTemplateManager::_begin_template_download(const String &p_url) { + + for (int i = 0; i < template_list->get_child_count(); i++) { + BaseButton *b = Object::cast_to<BaseButton>(template_list->get_child(0)); + if (b) { + b->set_disabled(true); + } + } + + download_data.clear(); + + Error err = download_templates->request(p_url); + if (err != OK) { + EditorNode::get_singleton()->show_warning(TTR("Error requesting url: ") + p_url); + return; + } + + set_process(true); + + template_list_state->show(); + template_download_progress->set_max(100); + template_download_progress->set_value(0); + template_download_progress->show(); + template_list_state->set_text(TTR("Connecting to Mirror..")); +} + +void ExportTemplateManager::_notification(int p_what) { + + if (p_what == NOTIFICATION_PROCESS) { + + update_countdown -= get_process_delta_time(); + + if (update_countdown > 0) { + return; + } + update_countdown = 0.5; + String status; + bool errored = false; + + switch (download_templates->get_http_client_status()) { + case HTTPClient::STATUS_DISCONNECTED: + status = TTR("Disconnected"); + errored = true; + break; + case HTTPClient::STATUS_RESOLVING: status = TTR("Resolving"); break; + case HTTPClient::STATUS_CANT_RESOLVE: + status = TTR("Can't Resolve"); + errored = true; + break; + case HTTPClient::STATUS_CONNECTING: status = TTR("Connecting.."); break; + case HTTPClient::STATUS_CANT_CONNECT: + status = TTR("Can't Conect"); + errored = true; + break; + case HTTPClient::STATUS_CONNECTED: status = TTR("Connected"); break; + case HTTPClient::STATUS_REQUESTING: status = TTR("Requesting.."); break; + case HTTPClient::STATUS_BODY: + status = TTR("Downloading"); + if (download_templates->get_body_size() > 0) { + status += " " + String::humanize_size(download_templates->get_downloaded_bytes()) + "/" + String::humanize_size(download_templates->get_body_size()); + template_download_progress->set_max(download_templates->get_body_size()); + template_download_progress->set_value(download_templates->get_downloaded_bytes()); + } else { + status += " " + String::humanize_size(download_templates->get_downloaded_bytes()); + } + break; + case HTTPClient::STATUS_CONNECTION_ERROR: + status = TTR("Connection Error"); + errored = true; + break; + case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR: + status = TTR("SSL Handshake Error"); + errored = true; + break; + } + + template_list_state->set_text(status); + if (errored) { + set_process(false); + ; + } + } + + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (!is_visible_in_tree()) { + print_line("closed"); + download_templates->cancel_request(); + set_process(false); + } + } +} + void ExportTemplateManager::_bind_methods() { ClassDB::bind_method("_download_template", &ExportTemplateManager::_download_template); ClassDB::bind_method("_uninstall_template", &ExportTemplateManager::_uninstall_template); ClassDB::bind_method("_uninstall_template_confirm", &ExportTemplateManager::_uninstall_template_confirm); ClassDB::bind_method("_install_from_file", &ExportTemplateManager::_install_from_file); + ClassDB::bind_method("_http_download_mirror_completed", &ExportTemplateManager::_http_download_mirror_completed); + ClassDB::bind_method("_http_download_templates_completed", &ExportTemplateManager::_http_download_templates_completed); + ClassDB::bind_method("_begin_template_download", &ExportTemplateManager::_begin_template_download); } ExportTemplateManager::ExportTemplateManager() { @@ -350,4 +543,33 @@ ExportTemplateManager::ExportTemplateManager() { set_title(TTR("Export Template Manager")); set_hide_on_ok(false); + + request_mirror = memnew(HTTPRequest); + add_child(request_mirror); + request_mirror->connect("request_completed", this, "_http_download_mirror_completed"); + + download_templates = memnew(HTTPRequest); + add_child(download_templates); + download_templates->connect("request_completed", this, "_http_download_templates_completed"); + + template_downloader = memnew(AcceptDialog); + template_downloader->set_title(TTR("Download Templates")); + template_downloader->get_ok()->set_text(TTR("Close")); + add_child(template_downloader); + + VBoxContainer *vbc = memnew(VBoxContainer); + template_downloader->add_child(vbc); + ScrollContainer *sc = memnew(ScrollContainer); + sc->set_custom_minimum_size(Size2(400, 200) * EDSCALE); + vbc->add_margin_child(TTR("Select mirror from list: "), sc); + template_list = memnew(VBoxContainer); + sc->add_child(template_list); + sc->set_enable_v_scroll(true); + sc->set_enable_h_scroll(false); + template_list_state = memnew(Label); + vbc->add_child(template_list_state); + template_download_progress = memnew(ProgressBar); + vbc->add_child(template_download_progress); + + update_countdown = 0; } diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h index c77f85688f..644c6b466b 100644 --- a/editor/export_template_manager.h +++ b/editor/export_template_manager.h @@ -33,13 +33,20 @@ #include "editor/editor_settings.h" #include "scene/gui/dialogs.h" #include "scene/gui/file_dialog.h" +#include "scene/gui/progress_bar.h" #include "scene/gui/scroll_container.h" +#include "scene/main/http_request.h" class ExportTemplateVersion; class ExportTemplateManager : public ConfirmationDialog { GDCLASS(ExportTemplateManager, ConfirmationDialog) + AcceptDialog *template_downloader; + VBoxContainer *template_list; + Label *template_list_state; + ProgressBar *template_download_progress; + ScrollContainer *installed_scroll; VBoxContainer *installed_vb; HBoxContainer *current_hb; @@ -48,6 +55,13 @@ class ExportTemplateManager : public ConfirmationDialog { ConfirmationDialog *remove_confirm; String to_remove; + HTTPRequest *request_mirror; + HTTPRequest *download_templates; + + Vector<uint8_t> download_data; + + float update_countdown; + void _update_template_list(); void _download_template(const String &p_version); @@ -57,7 +71,13 @@ class ExportTemplateManager : public ConfirmationDialog { virtual void ok_pressed(); void _install_from_file(const String &p_file); + void _http_download_mirror_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data); + void _http_download_templates_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data); + + void _begin_template_download(const String &p_url); + protected: + void _notification(int p_what); static void _bind_methods(); public: diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 62d77f56bc..00cbd9bb72 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -595,10 +595,10 @@ void FileSystemDock::_select_file(int p_idx) { current_path->set_text(path); _push_to_history(); } else { - if (ResourceLoader::get_resource_type(path) == "PackedScene") { - editor->open_request(path); + if (ResourceLoader::get_resource_type(fpath) == "PackedScene") { + editor->open_request(fpath); } else { - editor->load_resource(path); + editor->load_resource(fpath); } } } diff --git a/editor/icons/icon_editor_handle_add.svg b/editor/icons/icon_editor_handle_add.svg new file mode 100644 index 0000000000..0e7fe7129a --- /dev/null +++ b/editor/icons/icon_editor_handle_add.svg @@ -0,0 +1,6 @@ +<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> + <g transform="translate(0 -1044.4)"> + <ellipse cx="4" cy="1048.4" rx="4" ry="4" fill="#fff"/> + <ellipse cx="4" cy="1048.4" rx="2.8572" ry="2.8571" fill="#84ff84"/> + </g> +</svg> diff --git a/editor/icons/icon_editor_handle_selected.svg b/editor/icons/icon_editor_handle_selected.svg new file mode 100644 index 0000000000..8d338c1fbd --- /dev/null +++ b/editor/icons/icon_editor_handle_selected.svg @@ -0,0 +1,6 @@ +<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> + <g transform="translate(0 -1044.4)"> + <ellipse cx="4" cy="1048.4" rx="4" ry="4" fill="#fff"/> + <ellipse cx="4" cy="1048.4" rx="2.8572" ry="2.8571" fill="#8484ff"/> + </g> +</svg> diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index ffa4e36b5a..2f839b96cf 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -30,6 +30,49 @@ #include "abstract_polygon_2d_editor.h" #include "canvas_item_editor_plugin.h" +#include "core/os/keyboard.h" + +AbstractPolygon2DEditor::Vertex::Vertex() + : polygon(-1), vertex(-1) { + // invalid vertex +} + +AbstractPolygon2DEditor::Vertex::Vertex(int p_vertex) + : polygon(-1), vertex(p_vertex) { + // vertex p_vertex of current wip polygon +} + +AbstractPolygon2DEditor::Vertex::Vertex(int p_polygon, int p_vertex) + : polygon(p_polygon), vertex(p_vertex) { + // vertex p_vertex of polygon p_polygon +} + +bool AbstractPolygon2DEditor::Vertex::operator==(const AbstractPolygon2DEditor::Vertex &p_vertex) const { + + return polygon == p_vertex.polygon && vertex == p_vertex.vertex; +} + +bool AbstractPolygon2DEditor::Vertex::operator!=(const AbstractPolygon2DEditor::Vertex &p_vertex) const { + + return !(*this == p_vertex); +} + +bool AbstractPolygon2DEditor::Vertex::valid() const { + + return vertex >= 0; +} + +AbstractPolygon2DEditor::PosVertex::PosVertex() { + // invalid vertex +} + +AbstractPolygon2DEditor::PosVertex::PosVertex(const Vertex &p_vertex, const Vector2 &p_pos) + : Vertex(p_vertex.polygon, p_vertex.vertex), pos(p_pos) { +} + +AbstractPolygon2DEditor::PosVertex::PosVertex(int p_polygon, int p_vertex, const Vector2 &p_pos) + : Vertex(p_polygon, p_vertex), pos(p_pos) { +} bool AbstractPolygon2DEditor::_is_empty() const { @@ -171,7 +214,10 @@ void AbstractPolygon2DEditor::_wip_close() { wip.clear(); wip_active = false; - edited_point = -1; + + edited_point = PosVertex(); + hover_point = Vertex(); + selected_point = Vertex(); } bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { @@ -197,9 +243,6 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Vector2 gpoint = mb->get_position(); Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); - //first check if a point is to be added (segment split) - real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - if (mode == MODE_CREATE) { if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { @@ -209,13 +252,16 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) wip.clear(); wip.push_back(cpoint); wip_active = true; - edited_point_pos = cpoint; - edited_polygon = -1; - edited_point = 1; + edited_point = PosVertex(-1, 1, cpoint); canvas_item_editor->get_viewport_control()->update(); + hover_point = Vertex(); + selected_point = Vertex(0); + edge_point = PosVertex(); return true; } else { + const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { //wip closed _wip_close(); @@ -224,7 +270,8 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } else { wip.push_back(cpoint); - edited_point = wip.size(); + edited_point = PosVertex(-1, wip.size(), cpoint); + selected_point = Vertex(wip.size() - 1); canvas_item_editor->get_viewport_control()->update(); return true; @@ -240,66 +287,31 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) if (mb->is_pressed()) { - if (mb->get_control()) { - - const int n_polygons = _get_polygon_count(); + const PosVertex insert = closest_edge_point(gpoint); - if (n_polygons >= 1) { + if (insert.valid()) { - Vector<Vector2> vertices = _get_polygon(n_polygons - 1); + Vector<Vector2> vertices = _get_polygon(insert.polygon); - if (vertices.size() < 3) { - - vertices.push_back(cpoint); - undo_redo->create_action(TTR("Edit Poly")); - _action_set_polygon(n_polygons - 1, vertices); - _commit_action(); - return true; - } - } - - //search edges - int closest_poly = -1; - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - - for (int j = 0; j < n_polygons; j++) { - - PoolVector<Vector2> points = _get_polygon(j); - const Vector2 offset = _get_offset(j); - const int n_points = points.size(); - - for (int i = 0; i < n_points; i++) { - - Vector2 p[2] = { xform.xform(points[i] + offset), - xform.xform(points[(i + 1) % n_points] + offset) }; - - Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, p); - if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2) - continue; //not valid to reuse point - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_poly = j; - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - } + if (vertices.size() < 3) { - if (closest_idx >= 0) { + vertices.push_back(cpoint); + undo_redo->create_action(TTR("Edit Poly")); + selected_point = Vertex(insert.polygon, vertices.size()); + _action_set_polygon(insert.polygon, vertices); + _commit_action(); + return true; + } else { - Vector<Vector2> vertices = _get_polygon(closest_poly); + Vector<Vector2> vertices = _get_polygon(insert.polygon); pre_move_edit = vertices; - vertices.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos)); - edited_point = closest_idx + 1; - edited_polygon = closest_poly; - edited_point_pos = xform.affine_inverse().xform(closest_pos); + edited_point = PosVertex(insert.polygon, insert.vertex + 1, xform.affine_inverse().xform(insert.pos)); + vertices.insert(edited_point.vertex, edited_point.pos); + selected_point = edited_point; + edge_point = PosVertex(); undo_redo->create_action(TTR("Insert Point")); - _action_set_polygon(closest_poly, vertices); + _action_set_polygon(insert.polygon, vertices); _commit_action(); return true; @@ -307,134 +319,120 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } else { //look for points to move - int closest_poly = -1; - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - - const int n_polygons = _get_polygon_count(); - - for (int j = 0; j < n_polygons; j++) { - - PoolVector<Vector2> points = _get_polygon(j); - const Vector2 offset = _get_offset(j); - const int n_points = points.size(); - - for (int i = 0; i < n_points; i++) { - - Vector2 cp = xform.xform(points[i] + offset); - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_poly = j; - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - } + const PosVertex closest = closest_point(gpoint); - if (closest_idx >= 0) { + if (closest.valid()) { - pre_move_edit = _get_polygon(closest_poly); - edited_polygon = closest_poly; - edited_point = closest_idx; - edited_point_pos = xform.affine_inverse().xform(closest_pos); + pre_move_edit = _get_polygon(closest.polygon); + edited_point = PosVertex(closest, xform.affine_inverse().xform(closest.pos)); + selected_point = closest; + edge_point = PosVertex(); canvas_item_editor->get_viewport_control()->update(); return true; + } else { + + selected_point = Vertex(); } } } else { - if (edited_point != -1) { + if (edited_point.valid()) { //apply - Vector<Vector2> vertices = _get_polygon(edited_polygon); - ERR_FAIL_INDEX_V(edited_point, vertices.size(), false); - vertices[edited_point] = edited_point_pos - _get_offset(edited_polygon); + Vector<Vector2> vertices = _get_polygon(edited_point.polygon); + ERR_FAIL_INDEX_V(edited_point.vertex, vertices.size(), false); + vertices[edited_point.vertex] = edited_point.pos - _get_offset(edited_point.polygon); undo_redo->create_action(TTR("Edit Poly")); - _action_set_polygon(edited_polygon, pre_move_edit, vertices); + _action_set_polygon(edited_point.polygon, pre_move_edit, vertices); _commit_action(); - edited_point = -1; + edited_point = PosVertex(); return true; } } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) { + } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && !edited_point.valid()) { + + const PosVertex closest = closest_point(gpoint); + + if (closest.valid()) { + + remove_point(closest); + return true; + } + } + } + } - int closest_poly = -1; - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - const int n_polygons = _get_polygon_count(); + Ref<InputEventMouseMotion> mm = p_event; - for (int j = 0; j < n_polygons; j++) { + if (mm.is_valid()) { - PoolVector<Vector2> points = _get_polygon(j); - const int n_points = points.size(); - const Vector2 offset = _get_offset(j); + Vector2 gpoint = mm->get_position(); - for (int i = 0; i < n_points; i++) { + if (edited_point.valid() && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) { - Vector2 cp = xform.xform(points[i] + offset); + Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint))); + edited_point = PosVertex(edited_point, cpoint); - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_poly = j; - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - } + if (!wip_active) { - if (closest_idx >= 0) { + Vector<Vector2> vertices = _get_polygon(edited_point.polygon); + ERR_FAIL_INDEX_V(edited_point.vertex, vertices.size(), false); + vertices[edited_point.vertex] = cpoint - _get_offset(edited_point.polygon); + _set_polygon(edited_point.polygon, vertices); + } - PoolVector<Vector2> vertices = _get_polygon(closest_poly); + canvas_item_editor->get_viewport_control()->update(); + } else if (mode == MODE_EDIT) { - if (vertices.size() > 3) { + const PosVertex onEdgeVertex = closest_edge_point(gpoint); - vertices.remove(closest_idx); + if (onEdgeVertex.valid()) { - undo_redo->create_action(TTR("Edit Poly (Remove Point)")); - _action_set_polygon(closest_poly, vertices); - _commit_action(); - } else { + hover_point = Vertex(); + edge_point = onEdgeVertex; + canvas_item_editor->get_viewport_control()->update(); + } else { - undo_redo->create_action(TTR("Remove Poly And Point")); - _action_remove_polygon(closest_poly); - _commit_action(); - } + if (edge_point.valid()) { - if (_is_empty()) - _menu_option(MODE_CREATE); - return true; + edge_point = PosVertex(); + canvas_item_editor->get_viewport_control()->update(); + } + + const PosVertex new_hover_point = closest_point(gpoint); + if (hover_point != new_hover_point) { + + hover_point = new_hover_point; + canvas_item_editor->get_viewport_control()->update(); } } } } - Ref<InputEventMouseMotion> mm = p_event; + Ref<InputEventKey> k = p_event; - if (mm.is_valid()) { + if (k.is_valid() && k->is_pressed() && (k->get_scancode() == KEY_DELETE || k->get_scancode() == KEY_BACKSPACE)) { + if (wip_active && selected_point.polygon == -1) { - if (edited_point != -1 && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) { + if (wip.size() > selected_point.vertex) { - Vector2 gpoint = mm->get_position(); - Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()))); - edited_point_pos = cpoint; + wip.remove(selected_point.vertex); + selected_point = wip.size() - 1; + canvas_item_editor->get_viewport_control()->update(); + return true; + } + } else { - if (!wip_active) { + const Vertex active_point = get_active_point(); - Vector<Vector2> vertices = _get_polygon(edited_polygon); - ERR_FAIL_INDEX_V(edited_point, vertices.size(), false); - vertices[edited_point] = cpoint - _get_offset(edited_polygon); - _set_polygon(edited_polygon, vertices); - } + if (active_point.valid()) { - canvas_item_editor->get_viewport_control()->update(); + remove_point(active_point); + return true; + } } } @@ -448,7 +446,10 @@ void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) { Control *vpc = canvas_item_editor->get_viewport_control(); Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); - Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); + Ref<Texture> default_handle = get_icon("EditorHandle", "EditorIcons"); + Ref<Texture> selected_handle = get_icon("EditorHandleSelected", "EditorIcons"); + + const Vertex active_point = get_active_point(); const int n_polygons = _get_polygon_count(); for (int j = -1; j < n_polygons; j++) { @@ -459,7 +460,7 @@ void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) { PoolVector<Vector2> points; Vector2 offset; - if (wip_active && j == edited_polygon) { + if (wip_active && j == edited_point.polygon) { points = Variant(wip); offset = Vector2(0, 0); @@ -471,7 +472,7 @@ void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) { offset = _get_offset(j); } - if (!wip_active && j == edited_polygon && edited_point >= 0 && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) { + if (!wip_active && j == edited_point.polygon && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) { const Color col = Color(0.5, 0.5, 0.5); // FIXME polygon->get_outline_color(); const int n = pre_move_edit.size(); @@ -493,10 +494,12 @@ void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) { for (int i = 0; i < n_points; i++) { + const Vertex vertex(j, i); + Vector2 p, p2; - p = (j == edited_polygon && i == edited_point) ? edited_point_pos : (points[i] + offset); - if (j == edited_polygon && ((wip_active && i == n_points - 1) || (((i + 1) % n_points) == edited_point))) - p2 = edited_point_pos; + p = (vertex == edited_point) ? edited_point.pos : (points[i] + offset); + if (j == edited_point.polygon && ((wip_active && i == n_points - 1) || (((i + 1) % n_points) == edited_point.vertex))) + p2 = edited_point.pos; else p2 = points[(i + 1) % n_points] + offset; @@ -504,9 +507,16 @@ void AbstractPolygon2DEditor::forward_draw_over_canvas(Control *p_canvas) { Vector2 next_point = xform.xform(p2); vpc->draw_line(point, next_point, col, 2); + Ref<Texture> handle = vertex == active_point ? selected_handle : default_handle; vpc->draw_texture(handle, point - handle->get_size() * 0.5); } } + + if (edge_point.valid()) { + + Ref<Texture> add_handle = get_icon("EditorHandleAdd", "EditorIcons"); + vpc->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5); + } } void AbstractPolygon2DEditor::edit(Node *p_polygon) { @@ -525,7 +535,9 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) { wip.clear(); wip_active = false; - edited_point = -1; + edited_point = PosVertex(); + hover_point = Vertex(); + selected_point = Vertex(); canvas_item_editor->get_viewport_control()->update(); @@ -542,6 +554,107 @@ void AbstractPolygon2DEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_create_resource"), &AbstractPolygon2DEditor::_create_resource); } +void AbstractPolygon2DEditor::remove_point(const Vertex &p_vertex) { + + PoolVector<Vector2> vertices = _get_polygon(p_vertex.polygon); + + if (vertices.size() > 3) { + + vertices.remove(p_vertex.vertex); + + undo_redo->create_action(TTR("Edit Poly (Remove Point)")); + _action_set_polygon(p_vertex.polygon, vertices); + _commit_action(); + } else { + + undo_redo->create_action(TTR("Remove Poly And Point")); + _action_remove_polygon(p_vertex.polygon); + _commit_action(); + } + + if (_is_empty()) + _menu_option(MODE_CREATE); + + hover_point = Vertex(); + if (selected_point == p_vertex) + selected_point = Vertex(); +} + +AbstractPolygon2DEditor::Vertex AbstractPolygon2DEditor::get_active_point() const { + + return hover_point.valid() ? hover_point : selected_point; +} + +AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_point(const Vector2 &p_pos) const { + + const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + + const int n_polygons = _get_polygon_count(); + const Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); + + PosVertex closest; + real_t closest_dist = 1e10; + + for (int j = 0; j < n_polygons; j++) { + + PoolVector<Vector2> points = _get_polygon(j); + const Vector2 offset = _get_offset(j); + const int n_points = points.size(); + + for (int i = 0; i < n_points; i++) { + + Vector2 cp = xform.xform(points[i] + offset); + + real_t d = cp.distance_to(p_pos); + if (d < closest_dist && d < grab_threshold) { + closest_dist = d; + closest = PosVertex(j, i, cp); + } + } + } + + return closest; +} + +AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_edge_point(const Vector2 &p_pos) const { + + const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + const real_t eps = grab_threshold * 2; + const real_t eps2 = eps * eps; + + const int n_polygons = _get_polygon_count(); + const Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); + + PosVertex closest; + real_t closest_dist = 1e10; + + for (int j = 0; j < n_polygons; j++) { + + PoolVector<Vector2> points = _get_polygon(j); + const Vector2 offset = _get_offset(j); + const int n_points = points.size(); + + for (int i = 0; i < n_points; i++) { + + Vector2 segment[2] = { xform.xform(points[i] + offset), + xform.xform(points[(i + 1) % n_points] + offset) }; + + Vector2 cp = Geometry::get_closest_point_to_segment_2d(p_pos, segment); + + if (cp.distance_squared_to(segment[0]) < eps2 || cp.distance_squared_to(segment[1]) < eps2) + continue; //not valid to reuse point + + real_t d = cp.distance_to(p_pos); + if (d < closest_dist && d < grab_threshold) { + closest_dist = d; + closest = PosVertex(j, i, cp); + } + } + } + + return closest; +} + AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive) { canvas_item_editor = NULL; @@ -549,9 +662,13 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wi undo_redo = editor->get_undo_redo(); wip_active = false; - edited_polygon = -1; + edited_point = PosVertex(); wip_destructive = p_wip_destructive; + hover_point = Vertex(); + selected_point = Vertex(); + edge_point = PosVertex(); + add_child(memnew(VSeparator)); button_create = memnew(ToolButton); add_child(button_create); diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index 3e3bff6d0d..8dd22958db 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -47,9 +47,33 @@ class AbstractPolygon2DEditor : public HBoxContainer { ToolButton *button_create; ToolButton *button_edit; - int edited_polygon; - int edited_point; - Vector2 edited_point_pos; + struct Vertex { + Vertex(); + Vertex(int p_vertex); + Vertex(int p_polygon, int p_vertex); + + bool operator==(const Vertex &p_vertex) const; + bool operator!=(const Vertex &p_vertex) const; + + bool valid() const; + + int polygon; + int vertex; + }; + + struct PosVertex : public Vertex { + PosVertex(); + PosVertex(const Vertex &p_vertex, const Vector2 &p_pos); + PosVertex(int p_polygon, int p_vertex, const Vector2 &p_pos); + + Vector2 pos; + }; + + PosVertex edited_point; + Vertex hover_point; // point under mouse cursor + Vertex selected_point; // currently selected + PosVertex edge_point; // adding an edge point? + Vector<Vector2> pre_move_edit; Vector<Vector2> wip; bool wip_active; @@ -80,6 +104,11 @@ protected: void _node_removed(Node *p_node); static void _bind_methods(); + void remove_point(const Vertex &p_vertex); + Vertex get_active_point() const; + PosVertex closest_point(const Vector2 &p_pos) const; + PosVertex closest_edge_point(const Vector2 &p_pos) const; + bool _is_empty() const; void _commit_action(); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 34c0a3d439..3807c8961a 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -248,7 +248,7 @@ void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, if (canvas_item && (!p_to_snap || p_current != p_to_snap)) { Transform2D ci_transform = canvas_item->get_global_transform_with_canvas(); Transform2D to_snap_transform = p_to_snap ? p_to_snap->get_global_transform_with_canvas() : Transform2D(); - if (fmod(ci_transform.get_rotation() - to_snap_transform.get_rotation(), 360.0) == 0.0) { + if (fmod(ci_transform.get_rotation() - to_snap_transform.get_rotation(), (real_t)360.0) == 0.0) { Point2 begin = ci_transform.xform(canvas_item->get_item_rect().get_position()); Point2 end = ci_transform.xform(canvas_item->get_item_rect().get_position() + canvas_item->get_item_rect().get_size()); @@ -318,7 +318,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const _snap_other_nodes(p_target, output, snapped, get_tree()->get_edited_scene_root(), p_canvas_item); } - if (((snap_active && snap_guides && (p_modes & SNAP_GUIDES)) || (p_forced_modes & SNAP_GUIDES)) && fmod(rotation, 360.0) == 0.0) { + if (((snap_active && snap_guides && (p_modes & SNAP_GUIDES)) || (p_forced_modes & SNAP_GUIDES)) && fmod(rotation, (real_t)360.0) == 0.0) { // Guides if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_"); @@ -335,7 +335,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const } } - if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && fmod(rotation, 360.0) == 0.0) { + if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && fmod(rotation, (real_t)360.0) == 0.0) { // Grid Point2 offset = grid_offset; if (snap_relative) { diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index b8274122f8..b3bb103577 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -365,13 +365,11 @@ void SpriteFramesEditor::_animation_name_edited() { } void SpriteFramesEditor::_animation_add() { - String new_name = "New Anim"; - - String name = new_name; + String name = "New Anim"; int counter = 0; while (frames->has_animation(name)) { counter++; - name = new_name + " " + itos(counter); + name = "New Anim " + itos(counter); } List<Node *> nodes; @@ -393,7 +391,7 @@ void SpriteFramesEditor::_animation_add() { undo_redo->add_undo_method(E->get(), "set_animation", current); } - edited_anim = new_name; + edited_anim = name; undo_redo->commit_action(); } diff --git a/methods.py b/methods.py index b62dfc6544..2f3dac7e42 100644 --- a/methods.py +++ b/methods.py @@ -1149,7 +1149,10 @@ def build_gles3_headers(target, source, env): build_legacygl_header(str(x), include="drivers/gles3/shader_gles3.h", class_suffix="GLES3", output_attribs=True) -def update_version(): +def add_module_version_string(self,s): + self.module_version_string+="."+s + +def update_version(module_version_string=""): rev = "custom_build" @@ -1167,6 +1170,7 @@ def update_version(): f.write("#define VERSION_PATCH " + str(version.patch) + "\n") f.write("#define VERSION_REVISION " + str(rev) + "\n") f.write("#define VERSION_STATUS " + str(version.status) + "\n") + f.write("#define VERSION_MODULE_CONFIG \"" + str(version.module_config) + module_version_string + "\"\n") import datetime f.write("#define VERSION_YEAR " + str(datetime.datetime.now().year) + "\n") f.close() diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp index b1327cdaef..28af93f942 100644 --- a/modules/gdnative/gdnative/basis.cpp +++ b/modules/gdnative/gdnative/basis.cpp @@ -172,7 +172,7 @@ void GDAPI godot_basis_new_with_euler_quat(godot_basis *r_dest, const godot_quat } // p_elements is a pointer to an array of 3 (!!) vector3 -void GDAPI godot_basis_get_elements(godot_basis *p_self, godot_vector3 *p_elements) { +void GDAPI godot_basis_get_elements(const godot_basis *p_self, godot_vector3 *p_elements) { const Basis *self = (const Basis *)p_self; Vector3 *elements = (Vector3 *)p_elements; elements[0] = self->elements[0]; diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 905c513d9d..619003083d 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -65,11 +65,20 @@ void GDAPI godot_string_new_unicode_data(godot_string *r_dest, const wchar_t *p_ void GDAPI godot_string_get_data(const godot_string *p_self, char *p_dest, int *p_size) { String *self = (String *)p_self; - if (p_size != NULL) { - *p_size = self->utf8().length(); - } - if (p_dest != NULL) { - memcpy(p_dest, self->utf8().get_data(), *p_size); + + if (p_size) { + // we have a length pointer, that means we either want to know + // the length or want to write *p_size bytes into a buffer + + CharString utf8_string = self->utf8(); + + int len = utf8_string.length(); + + if (p_dest) { + memcpy(p_dest, utf8_string.get_data(), *p_size); + } else { + *p_size = len; + } } } @@ -78,6 +87,11 @@ wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int return &(self->operator[](p_idx)); } +wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx) { + const String *self = (const String *)p_self; + return self->operator[](p_idx); +} + const char GDAPI *godot_string_c_str(const godot_string *p_self) { const String *self = (const String *)p_self; return self->utf8().get_data(); diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 3a59b9ca1c..3a92afd7ab 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -847,7 +847,7 @@ "name": "godot_basis_get_elements", "return_type": "void", "arguments": [ - ["godot_basis *", "p_self"], + ["const godot_basis *", "p_self"], ["godot_vector3 *", "p_elements"] ] }, @@ -3927,6 +3927,14 @@ ] }, { + "name": "godot_string_operator_index_const", + "return_type": "wchar_t", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_int", "p_idx"] + ] + }, + { "name": "godot_string_c_str", "return_type": "const char *", "arguments": [ diff --git a/modules/gdnative/include/gdnative/basis.h b/modules/gdnative/include/gdnative/basis.h index b86b1c17d8..49ca765a01 100644 --- a/modules/gdnative/include/gdnative/basis.h +++ b/modules/gdnative/include/gdnative/basis.h @@ -97,7 +97,7 @@ void GDAPI godot_basis_new(godot_basis *r_dest); void GDAPI godot_basis_new_with_euler_quat(godot_basis *r_dest, const godot_quat *p_euler); // p_elements is a pointer to an array of 3 (!!) vector3 -void GDAPI godot_basis_get_elements(godot_basis *p_self, godot_vector3 *p_elements); +void GDAPI godot_basis_get_elements(const godot_basis *p_self, godot_vector3 *p_elements); godot_vector3 GDAPI godot_basis_get_axis(const godot_basis *p_self, const godot_int p_axis); diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h index f30fdb8dc7..29510313c9 100644 --- a/modules/gdnative/include/gdnative/string.h +++ b/modules/gdnative/include/gdnative/string.h @@ -66,6 +66,7 @@ void GDAPI godot_string_new_unicode_data(godot_string *r_dest, const wchar_t *p_ void GDAPI godot_string_get_data(const godot_string *p_self, char *p_dest, int *p_size); wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx); +wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx); const char GDAPI *godot_string_c_str(const godot_string *p_self); const wchar_t GDAPI *godot_string_unicode_str(const godot_string *p_self); diff --git a/modules/mono/config.py b/modules/mono/config.py index 44eef45f76..7ad135e0b9 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -47,6 +47,7 @@ def copy_file_no_replace(src_dir, dst_dir, name): def configure(env): env.use_ptrcall = True + env.add_module_version_string("mono") envvars = Variables() envvars.Add(BoolVariable('mono_static', 'Statically link mono', False)) diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index 00d8a59f74..993a93ff89 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -47,8 +47,8 @@ def configure(env): if (env["target"].startswith("release")): env.Append(CPPFLAGS=['-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1']) - env.Append(CPPFLAGS=['-O2', '-flto', '-ftree-vectorize', '-fomit-frame-pointer', '-ffast-math', '-funsafe-math-optimizations']) - env.Append(LINKFLAGS=['-O2', '-flto']) + env.Append(CPPFLAGS=['-O2', '-ftree-vectorize', '-fomit-frame-pointer', '-ffast-math', '-funsafe-math-optimizations']) + env.Append(LINKFLAGS=['-O2']) if env["target"] == "release_debug": env.Append(CPPFLAGS=['-DDEBUG_ENABLED']) @@ -56,6 +56,10 @@ def configure(env): elif (env["target"] == "debug"): env.Append(CPPFLAGS=['-D_DEBUG', '-DDEBUG=1', '-gdwarf-2', '-O0', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) + if (env["use_lto"]): + env.Append(CPPFLAGS=['-flto']) + env.Append(LINKFLAGS=['-flto']) + ## Architecture if env["ios_sim"] or env["arch"] == "x86": # i386, simulator diff --git a/platform/windows/detect.py b/platform/windows/detect.py index bac5df5668..fbb02c9d1b 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -64,7 +64,6 @@ def get_opts(): return [ ('mingw_prefix_32', 'MinGW prefix (Win32)', mingw32), ('mingw_prefix_64', 'MinGW prefix (Win64)', mingw64), - BoolVariable('use_lto', 'Use link time optimization (when using MingW)', False), EnumVariable('debug_symbols', 'Add debug symbols to release version', 'yes', ('yes', 'no', 'full')), ] diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 56bc1d4c59..6bd0ac8317 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -52,7 +52,6 @@ def get_opts(): BoolVariable('use_static_cpp', 'Link stdc++ statically', False), BoolVariable('use_sanitizer', 'Use LLVM compiler address sanitizer', False), BoolVariable('use_leak_sanitizer', 'Use LLVM compiler memory leaks sanitizer (implies use_sanitizer)', False), - BoolVariable('use_lto', 'Use link time optimization', False), BoolVariable('pulseaudio', 'Detect & use pulseaudio', True), BoolVariable('udev', 'Use udev for gamepad connection callbacks', False), EnumVariable('debug_symbols', 'Add debug symbols to release version', 'yes', ('yes', 'no', 'full')), diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 0f631c69b6..80b7748078 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -202,7 +202,6 @@ void AnimationPlayer::_notification(int p_what) { if (!Engine::get_singleton()->is_editor_hint() && animation_set.has(autoplay)) { play(autoplay); - set_autoplay(""); //this line is the fix for autoplay issues with animatio _animation_process(0); } } break; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index ad519d8d0c..65a8350bd3 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1195,8 +1195,9 @@ void RichTextLabel::add_newline() { return; ItemNewline *item = memnew(ItemNewline); item->line = current_frame->lines.size(); - current_frame->lines.resize(current_frame->lines.size() + 1); _add_item(item, false); + current_frame->lines.resize(current_frame->lines.size() + 1); + _invalidate_current_line(current_frame); } bool RichTextLabel::remove_line(const int p_line) { diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 1e1e4f2d5f..672e893f1b 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -579,6 +579,7 @@ HTTPRequest::HTTPRequest() { client.instance(); use_threads = false; thread_done = false; + downloaded = 0; body_size_limit = -1; file = NULL; status = HTTPClient::STATUS_DISCONNECTED; diff --git a/version.py b/version.py index f0da206837..38847d68f5 100644 --- a/version.py +++ b/version.py @@ -3,3 +3,4 @@ name = "Godot Engine" major = 3 minor = 0 status = "alpha" +module_config = "" |